Version 2.3.1-dev.0.0

Merge commit '5b63d74608e64109d8ffbedb33930e7c4725f339' into dev
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..db0e7d7 100644
--- a/.packages
+++ b/.packages
@@ -59,6 +59,7 @@
 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
 oauth2:third_party/pkg/oauth2/lib
 observatory:runtime/observatory/lib
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 1c596d0..e2243c8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,68 +1,244 @@
-## 2.3.0-dev.0.5
+## 2.3.1-dev.0.0
 
-* Cherry-pick 347b72c260949fa96ec5a45f3d6b1e2388ea245a to dev
+### Core library changes
 
-## 2.3.0-dev.0.4
+#### `dart:async`
+* BREAKING CHANGE:
+  Fixes bug in `StreamIterator` which allowed constructor argument to be `null`.
+  Also allowed `await for` on a `null` stream. This is now a runtime error.
 
-* Cherry-pick d03323783a5a5a571916457fcf084d103fce86b3 to dev
-* Cherry-pick 14d09498b7830fba62816ec8db3ed9b58601b841 to dev
+#### `dart:core`
 
-## 2.3.0-dev.0.3
+* **Breaking change**: The `RegExp` interface has been extended with two new
+  constructor named parameters:
 
-* Cherry-pick 04e1b0d976151cc6aa5dcc80667d568c95495c80 to dev
+  * `unicode:` (`bool`, default: `false`), for Unicode patterns , and
+  * `dotAll:` (`bool`, default: `false`), to change the matching behavior of
+    '.' to also match line terminating characters.
 
-## 2.3.0-dev.0.2
+  Appropriate properties for these named parameters have also been added so
+  their use can be detected after construction.
 
-* Cherry-pick d8a0d68bd66b388e4c5f6dc38f4fd940a4cb88bc to dev
-* Cherry-pick 1ecedb23416943b13fd3f48a5d398f2cfa6dbee4 to dev
-* Cherry-pick 2c304d997f08e9ba1d8d1af665522b31d695f19a to dev
-* Cherry-pick 1f1592edce7122ff657d9538d58d9cce0cae46e6 to dev
-* Cherry-pick cf4444b803a376bb1ad6442e1f09434a4d58167b to dev
+  In addition, `RegExp` methods that originally returned `Match` objects
+  now return a more specific subtype, `RegExpMatch`, which adds two features:
 
-## 2.3.0-dev.0.1
+  * `Iterable<String> groupNames`, a property that contains the names of all
+    named capture groups, and
+  * `String namedGroup(String name)`: a method that retrieves the match for
+    the given named capture group
 
-* Cherry-pick 43eebea5a3715d7c3904cd85a35db5cffaae687e to dev
+  This change only affects implementers of the `RegExp` interface; current
+  code using Dart regular expressions will not be affected.
 
-## 2.3.0-dev.0.0
+#### `dart:isolate`
 
-### Tool Changes
+* BREAKING CHANGE: The `await for` allowed `null` as a stream due to a bug
+  in `StreamIterator` class. This bug has now been fixed.
 
-#### Linter
+## 2.3.0 - 2019-05-08
 
-The Linter was updated to `0.1.86` which includes the following change:
-* new lint: `prefer_inlined_adds`
+The focus in this release is on the new "UI-as-code" language features which
+make collections more expressive and declarative.
 
-## 2.2.1-dev.4.2
+### Language
 
-* Cherry-pick ab66a3808b28dfc94eaf0ed151c13f4fc696b5dc to dev
+Flutter is growing rapidly, which means many Dart users are building UI in code
+out of big deeply-nested expressions. Our goal with 2.3.0 was to [make that kind
+of code easier to write and maintain][ui-as-code]. Collection literals are a
+large component, so we focused on three features to make collections more
+powerful. We'll use list literals in the examples below, but these features also
+work in map and set literals.
 
-## 2.2.1-dev.4.1
+[ui-as-code]: https://medium.com/dartlang/making-dart-a-better-language-for-ui-f1ccaf9f546c
 
-* Cherry-pick 72b7e95c74b3ec0f0530322923713162a83013e2 to dev
+#### Spread
 
-## 2.2.1-dev.4.0
+Placing `...` before an expression inside a collection literal unpacks the
+result of the expression and inserts its elements directly inside the new
+collection. Where before you had to write something like this:
+
+```dart
+CupertinoPageScaffold(
+  child: ListView(children: [
+    Tab2Header()
+  ]..addAll(buildTab2Conversation())
+    ..add(buildFooter())),
+);
+```
+
+Now you can write this:
+
+```dart
+CupertinoPageScaffold(
+  child: ListView(children: [
+    Tab2Header(),
+    ...buildTab2Conversation(),
+    buildFooter()
+  ]),
+);
+```
+
+If you know the expression might evaluate to null and you want to treat that as
+equivalent to zero elements, you can use the null-aware spread `...?`.
+
+#### Collection if
+
+Sometimes you might want to include one or more elements in a collection only
+under certain conditions. If you're lucky, you can use a `?:` operator to
+selectively swap out a single element, but if you want to exchange more than one
+or omit elements, you are forced to write imperative code like this:
+
+```dart
+Widget build(BuildContext context) {
+  var children = [
+    IconButton(icon: Icon(Icons.menu)),
+    Expanded(child: title)
+  ];
+
+  if (isAndroid) {
+    children.add(IconButton(icon: Icon(Icons.search)));
+  }
+
+  return Row(children: children);
+}
+```
+
+We now allow `if` inside collection literals to conditionally omit or (with
+`else`) swap out an element:
+
+```dart
+Widget build(BuildContext context) {
+  return Row(
+    children: [
+      IconButton(icon: Icon(Icons.menu)),
+      Expanded(child: title),
+      if (isAndroid)
+        IconButton(icon: Icon(Icons.search)),
+    ],
+  );
+}
+```
+
+Unlike the existing `?:` operator, a collection `if` can be composed with
+spreads to conditionally include or omit multiple items:
+
+```dart
+Widget build(BuildContext context) {
+  return Row(
+    children: [
+      IconButton(icon: Icon(Icons.menu)),
+      if (isAndroid) ...[
+        Expanded(child: title),
+        IconButton(icon: Icon(Icons.search)),
+      ]
+    ],
+  );
+}
+```
+
+#### Collection for
+
+In many cases, the higher-order methods on Iterable give you a declarative way
+to modify a collection in the context of a single expression. But some
+operations, especially involving both transforming and filtering, can be
+cumbersome to express in a functional style.
+
+To solve this problem, you can use `for` inside a collection literal. Each
+iteration of the loop produces an element which is then inserted in the
+resulting collection. Consider the following code:
+
+```dart
+var command = [
+  engineDartPath,
+  frontendServer,
+  ...fileSystemRoots.map((root) => "--filesystem-root=$root"),
+  ...entryPoints
+      .where((entryPoint) => fileExists("lib/$entryPoint.json"))
+      .map((entryPoint) => "lib/$entryPoint"),
+  mainPath
+];
+```
+
+With a collection `for`, the code becomes simpler:
+
+```dart
+var command = [
+  engineDartPath,
+  frontendServer,
+  for (var root in fileSystemRoots) "--filesystem-root=$root",
+  for (var entryPoint in entryPoints)
+    if (fileExists("lib/$entryPoint.json")) "lib/$entryPoint",
+  mainPath
+];
+```
+
+As you can see, all three of these features can be freely composed. For full
+details of the changes, see [the official proposal][ui-as-code proposal].
+
+[ui-as-code proposal]: https://github.com/dart-lang/language/blob/master/accepted/future-releases/unified-collections/feature-specification.md
+
+**Note: These features are not currently supported in *const* collection
+literals. In a future release, we intend to relax this restriction and allow
+spread and collection `if` inside const collections.**
+
+### Core library changes
+
+#### `dart:isolate`
+
+*   Added `debugName` property to `Isolate`.
+*   Added `debugName` optional parameter to `Isolate.spawn` and
+    `Isolate.spawnUri`.
+
+#### `dart:core`
+
+*   RegExp patterns can now use lookbehind assertions.
+*   RegExp patterns can now use named capture groups and named backreferences.
+    Currently, named group matches can only be retrieved in Dart either by the
+    implicit index of the named group or by downcasting the returned Match
+    object to the type RegExpMatch. The RegExpMatch interface contains methods
+    for retrieving the available group names and retrieving a match by group
+    name.
 
 ### Dart VM
 
-* The VM service now requires an authentication code by default. This behavior
-  can be disabled by providing the `--disable-service-auth-codes` flag.
+*   The VM service now requires an authentication code by default. This behavior
+    can be disabled by providing the `--disable-service-auth-codes` flag.
 
-### Tool Changes
+*   Support for deprecated flags '-c' and '--checked' has been removed.
 
-#### Linter
+### Dart for the Web
 
-The Linter was updated to `0.1.85` which includes the following changes:
+#### dart2js
 
-* new lint: `prefer_inlined_adds`
-* new lint: `prefer_for_elements_to_map_fromIterable`
-* new lint: `prefer_if_elements_to_conditional_expressions`
-* new lint: `diagnostic_describe_all_properties`
+A binary format was added to dump-info. The old JSON format is still available
+and provided by default, but we are starting to deprecate it. The new binary
+format is more compact and cheaper to generate. On some large apps we tested, it
+was 4x faster to serialize and used 6x less memory.
 
-## 2.2.1-dev.3.1
+To use the binary format today, use `--dump-info=binary`, instead of
+`--dump-info`.
 
-* Cherry-pick 245576a096a2da54ef21d664d37d1f50f6f8dbb7 to dev
-* Cherry-pick a47b4ad2b8683cc8a82aa0ff89da2db7a3be27a3 to dev
-* Cherry-pick 9a2b222cba94126591b5d985a42d40c704a73c90 to dev
+What to expect next?
+
+*   The [visualizer tool][visualizer] will not be updated to support the new
+    binary format, but you can find several command-line tools at
+    `package:dart2js_info` that provide similar features to those in the
+    visualizer.
+
+*   The command-line tools in `package:dart2js_info` also work with the old JSON
+    format, so you can start using them even before you enable the new format.
+
+*   In a future release `--dump-info` will default to `--dump-info=binary`. At
+    that point, there will be an option to fallback to the JSON format, but the
+    visualizer tool will be deprecated.
+
+*   A release after that, the JSON format will no longer be available from
+    dart2js, but may be available from a command-line tool in
+    `package:dart2js_info`.
+
+[visualizer]: https://dart-lang.github.io/dump-info-visualizer/
+
+### Tools
 
 #### dartfmt
 
@@ -71,103 +247,35 @@
 *   Properly format trailing commas in assertions.
 *   Improve indentation of adjacent strings in argument lists.
 
-## 2.2.1-dev.3.0
-
-### Dart VM
-
-* Support for deprecated flags '-c' and '--checked' has been removed
-
-### Core library changes
-
-#### `dart:isolate`
-
-* Added `debugName` property to `Isolate`.
-* Added `debugName` optional parameter to `Isolate.spawn` and
-  `Isolate.spawnUri`.
-
-### Tool Changes
-
-#### dartfmt
-
-* Tweak set literal formatting to follow other collection literals.
-* Add support for "UI as code" features.
-
 #### Linter
 
-The Linter was updated to `0.1.83` which includes the following changes:
+The Linter was updated to `0.1.86`, which includes the following changes:
 
-* updated `file_names` to skip prefixed-extension Dart files (e.g., `.css.dart`, `.g.dart`)
-* miscellaneous rule documentation fixes
-* fixed NPE in `avoid_shadowing_type_parameters`
-* added linter version numbering for use in analyzer summaries
-* fixed type utilities to handle inheritance cycles
-* fixed `unnecessary_parenthesis` false positives
-
-## 2.2.1-dev.2.0
-
-## 2.2.1-dev.1.1
-
-* Cherry-pick 567d552de8ff93d704111467e7f3bf3b896ab684 to dev
-* Cherry-pick 4ca57befd707a0309e384472a566c084eef0e56e to dev
-
-## 2.2.1-dev.1.0
-
-* Support for deprecated flags '-c' and '--checked' has been removed
-* RegExp patterns can now use lookbehind assertions.
-* RegExp patterns can now use named capture groups and named backreferences.
-  Currently, named group matches can only be retrieved in Dart either by
-  the implicit index of the named group or by downcasting the returned Match
-  object to the type RegExpMatch. The RegExpMatch interface contains methods
-  for retrieving the available group names and retrieving a match by group name.
-
-### Tool Changes
+*   Added the following lints: `prefer_inlined_adds`,
+    `prefer_for_elements_to_map_fromIterable`,
+    `prefer_if_elements_to_conditional_expressions`,
+    `diagnostic_describe_all_properties`.
+*   Updated `file_names` to skip prefixed-extension Dart files (`.css.dart`,
+  `.g.dart`, etc.).
+*   Fixed false positives in `unnecessary_parenthesis`.
 
 #### Pub client
 
-* Added a CHANGELOG validator that complains if you `pub publish` without mentioning the current
-  version.
-* Removed validation of library names when doing `pub publish`.
-* Added support for `pub global activate`ing package from a custom pub URL.
-* Added subcommand: `pub logout`. Logs you out of the current session.
-* Fix: Use default server for `pub uploader` command.
+*   Added a CHANGELOG validator that complains if you `pub publish` without
+    mentioning the current version.
+*   Removed validation of library names when doing `pub publish`.
+*   Added support for `pub global activate`ing package from a custom pub URL.
+*   Added subcommand: `pub logout`. Logs you out of the current session.
 
-#### dart2js
+#### Dart native
 
-*  `--dump-info=binary`
+Initial support for compiling Dart apps to native machine code has been added.
+Two new tools have been added to the `bin` folder of the Dart SDK:
 
-   A binary format was added to dump-info. The old JSON format is still
-   available and provided by default, but we are starting to deprecate it.
+* `dart2aot`: AOT (ahead-of-time) compiles a Dart program to native
+machine code. The tool is supported on Windows, macOS, and Linux.
 
-   The new binary format is more compact and cheaper to generate.  On some large
-   apps we tested, it was 4x faster to serialize and used 6x less memory.
-
-   To use it today, use `--dump-info=binary`, instead of `--dump-info`.
-
-   What to expect next?
-   * The [visualizer tool][visualizer] will not be updated to support this new
-     format, but you can find several command-line tools at
-     `package:dart2js_info` that provide similar features to those in the
-     visualizer.
-
-   * The command-line tools in `package:dart2js_info` also work with the old
-     JSON format, so you can start using it even before you enable the new
-     format.
-
-   * In a future release `--dump-info` will default to `--dump-info=binary`. At
-     that point, there will be an option to fallback to the JSON format, but the
-     visualizer tool will be deprecated.
-
-   * A release after that, the JSON format will no longer be available from
-     dart2js, but may be availabe from a command-line tool in
-     `package:dart2js_info`.
-
-[visualizer]: https://dart-lang.github.io/dump-info-visualizer/
-
-## 2.2.1-dev.0.0
-
-* Cherry-pick 6f8415245d4dd298730facf83e03de69fc29bbd3 to dev
-* Cherry-pick e7d263b05f7f66d15f778df60ee60625e9a3c5f4 to dev
-* Cherry-pick dc8a56bc0ece296915c7016e0a8241c7068eca18 to dev
+* `dartaotruntime`: A small runtime used for executing an AOT compiled program.
 
 ## 2.2.0 - 2019-02-26
 
diff --git a/DEPS b/DEPS
index 0ad497f..208ee7a 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": "7bd9873fceb872aeb8c6ee69f14de7f7e7605e4e",
 
   # 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.
@@ -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.87",
   "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",
+  "protobuf_rev": "7d34c9e4e552a4f66acce32e4344ae27756a1949",
   "pub_rev": "8c363fe26f059c3063f1129adbb3c4e22a8ce954",
   "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",
@@ -210,6 +211,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 +320,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/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..baa7bc3 100644
--- a/build/config/compiler/BUILD.gn
+++ b/build/config/compiler/BUILD.gn
@@ -594,7 +594,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/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..c1d8eb8 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -2896,6 +2896,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>
@@ -3402,6 +3408,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).
@@ -5403,7 +5430,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></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_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>
 
 
 </body></html>
\ No newline at end of file
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/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index c60be02..4eb8f59 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -149,7 +149,9 @@
 
   ByteStore byteStore;
   nd.AnalysisDriverScheduler analysisDriverScheduler;
+
   DeclarationsTracker declarationsTracker;
+  DeclarationsTrackerData declarationsTrackerData;
 
   /// The controller for [onAnalysisSetChanged].
   final StreamController _onAnalysisSetChangedController =
@@ -202,13 +204,20 @@
       }
       _analysisPerformanceLogger = new PerformanceLog(sink);
     }
+
     byteStore = createByteStore(resourceProvider);
+
     analysisDriverScheduler = new nd.AnalysisDriverScheduler(
         _analysisPerformanceLogger,
         driverWatcher: pluginWatcher);
     analysisDriverScheduler.status.listen(sendStatusNotificationNew);
     analysisDriverScheduler.start();
 
+    declarationsTracker = DeclarationsTracker(byteStore, resourceProvider);
+    declarationsTrackerData = DeclarationsTrackerData(declarationsTracker);
+    analysisDriverScheduler.outOfBandWorker =
+        CompletionLibrariesWorker(declarationsTracker);
+
     contextManager = new ContextManagerImpl(
         resourceProvider,
         sdkManager,
@@ -276,27 +285,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() {}
 
@@ -389,10 +377,8 @@
   /// 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);
-    }
+    declarationsTracker.changeFile(path);
+    analysisDriverScheduler.notify(null);
   }
 
   /// Read all files, resolve all URIs, and perform required analysis in
@@ -513,7 +499,7 @@
   /// projects/contexts support.
   void setAnalysisRoots(String requestId, List<String> includedPaths,
       List<String> excludedPaths, Map<String, String> packageRoots) {
-    declarationsTracker?.discardContexts();
+    declarationsTracker.discardContexts();
     if (notificationManager != null) {
       notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
     }
@@ -702,11 +688,9 @@
   }
 
   void _addContextsToDeclarationsTracker() {
-    if (declarationsTracker != null) {
-      for (var driver in driverMap.values) {
-        declarationsTracker.addContext(driver.analysisContext);
-        driver.resetUriResolution();
-      }
+    for (var driver in driverMap.values) {
+      declarationsTracker.addContext(driver.analysisContext);
+      driver.resetUriResolution();
     }
   }
 
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..1dd0b83 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -107,7 +107,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/domain_analysis.dart b/pkg/analysis_server/lib/src/domain_analysis.dart
index 53a2d7f..e967188 100644
--- a/pkg/analysis_server/lib/src/domain_analysis.dart
+++ b/pkg/analysis_server/lib/src/domain_analysis.dart
@@ -513,7 +513,7 @@
   DartdocDirectiveInfo _getDartdocDirectiveInfoFor(ResolvedUnitResult result) {
     // TODO(brianwilkerson) Consider moving this to AnalysisServer.
     return server.declarationsTracker
-            ?.getContext(result.session.analysisContext)
+            .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..26461fc 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);
@@ -344,7 +356,7 @@
             request,
             'params.offset',
             'Expected offset between 0 and source length inclusive,'
-            ' but found $offset'));
+                ' but found $offset'));
         return;
       }
 
@@ -465,13 +477,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..bee0613 100644
--- a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -68,13 +68,14 @@
 
 /// 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();
 }
 
@@ -219,3 +220,55 @@
     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;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index dbbd2d4..99a39bd 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -810,7 +810,7 @@
           // try RENAME
           {
             RenameRefactoring renameRefactoring = new RenameRefactoring(
-                refactoringWorkspace, resolvedUnit.session, element);
+                refactoringWorkspace, resolvedUnit, element);
             if (renameRefactoring != null) {
               kinds.add(RefactoringKind.RENAME);
             }
@@ -1148,13 +1148,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 +1164,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/flutter/flutter_outline_computer.dart b/pkg/analysis_server/lib/src/flutter/flutter_outline_computer.dart
index 2df986e..277658d 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.
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..86c39e9 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_rename.dart
@@ -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();
@@ -95,8 +95,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
diff --git a/pkg/analysis_server/lib/src/nullability/conditional_discard.dart b/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
index 3e09ed4..dca55ce 100644
--- a/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
+++ b/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
@@ -3,7 +3,6 @@
 // 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.
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
index a723c9a..c6d9e80 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
@@ -6,6 +6,7 @@
 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_graph.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';
@@ -38,6 +39,8 @@
   /// Constraints gathered by the visitor are stored here.
   final Constraints _constraints;
 
+  final NullabilityGraph _graph;
+
   /// The file being analyzed.
   final Source _source;
 
@@ -78,8 +81,14 @@
   /// or expression.
   bool _inConditionalControlFlow = false;
 
-  ConstraintGatherer(TypeProvider typeProvider, this._variables,
-      this._constraints, this._source, this._permissive, this.assumptions)
+  ConstraintGatherer(
+      TypeProvider typeProvider,
+      this._variables,
+      this._constraints,
+      this._graph,
+      this._source,
+      this._permissive,
+      this.assumptions)
       : _notNullType =
             DecoratedType(typeProvider.objectType, NullabilityNode.never),
         _nonNullableBoolType =
@@ -206,8 +215,8 @@
     assert(_isSimple(elseType)); // TODO(paulberry)
     var overallType = DecoratedType(
         node.staticType,
-        NullabilityNode.forConditionalexpression(
-            node, thenType.node, elseType.node, _joinNullabilities));
+        NullabilityNode.forLUB(
+            node, thenType.node, elseType.node, _graph, _joinNullabilities));
     _variables.recordDecoratedExpressionType(node, overallType);
     return overallType;
   }
@@ -228,6 +237,7 @@
             null,
             _guards,
             _constraints,
+            _graph,
             false);
       } else {
         assert(assumptions.namedNoDefaultParameterHeuristic ==
@@ -432,10 +442,13 @@
     if (expression != null) {
       checkNotNull = CheckExpression(expression);
       _variables.recordExpressionChecks(
-          _source, expression, ExpressionChecks(checkNotNull));
+          _source,
+          expression,
+          ExpressionChecks(
+              expression.end, sourceType.node, destinationType.node, _guards));
     }
     NullabilityNode.recordAssignment(sourceType.node, destinationType.node,
-        checkNotNull, _guards, _constraints, _inConditionalControlFlow);
+        checkNotNull, _guards, _constraints, _graph, _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.
@@ -499,7 +512,7 @@
   /// 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) {
+      Expression node, ConstraintVariable a, ConstraintVariable b) {
     if (a == null) return b;
     if (b == null) return a;
     if (identical(a, ConstraintVariable.always) ||
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
index 8f5f170..adbae5e 100644
--- a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
+++ b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
@@ -7,7 +7,6 @@
 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';
@@ -64,6 +63,7 @@
     }
     decoratedType.node.trackPossiblyOptional();
     _variables.recordPossiblyOptional(_source, node, decoratedType.node);
+    return null;
   }
 
   @override
diff --git a/pkg/analysis_server/lib/src/nullability/expression_checks.dart b/pkg/analysis_server/lib/src/nullability/expression_checks.dart
index 14f47db..bc533d6 100644
--- a/pkg/analysis_server/lib/src/nullability/expression_checks.dart
+++ b/pkg/analysis_server/lib/src/nullability/expression_checks.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/src/nullability/nullability_node.dart';
 import 'package:analysis_server/src/nullability/transitional_api.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
@@ -13,16 +14,34 @@
 /// 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;
+  /// Source offset where a trailing `!` might need to be inserted.
+  final int offset;
 
-  ExpressionChecks(this.nullCheck);
+  /// 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 => !nullCheck.value;
+  bool get isEmpty {
+    for (var guard in guards) {
+      if (!guard.isNullable) return true;
+    }
+    return !valueNode.isNullable || contextNode.isNullable;
+  }
 
   @override
   Iterable<SourceEdit> get modifications =>
-      nullCheck.value ? [SourceEdit(nullCheck.offset, 0, '!')] : [];
+      isEmpty ? [] : [SourceEdit(offset, 0, '!')];
 }
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_graph.dart b/pkg/analysis_server/lib/src/nullability/nullability_graph.dart
new file mode 100644
index 0000000..bcc2300
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/nullability_graph.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 'package:analysis_server/src/nullability/nullability_node.dart';
+
+/// Data structure to keep track of the relationship between [NullabilityNode]
+/// objects.
+class NullabilityGraph {
+  /// Map from a nullability node to those 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 _downstream = Map<NullabilityNode, List<NullabilityNode>>.identity();
+
+  /// Map from a nullability node to those nodes that are "upstream" from it
+  /// (meaning that if a node in the value is nullable, then the corresponding
+  /// key node will have to be nullable, or null checks will have to be added).
+  final _upstream = Map<NullabilityNode, List<NullabilityNode>>.identity();
+
+  /// Records that [sourceNode] is immediately upstream from [destinationNode].
+  void connect(NullabilityNode sourceNode, NullabilityNode destinationNode) {
+    (_downstream[sourceNode] ??= []).add(destinationNode);
+    (_upstream[destinationNode] ??= []).add(sourceNode);
+  }
+
+  /// Iterates through all nodes that are "downstream" of [node] (i.e. if
+  /// [node] is nullable, then all the iterated nodes will either have to be
+  /// nullable, or null checks will have to be added).
+  ///
+  /// There is no guarantee of uniqueness of the iterated nodes.
+  Iterable<NullabilityNode> getDownstreamNodes(NullabilityNode node) =>
+      _downstream[node] ?? 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.
+  Iterable<NullabilityNode> getUpstreamNodes(NullabilityNode node) =>
+      _upstream[node] ?? const [];
+}
diff --git a/pkg/analysis_server/lib/src/nullability/nullability_node.dart b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
index fd7d82b..e871c28 100644
--- a/pkg/analysis_server/lib/src/nullability/nullability_node.dart
+++ b/pkg/analysis_server/lib/src/nullability/nullability_node.dart
@@ -3,6 +3,7 @@
 // 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/nullability_graph.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';
@@ -34,23 +35,6 @@
 
   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.
   ///
@@ -58,6 +42,22 @@
   /// inferred type rather than assuming `dynamic`.
   NullabilityNode.forInferredDynamicType() : this._(ConstraintVariable.always);
 
+  /// 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(
+      Expression conditionalExpression,
+      NullabilityNode a,
+      NullabilityNode b,
+      NullabilityGraph graph,
+      ConstraintVariable Function(
+              Expression, ConstraintVariable, ConstraintVariable)
+          joinNullabilities) = 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
@@ -69,10 +69,10 @@
   /// 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));
+  factory NullabilityNode.forSubstitution(
+      Constraints constraints,
+      NullabilityNode innerNode,
+      NullabilityNode outerNode) = NullabilityNodeForSubstitution._;
 
   /// Creates a [NullabilityNode] representing the nullability of a type
   /// annotation appearing explicitly in the user's program.
@@ -88,9 +88,12 @@
   /// Indicates whether this node is always nullable, by construction.
   bool get isAlwaysNullable => identical(nullable, ConstraintVariable.always);
 
+  /// Indicates whether this node is never nullable, by construction.
+  bool get isNeverNullable => nullable == null;
+
   /// 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;
+  bool get isNullable => nullable == null ? false : 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.
@@ -151,8 +154,10 @@
       CheckExpression checkNotNull,
       List<NullabilityNode> guards,
       Constraints constraints,
+      NullabilityGraph graph,
       bool inConditionalControlFlow) {
     var additionalConditions = <ConstraintVariable>[];
+    graph.connect(sourceNode, destinationNode);
     if (sourceNode.nullable != null) {
       additionalConditions.add(sourceNode.nullable);
       var destinationNonNullIntent = destinationNode.nonNullIntent;
@@ -199,3 +204,47 @@
     constraints.record(conditions, consequence);
   }
 }
+
+/// Derived class for nullability nodes that arise from the least-upper-bound
+/// implied by a conditional expression.
+class NullabilityNodeForLUB extends NullabilityNode {
+  final NullabilityNode left;
+
+  final NullabilityNode right;
+
+  NullabilityNodeForLUB._(
+      Expression expression,
+      this.left,
+      this.right,
+      NullabilityGraph graph,
+      ConstraintVariable Function(
+              ConditionalExpression, ConstraintVariable, ConstraintVariable)
+          joinNullabilities)
+      : super._(joinNullabilities(expression, left.nullable, right.nullable)) {
+    graph.connect(left, this);
+    graph.connect(right, this);
+  }
+}
+
+/// Derived class for nullability nodes that arise from type variable
+/// substitution.
+class NullabilityNodeForSubstitution extends NullabilityNode {
+  /// 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._(
+      Constraints constraints, this.innerNode, this.outerNode)
+      : super._(ConstraintVariable.or(
+            constraints, innerNode?.nullable, outerNode.nullable));
+}
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
index 7a1b505..ac1d8df 100644
--- a/pkg/analysis_server/lib/src/nullability/transitional_api.dart
+++ b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
@@ -7,6 +7,7 @@
 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_graph.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';
@@ -149,6 +150,8 @@
 
   final _constraints = Solver();
 
+  final _graph = NullabilityGraph();
+
   /// Prepares to perform nullability migration.
   ///
   /// If [permissive] is `true`, exception handling logic will try to proceed
@@ -172,7 +175,7 @@
 
   void processInput(CompilationUnit unit, TypeProvider typeProvider) {
     unit.accept(ConstraintGatherer(typeProvider, _variables, _constraints,
-        unit.declaredElement.source, _permissive, assumptions));
+        _graph, unit.declaredElement.source, _permissive, assumptions));
   }
 }
 
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/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/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..50ac2ac 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -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(
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..6539550 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].
@@ -1009,7 +1009,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;
             }
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..dc43fd4 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -196,7 +196,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 +1747,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 +2343,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) {
@@ -3908,7 +3910,7 @@
     // Prepare the last required parameter.
     FormalParameter lastRequiredParameter;
     for (FormalParameter parameter in parameters) {
-      if (parameter.isRequired) {
+      if (parameter.isRequiredPositional) {
         lastRequiredParameter = parameter;
       }
     }
@@ -4692,7 +4694,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/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..b803440 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;
   }
 
@@ -456,3 +476,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/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/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/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..6331b59 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -33,7 +33,7 @@
 - [ ] completion.availableSuggestions
 - [ ] 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/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index ec50cf1..23e34a7 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
         }));
 
@@ -387,6 +389,17 @@
     optionalFields: {"location": isLocation}));
 
 /**
+ * DiagnosticMessage
+ *
+ * {
+ *   "message": String
+ *   "location": Location
+ * }
+ */
+final Matcher isDiagnosticMessage = new LazyMatcher(() => new MatchesJsonObject(
+    "DiagnosticMessage", {"message": isString, "location": isLocation}));
+
+/**
  * Element
  *
  * {
diff --git a/pkg/analysis_server/test/protocol_server_test.dart b/pkg/analysis_server/test/protocol_server_test.dart
index 7b66304..b83902c 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';
 
@@ -263,6 +264,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 {
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/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/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
index c3b1915..61c133d 100644
--- a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
+++ b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
@@ -7,11 +7,11 @@
 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_graph.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';
@@ -32,6 +32,30 @@
   @override
   final _Constraints constraints = _Constraints();
 
+  @override
+  final graph = NullabilityGraph();
+
+  void assertConditional(
+      NullabilityNode node, NullabilityNode left, NullabilityNode right) {
+    var conditionalNode = node as NullabilityNodeForLUB;
+    expect(conditionalNode.left, same(left));
+    expect(conditionalNode.right, same(right));
+    if (left.isNeverNullable) {
+      if (right.isNeverNullable) {
+        expect(conditionalNode.isNeverNullable, true);
+      } else {
+        expect(conditionalNode.nullable, same(right.nullable));
+      }
+    } else {
+      if (right.isNeverNullable) {
+        expect(conditionalNode.nullable, same(left.nullable));
+      } else {
+        assertConstraint([left.nullable], conditionalNode.nullable);
+        assertConstraint([right.nullable], conditionalNode.nullable);
+      }
+    }
+  }
+
   /// Checks that a constraint was recorded with a left hand side of
   /// [conditions] and a right hand side of [consequence].
   void assertConstraint(
@@ -57,6 +81,36 @@
     }
   }
 
+  /// Checks that there are no nullability nodes upstream from [node] that could
+  /// cause it to become nullable.
+  void assertNoUpstreamNullability(NullabilityNode node) {
+    for (var upstreamNode in graph.getUpstreamNodes(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.
@@ -95,8 +149,8 @@
 int f(int i, int j) => i + j;
 ''');
 
-    assertConstraint([decoratedTypeAnnotation('int i').node.nullable],
-        checkExpression('i +').nullCheck);
+    assertNullCheck(
+        checkExpression('i +'), decoratedTypeAnnotation('int i').node);
   }
 
   test_binaryExpression_add_left_check_custom() async {
@@ -107,8 +161,8 @@
 Int f(Int i, Int j) => i + j;
 ''');
 
-    assertConstraint([decoratedTypeAnnotation('Int i').node.nullable],
-        checkExpression('i +').nullCheck);
+    assertNullCheck(
+        checkExpression('i +'), decoratedTypeAnnotation('Int i').node);
   }
 
   test_binaryExpression_add_result_custom() async {
@@ -119,10 +173,9 @@
 Int f(Int i, Int j) => (i + j);
 ''');
 
-    assertConstraint(
-        [decoratedTypeAnnotation('Int operator+').node.nullable],
-        _either(decoratedTypeAnnotation('Int f').node.nullable,
-            checkExpression('(i + j)').nullCheck));
+    assertNullCheck(checkExpression('(i + j)'),
+        decoratedTypeAnnotation('Int operator+').node,
+        contextNode: decoratedTypeAnnotation('Int f').node);
   }
 
   test_binaryExpression_add_result_not_null() async {
@@ -130,7 +183,7 @@
 int f(int i, int j) => i + j;
 ''');
 
-    assertNoConstraints(decoratedTypeAnnotation('int f').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int f').node);
   }
 
   test_binaryExpression_add_right_check() async {
@@ -138,8 +191,8 @@
 int f(int i, int j) => i + j;
 ''');
 
-    assertConstraint([decoratedTypeAnnotation('int j').node.nullable],
-        checkExpression('j;').nullCheck);
+    assertNullCheck(
+        checkExpression('j;'), decoratedTypeAnnotation('int j').node);
   }
 
   test_binaryExpression_add_right_check_custom() async {
@@ -150,10 +203,9 @@
 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));
+    assertNullCheck(
+        checkExpression('j/*check*/'), decoratedTypeAnnotation('Int j').node,
+        contextNode: decoratedTypeAnnotation('Int other').node);
   }
 
   test_binaryExpression_equal() async {
@@ -161,7 +213,7 @@
 bool f(int i, int j) => i == j;
 ''');
 
-    assertNoConstraints(decoratedTypeAnnotation('bool f').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool f').node);
   }
 
   test_boolLiteral() async {
@@ -170,7 +222,7 @@
   return true;
 }
 ''');
-    assertNoConstraints(decoratedTypeAnnotation('bool').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('bool').node);
   }
 
   test_conditionalExpression_condition_check() async {
@@ -180,9 +232,9 @@
 }
 ''');
 
-    var nullable_b = decoratedTypeAnnotation('bool b').node.nullable;
-    var check_b = checkExpression('b ?').nullCheck;
-    assertConstraint([nullable_b], check_b);
+    var nullable_b = decoratedTypeAnnotation('bool b').node;
+    var check_b = checkExpression('b ?');
+    assertNullCheck(check_b, nullable_b);
   }
 
   test_conditionalExpression_general() async {
@@ -192,16 +244,13 @@
 }
 ''');
 
-    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));
+    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 {
@@ -211,9 +260,12 @@
 }
 ''');
 
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(nullable_i));
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional =
+        decoratedExpressionType('(b ?').node as NullabilityNodeForLUB;
+    var nullable_throw = nullable_conditional.left;
+    expect(nullable_throw.isNeverNullable, true);
+    assertConditional(nullable_conditional, nullable_throw, nullable_i);
   }
 
   test_conditionalExpression_left_null() async {
@@ -223,8 +275,8 @@
 }
 ''');
 
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(ConstraintVariable.always));
+    var nullable_conditional = decoratedExpressionType('(b ?').node;
+    expect(nullable_conditional.isAlwaysNullable, true);
   }
 
   test_conditionalExpression_right_non_null() async {
@@ -234,9 +286,12 @@
 }
 ''');
 
-    var nullable_i = decoratedTypeAnnotation('int i').node.nullable;
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(nullable_i));
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_conditional =
+        decoratedExpressionType('(b ?').node as NullabilityNodeForLUB;
+    var nullable_throw = nullable_conditional.right;
+    expect(nullable_throw.isNeverNullable, true);
+    assertConditional(nullable_conditional, nullable_i, nullable_throw);
   }
 
   test_conditionalExpression_right_null() async {
@@ -246,8 +301,8 @@
 }
 ''');
 
-    var nullable_conditional = decoratedExpressionType('(b ?').node.nullable;
-    expect(nullable_conditional, same(ConstraintVariable.always));
+    var nullable_conditional = decoratedExpressionType('(b ?').node;
+    expect(nullable_conditional.isAlwaysNullable, true);
   }
 
   test_functionDeclaration_expression_body() async {
@@ -255,10 +310,9 @@
 int/*1*/ f(int/*2*/ i) => i/*3*/;
 ''');
 
-    assertConstraint(
-        [decoratedTypeAnnotation('int/*2*/').node.nullable],
-        _either(decoratedTypeAnnotation('int/*1*/').node.nullable,
-            checkExpression('i/*3*/').nullCheck));
+    assertNullCheck(
+        checkExpression('i/*3*/'), decoratedTypeAnnotation('int/*2*/').node,
+        contextNode: decoratedTypeAnnotation('int/*1*/').node);
   }
 
   test_functionDeclaration_parameter_named_default_notNull() async {
@@ -266,7 +320,7 @@
 void f({int i = 1}) {}
 ''');
 
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_functionDeclaration_parameter_named_default_null() async {
@@ -298,7 +352,7 @@
             namedNoDefaultParameterHeuristic:
                 NamedNoDefaultParameterHeuristic.assumeRequired));
 
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_functionDeclaration_parameter_named_no_default_required_assume_nullable() async {
@@ -311,7 +365,7 @@
             namedNoDefaultParameterHeuristic:
                 NamedNoDefaultParameterHeuristic.assumeNullable));
 
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_functionDeclaration_parameter_named_no_default_required_assume_required() async {
@@ -324,7 +378,7 @@
             namedNoDefaultParameterHeuristic:
                 NamedNoDefaultParameterHeuristic.assumeRequired));
 
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_functionDeclaration_parameter_positionalOptional_default_notNull() async {
@@ -332,7 +386,7 @@
 void f([int i = 1]) {}
 ''');
 
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_functionDeclaration_parameter_positionalOptional_default_null() async {
@@ -394,10 +448,7 @@
     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);
+    assertNullCheck(i_3, int_2.node, contextNode: int_1.node);
     assertConstraint([int_1.node.nonNullIntent], int_2.node.nonNullIntent);
   }
 
@@ -408,10 +459,10 @@
   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));
+    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 {
@@ -438,8 +489,8 @@
     // 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);
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    assertNoUpstreamNullability(nullable_i);
   }
 
   test_functionInvocation_parameter_null() async {
@@ -450,10 +501,8 @@
 }
 ''');
 
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('null').nullCheck));
+    assertNullCheck(checkExpression('null'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
   }
 
   test_functionInvocation_return() async {
@@ -464,10 +513,9 @@
 }
 ''');
 
-    assertConstraint(
-        [decoratedTypeAnnotation('int/*1*/').node.nullable],
-        _either(decoratedTypeAnnotation('int/*2*/').node.nullable,
-            checkExpression('(f())').nullCheck));
+    assertNullCheck(
+        checkExpression('(f())'), decoratedTypeAnnotation('int/*1*/').node,
+        contextNode: decoratedTypeAnnotation('int/*2*/').node);
   }
 
   test_if_condition() async {
@@ -477,8 +525,8 @@
 }
 ''');
 
-    assertConstraint([(decoratedTypeAnnotation('bool b').node.nullable)],
-        checkExpression('b) {}').nullCheck);
+    assertNullCheck(
+        checkExpression('b) {}'), decoratedTypeAnnotation('bool b').node);
   }
 
   test_if_conditional_control_flow_after() async {
@@ -519,16 +567,16 @@
   }
 }
 ''');
-    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 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.nullable, same(nullable_i));
+    expect(discard.trueGuard, same(nullable_i));
     expect(discard.falseGuard, null);
     expect(discard.pureCondition, true);
   }
@@ -544,13 +592,13 @@
 }
 ''');
 
-    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));
+    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 {
@@ -563,10 +611,10 @@
 }
 ''');
 
-    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));
+    var nullable_i = decoratedTypeAnnotation('int i').node;
+    var nullable_return = decoratedTypeAnnotation('int f').node;
+    assertNullCheck(checkExpression('i/*check*/'), nullable_i,
+        contextNode: nullable_return);
   }
 
   test_intLiteral() async {
@@ -575,7 +623,7 @@
   return 0;
 }
 ''');
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_methodDeclaration_resets_unconditional_control_flow() async {
@@ -606,15 +654,16 @@
 }
 ''');
 
-    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));
+    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 {
@@ -628,10 +677,9 @@
 
     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));
+    assertNullCheck(checkExpression('c/*check*/'),
+        decoratedTypeAnnotation('C<int/*3*/>/*4*/').node,
+        contextNode: decoratedTypeAnnotation('C<int/*1*/>/*2*/').node);
   }
 
   test_methodInvocation_parameter_named() async {
@@ -643,10 +691,10 @@
   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));
+    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_target_check() async {
@@ -659,8 +707,8 @@
 }
 ''');
 
-    assertConstraint([decoratedTypeAnnotation('C c').node.nullable],
-        checkExpression('c.m').nullCheck);
+    assertNullCheck(
+        checkExpression('c.m'), decoratedTypeAnnotation('C c').node);
   }
 
   test_methodInvocation_target_demonstrates_non_null_intent() async {
@@ -683,10 +731,8 @@
 }
 ''');
 
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('(null)').nullCheck));
+    assertNullCheck(checkExpression('(null)'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
   }
 
   test_return_implicit_null() async {
@@ -708,10 +754,8 @@
 }
 ''');
 
-    assertConstraint(
-        [ConstraintVariable.always],
-        _either(decoratedTypeAnnotation('int').node.nullable,
-            checkExpression('null').nullCheck));
+    assertNullCheck(checkExpression('null'), NullabilityNode.always,
+        contextNode: decoratedTypeAnnotation('int').node);
   }
 
   test_stringLiteral() async {
@@ -721,7 +765,7 @@
   return 'x';
 }
 ''');
-    assertNoConstraints(decoratedTypeAnnotation('String').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('String').node);
   }
 
   test_thisExpression() async {
@@ -731,7 +775,7 @@
 }
 ''');
 
-    assertNoConstraints(decoratedTypeAnnotation('C f').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('C f').node);
   }
 
   test_throwExpression() async {
@@ -740,7 +784,7 @@
   return throw null;
 }
 ''');
-    assertNoConstraints(decoratedTypeAnnotation('int').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('int').node);
   }
 
   test_typeName() async {
@@ -749,20 +793,15 @@
   return int;
 }
 ''');
-    assertNoConstraints(decoratedTypeAnnotation('Type').node.nullable);
+    assertNoUpstreamNullability(decoratedTypeAnnotation('Type').node);
   }
-
-  /// 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;
 
+  NullabilityGraph get graph;
+
   /// Analyzes the given source code, producing constraint variables and
   /// constraints for it.
   @override
@@ -770,8 +809,8 @@
       {NullabilityMigrationAssumptions assumptions:
           const NullabilityMigrationAssumptions()}) async {
     var unit = await super.analyze(code);
-    unit.accept(ConstraintGatherer(
-        typeProvider, _variables, constraints, testSource, false, assumptions));
+    unit.accept(ConstraintGatherer(typeProvider, _variables, constraints, graph,
+        testSource, false, assumptions));
     return unit;
   }
 }
@@ -784,7 +823,10 @@
       _variables.decoratedElementType(
           findNode.functionDeclaration(search).declaredElement);
 
+  @failingTest
   test_interfaceType_nullable() async {
+    // The tests are now being run without enabling nnbd, which causes the '?'
+    // to be reported as an error.
     await analyze('''
 void f(int? x) {}
 ''');
@@ -924,12 +966,6 @@
         .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) {
@@ -983,13 +1019,6 @@
   }
 }
 
-/// 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>{};
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/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/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/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/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index e30b6cf..19b5b21 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,27 @@
+## 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/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..6841054
--- /dev/null
+++ b/pkg/analyzer/lib/dart/analysis/features.dart
@@ -0,0 +1,89 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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 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/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index bce36d6..8747ace 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
@@ -1223,6 +1224,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;
 
@@ -2289,15 +2301,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 +2321,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;
@@ -3447,6 +3471,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.
@@ -5227,6 +5260,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 +5276,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 +5293,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 +5305,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..815ad03 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(
@@ -907,6 +926,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 +935,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/element/element.dart b/pkg/analyzer/lib/dart/element/element.dart
index 20b425d..fb66964 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
@@ -1051,13 +1054,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;
@@ -1333,12 +1329,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 +1400,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 +1417,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 +1437,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 +1545,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..ce67ab7 100644
--- a/pkg/analyzer/lib/dart/element/type.dart
+++ b/pkg/analyzer/lib/dart/element/type.dart
@@ -80,6 +80,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..8cadd5f 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,
@@ -346,6 +353,8 @@
   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 +392,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,
@@ -743,7 +753,7 @@
  *
  * See [AnalysisErrorListener].
  */
-class AnalysisError {
+class AnalysisError implements Diagnostic {
   /**
    * An empty array of errors used when no errors are expected.
    */
@@ -781,10 +791,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 +807,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 +850,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 +929,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 +952,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/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/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 463a9db..2098c3f 100644
--- a/pkg/analyzer/lib/src/dart/analysis/driver.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/driver.dart
@@ -94,7 +94,7 @@
   /**
    * The version of data format, should be incremented on every format change.
    */
-  static const int DATA_VERSION = 79;
+  static const int DATA_VERSION = 80;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
@@ -103,6 +103,11 @@
   static int allowedNumberOfContextsToWrite = 10;
 
   /**
+   * Whether summary2 should be used to resynthesize elements.
+   */
+  static final bool useSummary2 = false;
+
+  /**
    * The scheduler that schedules analysis work in this, and possibly other
    * analysis drivers.
    */
@@ -740,12 +745,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);
     }
@@ -1432,6 +1443,7 @@
             libraryContext.isLibraryUri,
             libraryContext.analysisContext,
             libraryContext.resynthesizer,
+            libraryContext.elementFactory,
             libraryContext.inheritanceManager,
             library,
             _resourceProvider);
@@ -1500,6 +1512,7 @@
           libraryContext.isLibraryUri,
           libraryContext.analysisContext,
           libraryContext.resynthesizer,
+          libraryContext.elementFactory,
           libraryContext.inheritanceManager,
           library,
           _resourceProvider);
@@ -1594,6 +1607,7 @@
       _unlinkedSalt,
       _linkedSalt,
       externalSummaries: _externalSummaries,
+      useSummary2: useSummary2,
     );
     _fileTracker = new FileTracker(_logger, _fsState, _changeHook);
   }
@@ -1608,7 +1622,7 @@
       }
     }
 
-    if (_libraryContext == null) {
+    if (_libraryContext == null || useSummary2) {
       _libraryContext = new LibraryContext(
         session: currentSession,
         logger: _logger,
@@ -1619,6 +1633,7 @@
         sourceFactory: _sourceFactory,
         externalSummaries: _externalSummaries,
         targetLibrary: library,
+        useSummary2: useSummary2,
       );
     } else {
       _libraryContext.load(library);
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 54978bd..2cfdf21 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
@@ -62,59 +52,83 @@
   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,
+      'Q4 2018 Constant Update');
+
+  static const non_nullable = const ExperimentalFeature(
+      1,
+      EnableString.non_nullable,
+      IsEnabledByDefault.non_nullable,
+      IsExpired.non_nullable,
+      'Non Nullable');
+
+  static const control_flow_collections = const ExperimentalFeature(
+      2,
+      EnableString.control_flow_collections,
+      IsEnabledByDefault.control_flow_collections,
+      IsExpired.control_flow_collections,
+      'Control Flow Collections',
+      firstSupportedVersion: '2.2.2');
+
+  static const spread_collections = const ExperimentalFeature(
+      3,
+      EnableString.spread_collections,
+      IsEnabledByDefault.spread_collections,
+      IsExpired.spread_collections,
+      'Spread Collections',
+      firstSupportedVersion: '2.2.2');
+
+  static const set_literals = const ExperimentalFeature(
+      4,
+      EnableString.set_literals,
+      IsEnabledByDefault.set_literals,
+      IsExpired.set_literals,
+      'Set Literals',
+      firstSupportedVersion: '2.2.0');
+
+  static const triple_shift = const ExperimentalFeature(
+      5,
+      EnableString.triple_shift,
+      IsEnabledByDefault.triple_shift,
+      IsExpired.triple_shift,
+      'Triple-shift operator');
+
+  static const bogus_disabled = const ExperimentalFeature(
+      6,
+      EnableString.bogus_disabled,
+      IsEnabledByDefault.bogus_disabled,
+      IsExpired.bogus_disabled,
+      null);
+
+  static const bogus_enabled = const ExperimentalFeature(
+      7,
+      EnableString.bogus_enabled,
+      IsEnabledByDefault.bogus_enabled,
+      IsExpired.bogus_enabled,
+      null,
+      firstSupportedVersion: '1.0.0');
+}
+
 /// A representation of the set of experiments that are active and whether they
 /// are enabled.
-class ExperimentStatus {
+class ExperimentStatus 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),
+    EnableString.constant_update_2018:
+        ExperimentalFeatures.constant_update_2018,
+    EnableString.non_nullable: ExperimentalFeatures.non_nullable,
+    EnableString.control_flow_collections:
+        ExperimentalFeatures.control_flow_collections,
+    EnableString.spread_collections: ExperimentalFeatures.spread_collections,
+    EnableString.set_literals: ExperimentalFeatures.set_literals,
+    EnableString.triple_shift: ExperimentalFeatures.triple_shift,
+    EnableString.bogus_disabled: ExperimentalFeatures.bogus_disabled,
+    EnableString.bogus_enabled: ExperimentalFeatures.bogus_enabled,
   };
 
   final List<bool> _enableFlags;
@@ -131,9 +145,25 @@
       : _enableFlags = <bool>[
           constant_update_2018 ?? IsEnabledByDefault.constant_update_2018,
           non_nullable ?? IsEnabledByDefault.non_nullable,
+          true, // control-flow-collections
+          true, // spread-collections
+          true, // set-literals
           triple_shift ?? IsEnabledByDefault.triple_shift,
+          false, // bogus-disabled
+          true, // bogus-enabled
         ];
 
+  /// 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,34 +174,65 @@
 
   ExperimentStatus._(this._enableFlags);
 
-  /// Hardcoded state for the expired flag "bogus_disabled"
-  bool get bogus_disabled => false;
+  /// Current state for the flag "bogus_disabled"
+  bool get bogus_disabled => isEnabled(ExperimentalFeatures.bogus_disabled);
 
-  /// Hardcoded state for the expired flag "bogus_enabled"
-  bool get bogus_enabled => true;
+  /// 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 => _enableFlags[0];
+  bool get constant_update_2018 =>
+      isEnabled(ExperimentalFeatures.constant_update_2018);
 
   /// Current state for the flag "control_flow_collections"
-  bool get control_flow_collections => true;
+  bool get control_flow_collections =>
+      isEnabled(ExperimentalFeatures.control_flow_collections);
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    for (var flag in _enableFlags) {
+      hash = JenkinsSmiHash.combine(hash, flag.hashCode);
+    }
+    return JenkinsSmiHash.finish(hash);
+  }
 
   /// Current state for the flag "non-nullable"
-  bool get non_nullable => _enableFlags[1];
+  bool get non_nullable => isEnabled(ExperimentalFeatures.non_nullable);
 
   /// Current state for the flag "set-literals"
-  bool get set_literals => true;
+  bool get set_literals => isEnabled(ExperimentalFeatures.set_literals);
 
   /// Current state for the flag "spread_collections"
-  bool get spread_collections => true;
+  bool get spread_collections =>
+      isEnabled(ExperimentalFeatures.spread_collections);
 
   /// Current state for the flag "triple_shift"
-  bool get triple_shift => _enableFlags[2];
+  bool get triple_shift => isEnabled(ExperimentalFeatures.triple_shift);
+
+  @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].
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..7c8377e 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,7 +13,6 @@
 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';
@@ -118,6 +118,7 @@
   String _unlinkedKey;
   AnalysisDriverUnlinkedUnit _driverUnlinkedUnit;
   UnlinkedUnit _unlinked;
+  UnlinkedUnit2 _unlinked2;
   List<int> _apiSignature;
 
   List<FileState> _importedFiles;
@@ -244,6 +245,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;
   }
 
@@ -434,7 +438,8 @@
         return _parse(errorListener);
       });
     } catch (_) {
-      return _createEmptyCompilationUnit();
+      AnalysisOptionsImpl analysisOptions = _fsState._analysisOptions;
+      return _createEmptyCompilationUnit(analysisOptions.contextFeatures);
     }
   }
 
@@ -449,6 +454,10 @@
    * Return `true` if the API signature changed since the last refresh.
    */
   bool refresh({bool allowCached: false}) {
+    if (_fsState.useSummary2) {
+      return _refresh2();
+    }
+
     _invalidateCurrentUnresolvedData();
 
     {
@@ -578,7 +587,7 @@
   }
 
   @override
-  String toString() => path;
+  String toString() => path ?? '<unresolved>';
 
   /**
    * Compute the full or partial map of exported declarations for this library.
@@ -643,9 +652,10 @@
     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]);
   }
 
@@ -688,28 +698,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();
     });
     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 +729,168 @@
     return unit;
   }
 
+  bool _refresh2() {
+    _invalidateCurrentUnresolvedData();
+
+    {
+      var rawFileState = _fsState._fileContentCache.get(path, false);
+      _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(contentSignature, 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();
+        }
+      }
+
+      for (FileState file in _fsState._uriToFile.values) {
+        file._exportedTopLevelDeclarations = null;
+      }
+    }
+
+    // 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);
+    }
+
+    // Return whether the API signature changed.
+    return apiSignatureChanged;
+  }
+
+  static UnlinkedUnit2Builder serializeAstUnlinked2(
+      List<int> contentSignature, 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;
+      }
+    }
+    return UnlinkedUnit2Builder(
+      apiSignature: contentSignature,
+      exports: exports,
+      imports: imports,
+      parts: parts,
+      hasLibraryDirective: hasLibraryDirective,
+      hasPartOfDirective: hasPartOfDirective,
+      lineStarts: unit.lineInfo.lineStarts,
+    );
+  }
+
   /**
    * Return `true` if the given byte lists are equal.
    */
@@ -762,6 +933,7 @@
   final AnalysisOptions _analysisOptions;
   final Uint32List _unlinkedSalt;
   final Uint32List _linkedSalt;
+  final bool useSummary2;
 
   /**
    * The optional store with externally provided unlinked and corresponding
@@ -842,6 +1014,7 @@
     this._unlinkedSalt,
     this._linkedSalt, {
     this.externalSummaries,
+    this.useSummary2 = false,
   }) {
     _fileContentCache = _FileContentCache.getInstance(
       _resourceProvider,
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index abea6f05..33e6df3 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -32,6 +32,8 @@
 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/declaration_splicer.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';
 
@@ -53,6 +55,7 @@
   final bool Function(Uri) _isLibraryUri;
   final AnalysisContext _context;
   final ElementResynthesizer _resynthesizer;
+  final LinkedElementFactory _elementFactory;
   final TypeProvider _typeProvider;
 
   final TypeSystem _typeSystem;
@@ -85,6 +88,7 @@
       this._isLibraryUri,
       this._context,
       this._resynthesizer,
+      this._elementFactory,
       this._inheritance,
       this._library,
       this._resourceProvider)
@@ -119,8 +123,12 @@
       _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);
 
     _resolveDirectives(units);
@@ -204,7 +212,7 @@
       ErrorReporter errorReporter, CompilationUnit unit) {
     ConstantVerifier constantVerifier = new ConstantVerifier(
         errorReporter, _libraryElement, _typeProvider, _declaredVariables,
-        forAnalysisDriver: true);
+        featureSet: unit.featureSet, forAnalysisDriver: true);
     unit.accept(constantVerifier);
   }
 
@@ -240,7 +248,7 @@
     }
 
     unit.accept(new BestPracticesVerifier(
-        errorReporter, _typeProvider, _libraryElement,
+        errorReporter, _typeProvider, _libraryElement, unit, file.content,
         typeSystem: _context.typeSystem,
         resourceProvider: _resourceProvider,
         analysisOptions: _context.analysisOptions));
@@ -623,7 +631,11 @@
       }
     }
 
-    new DeclarationResolver().resolve(unit, unitElement);
+    if (_elementFactory != null) {
+      new DeclarationSplicer(unitElement).splice(unit);
+    } else {
+      new DeclarationResolver().resolve(unit, unitElement);
+    }
 
     unit.accept(new AstRewriteVisitor(_context.typeSystem, _libraryElement,
         source, _typeProvider, errorListener,
@@ -644,15 +656,21 @@
         _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));
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_context.dart b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
index 0be1dab..421a8df 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_context.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_context.dart
@@ -9,6 +9,7 @@
 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/element/element.dart';
@@ -22,6 +23,11 @@
 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';
 
 /**
@@ -35,6 +41,7 @@
 
   final PerformanceLog logger;
   final ByteStore byteStore;
+  final AnalysisSession analysisSession;
   final SummaryDataStore store = new SummaryDataStore([]);
 
   /// The size of the linked data that is loaded by this context.
@@ -44,6 +51,7 @@
 
   RestrictedAnalysisContext analysisContext;
   SummaryResynthesizer resynthesizer;
+  LinkedElementFactory elementFactory;
   InheritanceManager2 inheritanceManager;
 
   LibraryContext({
@@ -56,8 +64,10 @@
     @required SourceFactory sourceFactory,
     @required SummaryDataStore 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);
     }
@@ -68,13 +78,17 @@
       sourceFactory,
     );
 
-    // Fill the store with summaries required for the initial library.
-    load(targetLibrary);
+    if (useSummary2) {
+      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 +102,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,7 +128,11 @@
    */
   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].
@@ -193,6 +219,100 @@
     }
   }
 
+  /// Load data required to access elements of the given [targetLibrary].
+  void load2(FileState targetLibrary) {
+    var loadedBundles = Set<LibraryCycle>.identity();
+    var inputBundles = <LinkedNodeBundle>[];
+
+    void loadBundle(LibraryCycle cycle) {
+      if (!loadedBundles.add(cycle)) return;
+
+      logger.run('Prepare linked bundle', () {
+        logger.writeln('Libraries: ${cycle.libraries}');
+        cycle.directDependencies.forEach(loadBundle);
+
+        var key = cycle.transitiveSignature + '.linked_bundle';
+        var bytes = byteStore.get(key);
+
+        if (bytes == null) {
+          var inputLibraries = <link2.LinkInputLibrary>[];
+          logger.run('Prepare input libraries', () {
+            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;
+                inputUnits.add(
+                  link2.LinkInputUnit(file.source, isSynthetic, file.parse()),
+                );
+              }
+
+              inputLibraries.add(
+                link2.LinkInputLibrary(librarySource, inputUnits),
+              );
+            }
+            logger.writeln('Prepared ${inputLibraries.length} libraries.');
+          });
+
+          link2.LinkResult linkResult;
+          logger.run('Link libraries', () {
+            linkResult = link2.link(
+              analysisContext.analysisOptions,
+              analysisContext.sourceFactory,
+              analysisContext.declaredVariables,
+              inputBundles,
+              inputLibraries,
+            );
+            logger.writeln('Linked ${inputLibraries.length} libraries.');
+          });
+
+          bytes = linkResult.bundle.toBuffer();
+          byteStore.put(key, bytes);
+          logger.writeln('Stored ${bytes.length} bytes.');
+        } else {
+          logger.writeln('Loaded ${bytes.length} bytes.');
+        }
+
+        inputBundles.add(
+          LinkedNodeBundle.fromBuffer(bytes),
+        );
+      });
+    }
+
+    logger.run('Prepare linked bundles', () {
+      var libraryCycle = targetLibrary.libraryCycle;
+      loadBundle(libraryCycle);
+    });
+
+    var rootReference = Reference.root();
+    rootReference.getChild('dart:core').getChild('dynamic').element =
+        DynamicElementImpl.instance;
+
+    elementFactory = LinkedElementFactory(
+      analysisContext,
+      analysisSession,
+      rootReference,
+    );
+
+    for (var bundle in inputBundles) {
+      elementFactory.addBundle(
+        LinkedBundleContext(elementFactory, bundle),
+      );
+    }
+
+    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 `true` if this context grew too large, and should be recreated.
   ///
   /// It might have been used to analyze libraries that we don't need anymore,
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/session.dart b/pkg/analyzer/lib/src/dart/analysis/session.dart
index 6ff7f8f..5c88736 100644
--- a/pkg/analyzer/lib/src/dart/analysis/session.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/session.dart
@@ -17,38 +17,24 @@
 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
@@ -190,10 +176,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();
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index 676b8dc..1eee9ae 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;
@@ -2060,7 +2058,10 @@
   LocalVariableInfo localVariableInfo = new LocalVariableInfo();
 
   /// Is `true` if this unit has been parsed as non-nullable.
-  bool isNonNullable = false;
+  final bool isNonNullable;
+
+  @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 +2073,10 @@
       ScriptTagImpl scriptTag,
       List<Directive> directives,
       List<CompilationUnitMember> declarations,
-      this.endToken) {
+      this.endToken,
+      this.featureSet)
+      : this.isNonNullable =
+            featureSet?.isEnabled(Feature.non_nullable) ?? false {
     _scriptTag = _becomeParentOf(scriptTag);
     _directives = new NodeListImpl<Directive>(this, directives);
     _declarations = new NodeListImpl<CompilationUnitMember>(this, declarations);
@@ -4223,13 +4227,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 +4245,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.
@@ -5201,6 +5216,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 +6070,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 +6324,9 @@
   TypeArgumentListImpl _typeArguments;
 
   @override
+  List<DartType> typeArgumentTypes;
+
+  @override
   DartType staticInvokeType;
 
   /// Initialize a newly created invocation.
@@ -10381,6 +10404,12 @@
   }
 
   @override
+  bool get isLate {
+    AstNode parent = this.parent;
+    return parent is VariableDeclarationList && parent.isLate;
+  }
+
+  @override
   SimpleIdentifier get name => _name;
 
   @override
@@ -10406,16 +10435,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 +10463,7 @@
   VariableDeclarationListImpl(
       CommentImpl comment,
       List<Annotation> metadata,
+      this.lateKeyword,
       this.keyword,
       TypeAnnotationImpl type,
       List<VariableDeclaration> variables)
@@ -10465,6 +10499,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..95b5867 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(
@@ -1021,7 +1035,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..5ac34d1 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;
   }
@@ -2642,12 +2643,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;
@@ -7059,6 +7061,9 @@
 
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (node.isRequiredNamed) {
+      _writer.print('required ');
+    }
     _visitNode(node.parameter);
     if (node.separator != null) {
       if (node.separator.lexeme != ":") {
@@ -7780,6 +7785,7 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     _visitNodeListWithSeparatorAndSuffix(node.metadata, " ", " ");
+    _visitTokenWithSuffix(node.lateKeyword, " ");
     _visitTokenWithSuffix(node.keyword, " ");
     _visitNodeWithSuffix(node.type, " ");
     _visitNodeListWithSeparator(node.variables, ", ");
@@ -8320,6 +8326,9 @@
 
   @override
   void visitDefaultFormalParameter(DefaultFormalParameter node) {
+    if (node.isRequiredNamed) {
+      sink.write('required ');
+    }
     safelyVisitNode(node.parameter);
     if (node.separator != null) {
       if (node.separator.lexeme != ":") {
@@ -9038,6 +9047,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..43dbc77 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>{};
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..bac1408 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -98,11 +98,6 @@
   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
@@ -113,7 +108,8 @@
       {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(),
@@ -902,9 +898,6 @@
     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
@@ -1019,7 +1012,8 @@
  */
 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;
 
@@ -1717,23 +1711,13 @@
         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;
@@ -1804,7 +1788,7 @@
   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;
 
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/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 0997e08..b917123 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -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..9bad2c1 100644
--- a/pkg/analyzer/lib/src/dart/element/element.dart
+++ b/pkg/analyzer/lib/src/dart/element/element.dart
@@ -454,6 +454,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)
@@ -555,12 +558,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) {
@@ -882,11 +897,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 +953,10 @@
 
   @override
   List<InterfaceType> get mixins {
+    if (linkedMixinInferenceCallback != null) {
+      _mixins = linkedMixinInferenceCallback(this);
+    }
+
     if (_mixins != null) {
       return _mixins;
     }
@@ -1009,6 +1027,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 +1654,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 +1703,9 @@
 
   @override
   int get codeLength {
+    if (linkedNode != null) {
+      return linkedContext.getCodeLength(linkedNode);
+    }
     if (_unlinkedUnit != null) {
       return _unlinkedUnit.codeRange?.length;
     }
@@ -1687,6 +1714,9 @@
 
   @override
   int get codeOffset {
+    if (linkedNode != null) {
+      return linkedContext.getCodeOffset(linkedNode);
+    }
     if (_unlinkedUnit != null) {
       return _unlinkedUnit.codeRange?.offset;
     }
@@ -1712,11 +1742,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 +1779,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 +1820,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 +1873,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 +1980,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;
     }
@@ -2811,7 +2839,7 @@
 
     if (linkedNode != null) {
       var context = enclosingUnit.linkedContext;
-      return _constantInitializer = context.readInitializer(this, linkedNode);
+      return _constantInitializer = context.readInitializer(linkedNode);
     }
 
     if (_unlinkedConst != null) {
@@ -3232,7 +3260,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 +3408,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 +3807,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;
   }
@@ -4135,6 +4176,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 +4340,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)
@@ -4580,19 +4623,19 @@
         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 +4644,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,7 +4663,7 @@
       if (closing != null) {
         buffer.write(closing);
       }
-      buffer.write(")");
+      buffer.write(')');
     }
     if (type != null) {
       buffer.write(ElementImpl.RIGHT_ARROW);
@@ -4757,6 +4803,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 +4937,7 @@
   @override
   bool get isCovariant {
     if (linkedNode != null) {
-      return linkedContext.isCovariant(linkedNode);
+      return linkedContext.isExplicitlyCovariant(linkedNode);
     }
 
     if (_unlinkedVariable != null) {
@@ -4908,17 +4958,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 +5024,9 @@
   FieldElement get field {
     if (_field == null) {
       String fieldName;
+      if (linkedNode != null) {
+        fieldName = linkedContext.getFieldFormalParameterName(linkedNode);
+      }
       if (unlinkedParam != null) {
         fieldName = unlinkedParam.name;
       }
@@ -5540,11 +5582,17 @@
     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 = GenericFunctionTypeElementImpl.forLinkedNode(
+            this,
+            reference,
+            function,
+          );
+        } else {
+          return null;
+        }
       } else {
         return _function = GenericFunctionTypeElementImpl.forLinkedNode(
           this,
@@ -5590,6 +5638,13 @@
     _function = function;
   }
 
+  bool get hasSelfReference {
+    if (linkedNode != null) {
+      return linkedContext.getHasTypedefSelfReference(linkedNode);
+    }
+    return false;
+  }
+
   @override
   bool get isSimplyBounded {
     if (linkedNode != null) {
@@ -5623,6 +5678,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;
@@ -5969,6 +6028,10 @@
 
   @override
   int get nameOffset {
+    if (linkedNode != null) {
+      return linkedContext.getDirectiveOffset(linkedNode);
+    }
+
     int offset = super.nameOffset;
     if (offset == 0 && _unlinkedImport != null) {
       if (_unlinkedImport.isImplicit) {
@@ -6262,6 +6325,10 @@
         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
@@ -6335,9 +6402,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 +6508,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 +6662,14 @@
   }
 
   @override
+  bool get isSynthetic {
+    if (linkedNode != null) {
+      return linkedContext.isSynthetic;
+    }
+    return super.isSynthetic;
+  }
+
+  @override
   ElementKind get kind => ElementKind.LIBRARY;
 
   @override
@@ -6667,7 +6767,7 @@
 
     if (linkedNode != null) {
       var metadata = linkedContext.getLibraryMetadata(linkedNode);
-      return _metadata = _buildAnnotations2(enclosingUnit, metadata);
+      return _metadata = _buildAnnotations2(definingCompilationUnit, metadata);
     }
 
     if (unlinkedDefiningUnit != null) {
@@ -7013,14 +7113,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
@@ -7244,6 +7344,7 @@
         constraints = onClause.superclassConstraints
             .map((node) => node.type)
             .whereType<InterfaceType>()
+            .where(_isInterfaceTypeInterface)
             .toList();
       }
       if (constraints == null || constraints.isEmpty) {
@@ -7283,11 +7384,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 +7496,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 +7532,7 @@
     GETTER,
     HAS_EXT_URI,
     IMPLICIT_TYPE,
-    LAZY,
+    LATE,
     MIXIN_APPLICATION,
     REFERENCES_SUPER,
     SETTER,
@@ -7506,6 +7613,9 @@
   bool get hasLiteral => false;
 
   @override
+  bool get hasMustCallSuper => false;
+
+  @override
   bool get hasOptionalTypeArgs => false;
 
   @override
@@ -7786,6 +7896,13 @@
   @override
   FunctionElement get initializer {
     if (_initializer == null) {
+      if (linkedNode != null) {
+        if (linkedContext.readInitializer(linkedNode) != null) {
+          _initializer = new FunctionElementImpl('', -1)
+            ..isSynthetic = true
+            .._type = FunctionTypeImpl.synthetic(type, [], []);
+        }
+      }
       if (_unlinkedVariable != null) {
         UnlinkedExecutable unlinkedInitializer = _unlinkedVariable.initializer;
         if (unlinkedInitializer != null) {
@@ -7892,6 +8009,10 @@
 
   @override
   TopLevelInferenceError get typeInferenceError {
+    if (linkedNode != null) {
+      return linkedContext.getTypeInferenceError(linkedNode);
+    }
+
     if (_unlinkedVariable != null) {
       return enclosingUnit.resynthesizerContext
           .getTypeInferenceError(_unlinkedVariable.inferredTypeSlot);
@@ -7911,6 +8032,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 +8100,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 +8108,7 @@
             unlinkedParameter, enclosingElement);
       }
     } else {
-      if (unlinkedParameter.kind == UnlinkedParamKind.required) {
+      if (unlinkedParameter.kind == UnlinkedParamKind.requiredPositional) {
         element = new ParameterElementImpl.forSerialized(
             unlinkedParameter, enclosingElement);
       } else {
@@ -8023,6 +8154,10 @@
 
   @override
   String get defaultValueCode {
+    if (linkedNode != null) {
+      return linkedContext.getDefaultValueCode(linkedNode);
+    }
+
     if (unlinkedParam != null) {
       if (unlinkedParam.initializer?.bodyExpr == null) {
         return null;
@@ -8059,6 +8194,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 +8207,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 +8219,11 @@
   @override
   FunctionElement get initializer {
     if (_initializer == null) {
+      if (linkedNode != null) {
+        if (linkedContext.readInitializer(linkedNode) != null) {
+          _initializer = new FunctionElementImpl('', -1)..isSynthetic = true;
+        }
+      }
       if (unlinkedParam != null) {
         UnlinkedExecutable unlinkedInitializer = unlinkedParam.initializer;
         if (unlinkedInitializer != null) {
@@ -8113,9 +8261,6 @@
 
   @override
   bool get isCovariant {
-    if (linkedNode != null) {
-      return linkedContext.isCovariant(linkedNode);
-    }
     if (isExplicitlyCovariant || inheritsCovariant) {
       return true;
     }
@@ -8124,6 +8269,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 +8346,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 +8368,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 +8392,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 +8440,10 @@
 
   @override
   TopLevelInferenceError get typeInferenceError {
+    if (linkedNode != null) {
+      return linkedContext.getTypeInferenceError(linkedNode);
+    }
+
     if (unlinkedParam != null) {
       return enclosingUnit.resynthesizerContext
           .getTypeInferenceError(unlinkedParam.inferredTypeSlot);
@@ -8266,7 +8454,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 +8507,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 +8552,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 +8585,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 +8611,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 +8659,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 +8713,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 +8728,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -8501,21 +8739,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);
     }
   }
@@ -8886,6 +9125,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 +9424,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 +9494,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 +9533,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 +9545,7 @@
   }
 
   TypeParameterType get type {
-    if (linkedNode != null) {
-      _type ??= new TypeParameterTypeImpl(this);
-    }
-    if (_unlinkedTypeParam != null) {
-      _type ??= new TypeParameterTypeImpl(this);
-    }
-    return _type;
+    return _type ??= new TypeParameterTypeImpl(this);
   }
 
   void set type(TypeParameterType type) {
@@ -9343,10 +9599,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..f316eb7 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;
@@ -987,7 +987,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 +1180,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..fc58f4f 100644
--- a/pkg/analyzer/lib/src/dart/element/member.dart
+++ b/pkg/analyzer/lib/src/dart/element/member.dart
@@ -256,7 +256,7 @@
   bool get isEnumConstant => baseElement.isEnumConstant;
 
   @override
-  bool get isLazy => baseElement.isLazy;
+  bool get isLate => baseElement.isLate;
 
   @deprecated
   @override
@@ -428,6 +428,9 @@
   bool get hasLiteral => _baseElement.hasLiteral;
 
   @override
+  bool get hasMustCallSuper => _baseElement.hasMustCallSuper;
+
+  @override
   bool get hasOptionalTypeArgs => _baseElement.hasOptionalTypeArgs;
 
   @override
@@ -648,10 +651,10 @@
         if (closing != null) {
           buffer.write(closing);
         }
-        if (parameterKind == ParameterKind.POSITIONAL) {
+        if (parameter.isOptionalPositional) {
           buffer.write("[");
           closing = "]";
-        } else if (parameterKind == ParameterKind.NAMED) {
+        } else if (parameter.isNamed) {
           buffer.write("{");
           closing = "}";
         } else {
diff --git a/pkg/analyzer/lib/src/dart/element/type.dart b/pkg/analyzer/lib/src/dart/element/type.dart
index 267f338..9b55e2c 100644
--- a/pkg/analyzer/lib/src/dart/element/type.dart
+++ b/pkg/analyzer/lib/src/dart/element/type.dart
@@ -502,7 +502,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 +602,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,6 +678,9 @@
   @override
   void appendTo(StringBuffer buffer, Set<TypeImpl> visitedTypes,
       {bool withNullability = false}) {
+    // TODO(paulberry): update to use the new "Function" syntax to avoid
+    // ambiguity with NNBD, and eliminate code duplication with
+    // _ElementWriter.writeType.  See issue #35818.
     if (visitedTypes.add(this)) {
       if (typeFormals.isNotEmpty) {
         // To print a type with type variables, first make sure we have unique
@@ -936,43 +945,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 +1027,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 +1041,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);
@@ -3265,87 +3237,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 +3402,7 @@
   @override
   List<String> get normalParameterNames {
     return baseParameters
-        .where((parameter) => parameter.isNotOptional)
+        .where((parameter) => parameter.isRequiredPositional)
         .map((parameter) => parameter.name)
         .toList();
   }
@@ -3798,8 +3689,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..5a9be7c 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
@@ -472,6 +478,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..134f410 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,7 +51,7 @@
   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.");
@@ -148,7 +148,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 +163,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 +173,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 +204,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.");
 
   /**
@@ -261,7 +261,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 +274,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 +288,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 +319,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 +327,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 +338,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 +347,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 +358,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 +368,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 +405,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 +416,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 +428,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 +441,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 +450,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 +461,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 +479,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 +491,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 +560,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 +568,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 "
+  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 "
           "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 +582,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.2.2, but this code is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -593,8 +592,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.2.2, but this code is required to be able to run on earlier "
+          "versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -604,20 +603,19 @@
   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.",
+          "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 "
+  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 "
           "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
@@ -626,7 +624,7 @@
   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.",
+          "but this code is required to be able to run on earlier versions.",
       correction: "Try updating the SDK constraints.");
 
   /**
@@ -636,7 +634,7 @@
   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 +646,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.");
diff --git a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
index de2684c..5110557 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.dart
@@ -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,7 +106,8 @@
   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;
 
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..25c445b 100644
--- a/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
+++ b/pkg/analyzer/lib/src/dart/error/syntactic_errors.g.dart
@@ -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,
@@ -103,8 +103,6 @@
   _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 +135,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,11 +174,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'.",
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..23844eb 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,6 +560,20 @@
     }
     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) {
@@ -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/scanner/scanner.dart b/pkg/analyzer/lib/src/dart/scanner/scanner.dart
index ab852cf..616b9fc 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
@@ -104,9 +140,13 @@
 
   Token tokenize() {
     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();
@@ -133,4 +173,21 @@
     }
     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(
+              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..8a3e142 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -785,6 +785,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 +819,15 @@
           correction: "Try removing the default value.");
 
   /**
+   * It is an error if a required named parameter has a default value.
+   */
+  static const CompileTimeErrorCode DEFAULT_VALUE_ON_REQUIRED_PARAMETER =
+      const CompileTimeErrorCode('DEFAULT_VALUE_ON_REQUIRED_PARAMETER',
+          "Required named parameters cannot 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.
    */
@@ -1493,6 +1513,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 +1706,33 @@
           correction: "Check your Dart SDK installation for completeness.");
 
   /**
+   * It is an error if an optional parameter (named or otherwise) with no
+   * default value has a potentially non-nullable type.
+   */
+  static const CompileTimeErrorCode MISSING_DEFAULT_VALUE_FOR_PARAMETER =
+      const CompileTimeErrorCode(
+          'MISSING_DEFAULT_VALUE_FOR_PARAMETER',
+          "The parameter '{0}' cannot 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 +1756,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}'.");
 
   /**
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 22634cd..df9bd69 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;
@@ -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>{};
@@ -106,7 +105,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,6 +120,8 @@
   /// `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),
@@ -169,11 +173,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
@@ -255,10 +260,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 +284,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');
@@ -481,11 +504,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);
   }
 
@@ -696,27 +721,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(
         comment: comment,
         metadata: metadata,
         covariantKeyword: covariantKeyword,
-        staticKeyword: modifiers?.staticKeyword,
+        staticKeyword: staticToken,
         fieldList: variableList,
         semicolon: semicolon));
   }
@@ -791,6 +816,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,6 +835,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             returnType: typeOrFunctionTypedParameter.returnType,
             typeParameters: typeOrFunctionTypedParameter.typeParameters,
             parameters: typeOrFunctionTypedParameter.parameters);
@@ -815,6 +845,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             type: typeOrFunctionTypedParameter.returnType,
             thisKeyword: thisKeyword,
             period: periodAfterThis,
@@ -828,6 +859,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             keyword: keyword,
             type: type,
             identifier: name);
@@ -836,6 +868,7 @@
             comment: comment,
             metadata: metadata,
             covariantKeyword: covariantKeyword,
+            requiredKeyword: requiredKeyword,
             keyword: keyword,
             type: type,
             thisKeyword: thisKeyword,
@@ -844,7 +877,8 @@
       }
     }
 
-    ParameterKind analyzerKind = _toAnalyzerParameterKind(kind);
+    ParameterKind analyzerKind =
+        _toAnalyzerParameterKind(kind, requiredKeyword);
     FormalParameter parameter = node;
     if (analyzerKind != ParameterKind.REQUIRED) {
       parameter = ast.defaultFormalParameter(
@@ -1426,9 +1460,7 @@
     }
 
     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);
@@ -1725,20 +1757,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 +1885,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));
   }
 
@@ -2473,16 +2516,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"));
@@ -3253,10 +3286,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 +3328,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 +3339,9 @@
       externalKeyword,
       finalConstOrVarKeyword,
       staticKeyword,
-      covariantKeyword
+      covariantKeyword,
+      requiredToken,
+      lateToken,
     ]) {
       if (firstToken == null) {
         firstToken = token;
diff --git a/pkg/analyzer/lib/src/generated/declaration_resolver.dart b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
index 7175395..31c567f 100644
--- a/pkg/analyzer/lib/src/generated/declaration_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/declaration_resolver.dart
@@ -137,10 +137,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 +147,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 +198,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);
@@ -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);
@@ -405,7 +400,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);
@@ -514,6 +509,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 +735,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 +847,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..dae105c 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -14,12 +14,14 @@
 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/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';
@@ -745,6 +747,7 @@
   void visitFormalParameterList(FormalParameterList node) {
     _checkDuplicateDefinitionInParameterList(node);
     _checkUseOfCovariantInParameters(node);
+    _checkUseOfDefaultValuesInParameters(node);
     super.visitFormalParameterList(node);
   }
 
@@ -839,6 +842,8 @@
     }
     _checkForImplicitDynamicInvoke(node);
     _checkForNullableDereference(node.function);
+    _checkForMissingRequiredParam(
+        node.staticInvokeType, node.argumentList, node);
     super.visitFunctionExpressionInvocation(node);
   }
 
@@ -874,7 +879,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 +951,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 +961,7 @@
         } else {
           _checkForNewWithUndefinedConstructor(node, constructorName, typeName);
         }
+        _checkForListConstructor(node, type);
       }
       _checkForImplicitDynamicType(typeName);
       super.visitInstanceCreationExpression(node);
@@ -1045,6 +1053,8 @@
     }
     _checkTypeArguments(node);
     _checkForImplicitDynamicInvoke(node);
+    _checkForMissingRequiredParam(
+        node.staticInvokeType, node.argumentList, node.methodName);
     if (node.operator?.type != TokenType.QUESTION_PERIOD &&
         methodName.name != 'toString' &&
         methodName.name != 'noSuchMethod') {
@@ -1164,6 +1174,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 +1273,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 +1951,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);
         }
       }
@@ -2531,8 +2551,8 @@
         _errorReporter.reportErrorForElement(
             CompileTimeErrorCode.CONFLICTING_METHOD_AND_FIELD, method, [
           _enclosingClass.displayName,
-          inherited.enclosingElement.displayName,
-          name
+          name,
+          inherited.enclosingElement.displayName
         ]);
       }
     }
@@ -3294,7 +3314,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 +3479,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;
@@ -3890,6 +3909,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.
@@ -4100,6 +4130,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 +4258,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;
       }
     }
@@ -4358,7 +4409,7 @@
       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)) {
@@ -4759,6 +4810,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 +4828,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 +5014,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));
     }
   }
 
@@ -5246,6 +5315,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(
@@ -5613,7 +5684,7 @@
     }
 
     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);
@@ -5856,6 +5927,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 +6025,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 +6165,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 +6178,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 +6222,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 +6242,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 +6355,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 +6580,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 +6595,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 +6611,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..21a62ae 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).
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..0f3e861 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';
@@ -298,7 +300,9 @@
   BestPracticesVerifier(
     this._errorReporter,
     TypeProvider typeProvider,
-    this._currentLibrary, {
+    this._currentLibrary,
+    CompilationUnit unit,
+    String content, {
     TypeSystem typeSystem,
     ResourceProvider resourceProvider,
     DeclaredVariables declaredVariables,
@@ -317,7 +321,7 @@
     _workspacePackage = workspace.findPackageFor(libraryPath);
     _linterContext = LinterContextImpl(
         null /* allUnits */,
-        null /* currentUnit */,
+        new LinterContextUnit(content, unit),
         declaredVariables,
         typeProvider,
         _typeSystem,
@@ -743,15 +747,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 +771,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 +967,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
@@ -1278,6 +1272,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.
   ///
@@ -3331,9 +3334,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) {
@@ -3509,9 +3513,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) {
@@ -3661,6 +3666,8 @@
 
   final AnalysisOptionsImpl _analysisOptions;
 
+  final bool _uiAsCodeEnabled;
+
   /// The object used to resolve the element associated with the current node.
   ElementResolver elementResolver;
 
@@ -3718,16 +3725,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 +3776,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 +3887,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 +4847,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 +5469,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 +5988,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 +6009,8 @@
       super.visitGenericFunctionType(node);
       return;
     }
-    GenericFunctionTypeElement element = type.element;
+    GenericFunctionTypeElement element =
+        (node as GenericFunctionTypeImpl).declaredElement;
     Scope outerScope = nameScope;
     try {
       if (element == null) {
@@ -6256,7 +6296,6 @@
 class TypeNameResolver {
   final TypeSystem typeSystem;
   final DartType dynamicType;
-  final DartType undefinedType;
   final bool isNonNullableUnit;
   final AnalysisOptionsImpl analysisOptions;
   final LibraryElement definingLibrary;
@@ -6281,7 +6320,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 +6361,8 @@
         return;
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = undefinedType;
-        node.type = undefinedType;
+        typeName.staticType = dynamicType;
+        node.type = dynamicType;
         return;
       }
       //
@@ -6344,8 +6382,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 +6421,8 @@
         }
       }
       if (nameScope.shouldIgnoreUndefined(typeName)) {
-        typeName.staticType = undefinedType;
-        node.type = undefinedType;
+        typeName.staticType = dynamicType;
+        node.type = dynamicType;
         return;
       }
     }
@@ -6501,8 +6539,8 @@
       if (element is MultiplyDefinedElement) {
         _setElement(typeName, element);
       }
-      typeName.staticType = undefinedType;
-      node.type = undefinedType;
+      typeName.staticType = dynamicType;
+      node.type = dynamicType;
       return;
     }
 
@@ -6560,8 +6598,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 +6713,7 @@
   DartType _getType(TypeAnnotation annotation) {
     DartType type = annotation.type;
     if (type == null) {
-      return undefinedType;
+      return dynamicType;
     }
     return type;
   }
@@ -7232,9 +7270,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);
@@ -7373,9 +7408,6 @@
   /// 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) {
@@ -7477,9 +7509,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.
@@ -7534,7 +7563,6 @@
     _stringType = _getType(coreNamespace, 'String');
     _symbolType = _getType(coreNamespace, 'Symbol');
     _typeType = _getType(coreNamespace, 'Type');
-    _undefinedType = UndefinedTypeImpl.instance;
     _futureDynamicType = _futureType.instantiate(<DartType>[_dynamicType]);
     _futureNullType = _futureType.instantiate(<DartType>[_nullType]);
     _iterableDynamicType = _iterableType.instantiate(<DartType>[_dynamicType]);
@@ -7588,9 +7616,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;
@@ -7646,7 +7671,6 @@
       : 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,
@@ -7904,7 +7928,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 +8347,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..14f6958 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
@@ -68,11 +72,16 @@
   TypePromotionManager _promoteManager;
 
   /**
+   * Whether NNBD is enabled for this compilation unit.
+   */
+  bool _nonNullableEnabled;
+
+  /**
    * Initialize a newly created type analyzer.
    *
    * @param resolver the resolver driving this participant
    */
-  StaticTypeAnalyzer(this._resolver) {
+  StaticTypeAnalyzer(this._resolver, FeatureSet featureSet) {
     _typeProvider = _resolver.typeProvider;
     _typeSystem = _resolver.typeSystem;
     _dynamicType = _typeProvider.dynamicType;
@@ -80,6 +89,7 @@
     AnalysisOptionsImpl analysisOptions =
         _resolver.definingLibrary.context.analysisOptions;
     _strictInference = analysisOptions.strictInference;
+    _nonNullableEnabled = featureSet.isEnabled(Feature.non_nullable);
   }
 
   /**
@@ -123,9 +133,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);
         }
@@ -281,10 +291,22 @@
       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) {
@@ -363,11 +385,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;
@@ -500,7 +534,8 @@
   @override
   void visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
     _inferGenericInvocationExpression(node);
-    DartType staticType = _computeInvokeReturnType(node.staticInvokeType);
+    DartType staticType = _computeInvokeReturnType(node.staticInvokeType,
+        isNullableInvoke: false);
     _recordStaticType(node, staticType);
   }
 
@@ -670,8 +705,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);
     }
   }
@@ -775,6 +811,7 @@
     } else if (staticElement is VariableElement) {
       staticType = staticElement.type;
     }
+
     staticType = _inferGenericInstantiationFromContext(node, staticType);
     if (!_inferObjectAccess(node, staticType, prefixedIdentifier)) {
       _recordStaticType(prefixedIdentifier, staticType);
@@ -863,7 +900,14 @@
     } else {
       // TODO(brianwilkerson) Report this internal error.
     }
+
+    if (node.operator.type == TokenType.QUESTION_PERIOD &&
+        _nonNullableEnabled) {
+      staticType =
+          (staticType as TypeImpl).withNullability(NullabilitySuffix.question);
+    }
     staticType = _inferGenericInstantiationFromContext(node, staticType);
+
     if (!_inferObjectAccess(node, staticType, propertyName)) {
       _recordStaticType(propertyName, staticType);
       _recordStaticType(node, staticType);
@@ -1071,10 +1115,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;
@@ -1159,15 +1214,22 @@
    * 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;
     } else if (type is FunctionType) {
-      return type.returnType ?? _dynamicType;
+      returnType = type.returnType;
     }
-    return _dynamicType;
+
+    if (isNullableInvoke && _nonNullableEnabled) {
+      returnType = returnType?.withNullability(NullabilitySuffix.question);
+    }
+
+    return returnType ?? _dynamicType;
   }
 
   /**
@@ -1208,13 +1270,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 +1575,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 +1592,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 +1639,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;
   }
 
@@ -1962,6 +2044,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..ab12e27 100644
--- a/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
+++ b/pkg/analyzer/lib/src/generated/testing/ast_test_factory.dart
@@ -275,14 +275,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) =>
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..da58fd1 100644
--- a/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
+++ b/pkg/analyzer/lib/src/generated/testing/test_type_provider.dart
@@ -179,11 +179,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>`.
    */
@@ -612,14 +607,6 @@
     return _typeType;
   }
 
-  @override
-  DartType get undefinedType {
-    if (_undefinedType == null) {
-      _undefinedType = UndefinedTypeImpl.instance;
-    }
-    return _undefinedType;
-  }
-
   void _initDartAsync() {
     Source asyncSource;
     if (_driver != null) {
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index b2fa6c8..a774f85 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -11,6 +11,7 @@
 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';
@@ -193,8 +194,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 +232,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 +305,7 @@
           genericType: genericType);
     }
 
-    return inferrer.infer(genericType, typeFormals,
+    return inferrer.infer(typeFormals,
         errorReporter: errorReporter,
         errorNode: errorNode,
         downwardsInferPhase: downwards);
@@ -297,7 +345,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 +371,9 @@
       Set<DartType> visitedTypes = new HashSet<DartType>();
 
       void appendParameters(DartType type) {
+        if (type == null) {
+          return;
+        }
         if (visitedTypes.contains(type)) {
           return;
         }
@@ -330,6 +381,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);
         }
@@ -771,6 +829,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 +1205,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 +1248,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 +1307,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 +1326,7 @@
         ]);
       }
     }
+
     return result;
   }
 
@@ -1978,8 +2039,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,6 +2082,11 @@
     return null;
   }
 
+  DartType promoteToNonNull(TypeImpl type) {
+    // 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].
@@ -2166,6 +2237,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/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..331d7a6 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)));
@@ -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..1f18466 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';
@@ -626,19 +627,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 +676,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 +1086,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;
@@ -1488,6 +1512,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 +1555,7 @@
     if (parameters == null) return null;
 
     return parameters.parameters
-        .takeWhile((parameter) => parameter.isRequired)
+        .takeWhile((parameter) => parameter.isRequiredPositional)
         .length;
   }
 
@@ -1588,10 +1616,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 +1661,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 +1679,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/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/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 7b27b6c..d655c4c 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,
@@ -4653,12 +4728,12 @@
   LinkedNodeBuilder _variantField_6;
   int _variantField_15;
   LinkedNodeBuilder _variantField_7;
+  int _variantField_17;
+  LinkedNodeTypeBuilder _variantField_23;
   LinkedNodeBuilder _variantField_8;
   int _variantField_16;
-  int _variantField_17;
   int _variantField_18;
   int _variantField_19;
-  LinkedNodeTypeBuilder _variantField_23;
   bool _variantField_27;
   LinkedNodeBuilder _variantField_9;
   LinkedNodeBuilder _variantField_12;
@@ -4670,15 +4745,17 @@
   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;
   String _variantField_30;
   LinkedNodeBuilder _variantField_14;
   bool _isSynthetic;
   idl.LinkedNodeKind _kind;
+  List<String> _variantField_36;
   String _variantField_20;
   bool _variantField_31;
+  TopLevelInferenceErrorBuilder _variantField_35;
   String _variantField_22;
   LinkedNodeVariablesDeclarationBuilder _variantField_32;
 
@@ -4768,6 +4845,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>[];
@@ -4914,6 +4997,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;
@@ -5229,6 +5317,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;
@@ -5687,6 +5781,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;
@@ -6108,6 +6207,12 @@
   }
 
   @override
+  int get commentReference_newKeyword {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    return _variantField_15 ??= 0;
+  }
+
+  @override
   int get compilationUnit_beginToken {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     return _variantField_15 ??= 0;
@@ -6664,6 +6769,12 @@
     _variantField_15 = value;
   }
 
+  set commentReference_newKeyword(int value) {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    assert(value == null || value >= 0);
+    _variantField_15 = value;
+  }
+
   set compilationUnit_beginToken(int value) {
     assert(kind == idl.LinkedNodeKind.compilationUnit);
     assert(value == null || value >= 0);
@@ -7672,6 +7783,419 @@
   }
 
   @override
+  int get annotation_element {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    return _variantField_17 ??= 0;
+  }
+
+  @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 genericFunctionType_id {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    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 annotation_element(int value) {
+    assert(kind == idl.LinkedNodeKind.annotation);
+    assert(value == null || value >= 0);
+    _variantField_17 = value;
+  }
+
+  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 genericFunctionType_id(int value) {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    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
+  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;
@@ -8164,14 +8688,14 @@
   }
 
   @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
+  int get typeParameterList_rightBracket {
+    assert(kind == idl.LinkedNodeKind.typeParameterList);
     return _variantField_16 ??= 0;
   }
 
   @override
-  int get typeParameterList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
+  int get variableDeclarationList_lateKeyword {
+    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
     return _variantField_16 ??= 0;
   }
 
@@ -8503,14 +9027,14 @@
     _variantField_16 = value;
   }
 
-  set typeParameter_id(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
+  set typeParameterList_rightBracket(int value) {
+    assert(kind == idl.LinkedNodeKind.typeParameterList);
     assert(value == null || value >= 0);
     _variantField_16 = value;
   }
 
-  set typeParameterList_rightBracket(int value) {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
+  set variableDeclarationList_lateKeyword(int value) {
+    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
     assert(value == null || value >= 0);
     _variantField_16 = value;
   }
@@ -8528,262 +9052,6 @@
   }
 
   @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;
@@ -8862,6 +9130,14 @@
   }
 
   @override
+  int get normalFormalParameter_requiredKeyword {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    return _variantField_18 ??= 0;
+  }
+
+  @override
   int get switchStatement_leftBracket {
     assert(kind == idl.LinkedNodeKind.switchStatement);
     return _variantField_18 ??= 0;
@@ -8953,6 +9229,14 @@
     _variantField_18 = value;
   }
 
+  set normalFormalParameter_requiredKeyword(int value) {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    assert(value == null || value >= 0);
+    _variantField_18 = value;
+  }
+
   set switchStatement_leftBracket(int value) {
     assert(kind == idl.LinkedNodeKind.switchStatement);
     assert(value == null || value >= 0);
@@ -9144,117 +9428,6 @@
   }
 
   @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;
-  }
-
-  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;
-  }
-
-  @override
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     return _variantField_27 ??= false;
@@ -9267,16 +9440,11 @@
   }
 
   @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;
   }
 
@@ -9286,6 +9454,19 @@
     return _variantField_27 ??= false;
   }
 
+  @override
+  bool get simpleIdentifier_isDeclaration {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    return _variantField_27 ??= false;
+  }
+
+  @override
+  bool get typeAlias_hasSelfReference {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias);
+    return _variantField_27 ??= false;
+  }
+
   set booleanLiteral_value(bool value) {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 = value;
@@ -9296,15 +9477,11 @@
     _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;
   }
 
@@ -9313,6 +9490,17 @@
     _variantField_27 = value;
   }
 
+  set simpleIdentifier_isDeclaration(bool value) {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_27 = value;
+  }
+
+  set typeAlias_hasSelfReference(bool value) {
+    assert(kind == idl.LinkedNodeKind.functionTypeAlias ||
+        kind == idl.LinkedNodeKind.genericTypeAlias);
+    _variantField_27 = value;
+  }
+
   @override
   LinkedNodeBuilder get catchClause_stackTraceParameter {
     assert(kind == idl.LinkedNodeKind.catchClause);
@@ -9452,6 +9640,7 @@
   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 ||
@@ -9471,6 +9660,7 @@
   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 ||
@@ -9492,6 +9682,7 @@
   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 ||
@@ -9521,6 +9712,7 @@
   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 ||
@@ -9643,6 +9835,18 @@
   }
 
   @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
   double get doubleLiteral_value {
     assert(kind == idl.LinkedNodeKind.doubleLiteral);
     return _variantField_21 ??= 0.0;
@@ -9738,21 +9942,6 @@
   }
 
   @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;
-  }
-
-  set formalParameter_kind(idl.LinkedNodeFormalParameterKind value) {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_26 = value;
-  }
-
-  @override
   String get interpolationString_value {
     assert(kind == idl.LinkedNodeKind.interpolationString);
     return _variantField_30 ??= '';
@@ -9857,6 +10046,17 @@
   }
 
   @override
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    return _variantField_36 ??= <String>[];
+  }
+
+  set mixinDeclaration_superInvokedNames(List<String> value) {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_36 = value;
+  }
+
+  @override
   String get namespaceDirective_selectedUri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -9911,6 +10111,19 @@
   }
 
   @override
+  TopLevelInferenceErrorBuilder get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    return _variantField_35;
+  }
+
+  set topLevelTypeInferenceError(TopLevelInferenceErrorBuilder value) {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_35 = value;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -9980,6 +10193,7 @@
     LinkedNodeBuilder functionTypeAlias_typeParameters,
     int typeAlias_typedefKeyword,
     int typeAlias_semicolon,
+    bool typeAlias_hasSelfReference,
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder namedCompilationUnitMember_name,
@@ -9993,6 +10207,7 @@
         _variantField_8 = functionTypeAlias_typeParameters,
         _variantField_18 = typeAlias_typedefKeyword,
         _variantField_19 = typeAlias_semicolon,
+        _variantField_27 = typeAlias_hasSelfReference,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
         _variantField_14 = namedCompilationUnitMember_name,
@@ -10003,6 +10218,7 @@
     LinkedNodeBuilder genericFunctionType_typeParameters,
     int genericFunctionType_functionKeyword,
     LinkedNodeBuilder genericFunctionType_returnType,
+    int genericFunctionType_id,
     LinkedNodeBuilder genericFunctionType_formalParameters,
     int genericFunctionType_question,
     LinkedNodeTypeBuilder genericFunctionType_type,
@@ -10011,6 +10227,7 @@
         _variantField_6 = genericFunctionType_typeParameters,
         _variantField_15 = genericFunctionType_functionKeyword,
         _variantField_7 = genericFunctionType_returnType,
+        _variantField_17 = genericFunctionType_id,
         _variantField_8 = genericFunctionType_formalParameters,
         _variantField_16 = genericFunctionType_question,
         _variantField_25 = genericFunctionType_type;
@@ -10022,9 +10239,9 @@
     LinkedNodeBuilder methodDeclaration_body,
     int methodDeclaration_externalKeyword,
     LinkedNodeBuilder methodDeclaration_formalParameters,
+    int methodDeclaration_operatorKeyword,
     LinkedNodeBuilder methodDeclaration_returnType,
     int methodDeclaration_modifierKeyword,
-    int methodDeclaration_operatorKeyword,
     int methodDeclaration_propertyKeyword,
     int methodDeclaration_actualProperty,
     LinkedNodeBuilder methodDeclaration_typeParameters,
@@ -10038,9 +10255,9 @@
         _variantField_6 = methodDeclaration_body,
         _variantField_15 = methodDeclaration_externalKeyword,
         _variantField_7 = methodDeclaration_formalParameters,
+        _variantField_17 = methodDeclaration_operatorKeyword,
         _variantField_8 = methodDeclaration_returnType,
         _variantField_16 = methodDeclaration_modifierKeyword,
-        _variantField_17 = methodDeclaration_operatorKeyword,
         _variantField_18 = methodDeclaration_propertyKeyword,
         _variantField_19 = methodDeclaration_actualProperty,
         _variantField_9 = methodDeclaration_typeParameters,
@@ -10054,15 +10271,15 @@
     LinkedNodeBuilder fieldFormalParameter_type,
     int fieldFormalParameter_keyword,
     LinkedNodeBuilder fieldFormalParameter_typeParameters,
+    int fieldFormalParameter_thisKeyword,
     LinkedNodeBuilder fieldFormalParameter_formalParameters,
     int fieldFormalParameter_period,
-    int fieldFormalParameter_thisKeyword,
+    int normalFormalParameter_requiredKeyword,
     int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
+    bool inheritsCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     int codeLength,
     int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
   })  : _kind = idl.LinkedNodeKind.fieldFormalParameter,
         _variantField_24 = actualType,
@@ -10070,15 +10287,15 @@
         _variantField_6 = fieldFormalParameter_type,
         _variantField_15 = fieldFormalParameter_keyword,
         _variantField_7 = fieldFormalParameter_typeParameters,
+        _variantField_17 = fieldFormalParameter_thisKeyword,
         _variantField_8 = fieldFormalParameter_formalParameters,
         _variantField_16 = fieldFormalParameter_period,
-        _variantField_17 = fieldFormalParameter_thisKeyword,
+        _variantField_18 = normalFormalParameter_requiredKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
+        _variantField_27 = inheritsCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
 
   LinkedNodeBuilder.functionTypedFormalParameter({
@@ -10087,12 +10304,12 @@
     LinkedNodeBuilder functionTypedFormalParameter_formalParameters,
     LinkedNodeBuilder functionTypedFormalParameter_returnType,
     LinkedNodeBuilder functionTypedFormalParameter_typeParameters,
+    int normalFormalParameter_requiredKeyword,
     int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
+    bool inheritsCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     int codeLength,
     int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
   })  : _kind = idl.LinkedNodeKind.functionTypedFormalParameter,
         _variantField_24 = actualType,
@@ -10100,12 +10317,12 @@
         _variantField_6 = functionTypedFormalParameter_formalParameters,
         _variantField_7 = functionTypedFormalParameter_returnType,
         _variantField_8 = functionTypedFormalParameter_typeParameters,
+        _variantField_18 = normalFormalParameter_requiredKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
+        _variantField_27 = inheritsCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
         _variantField_14 = normalFormalParameter_comment;
 
   LinkedNodeBuilder.simpleFormalParameter({
@@ -10113,25 +10330,27 @@
     List<LinkedNodeBuilder> normalFormalParameter_metadata,
     LinkedNodeBuilder simpleFormalParameter_type,
     int simpleFormalParameter_keyword,
+    int normalFormalParameter_requiredKeyword,
     int normalFormalParameter_covariantKeyword,
-    bool normalFormalParameter_isCovariant,
+    bool inheritsCovariant,
     LinkedNodeBuilder normalFormalParameter_identifier,
     int codeLength,
     int codeOffset,
-    idl.LinkedNodeFormalParameterKind formalParameter_kind,
     LinkedNodeBuilder normalFormalParameter_comment,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
   })  : _kind = idl.LinkedNodeKind.simpleFormalParameter,
         _variantField_24 = actualType,
         _variantField_4 = normalFormalParameter_metadata,
         _variantField_6 = simpleFormalParameter_type,
         _variantField_15 = simpleFormalParameter_keyword,
+        _variantField_18 = normalFormalParameter_requiredKeyword,
         _variantField_19 = normalFormalParameter_covariantKeyword,
-        _variantField_27 = normalFormalParameter_isCovariant,
+        _variantField_27 = inheritsCovariant,
         _variantField_12 = normalFormalParameter_identifier,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
-        _variantField_26 = formalParameter_kind,
-        _variantField_14 = normalFormalParameter_comment;
+        _variantField_14 = normalFormalParameter_comment,
+        _variantField_35 = topLevelTypeInferenceError;
 
   LinkedNodeBuilder.variableDeclaration({
     LinkedNodeTypeBuilder actualType,
@@ -10140,8 +10359,10 @@
     LinkedNodeBuilder variableDeclaration_initializer,
     int variableDeclaration_equals,
     LinkedNodeBuilder variableDeclaration_name,
+    bool inheritsCovariant,
     int codeLength,
     int codeOffset,
+    TopLevelInferenceErrorBuilder topLevelTypeInferenceError,
     LinkedNodeVariablesDeclarationBuilder variableDeclaration_declaration,
   })  : _kind = idl.LinkedNodeKind.variableDeclaration,
         _variantField_24 = actualType,
@@ -10150,8 +10371,10 @@
         _variantField_6 = variableDeclaration_initializer,
         _variantField_15 = variableDeclaration_equals,
         _variantField_7 = variableDeclaration_name,
+        _variantField_27 = inheritsCovariant,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
+        _variantField_35 = topLevelTypeInferenceError,
         _variantField_32 = variableDeclaration_declaration;
 
   LinkedNodeBuilder.binaryExpression({
@@ -10159,16 +10382,16 @@
     LinkedNodeBuilder binaryExpression_leftOperand,
     int binaryExpression_element,
     LinkedNodeBuilder binaryExpression_rightOperand,
-    int binaryExpression_operator,
     LinkedNodeTypeBuilder binaryExpression_elementType,
+    int binaryExpression_operator,
     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_16 = binaryExpression_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.functionExpressionInvocation({
@@ -10235,17 +10458,30 @@
         _variantField_6 = cascadeExpression_target,
         _variantField_25 = expression_type;
 
+  LinkedNodeBuilder.comment({
+    List<LinkedNodeBuilder> comment_references,
+    List<int> comment_tokens,
+    idl.LinkedNodeCommentType comment_type,
+  })  : _kind = idl.LinkedNodeKind.comment,
+        _variantField_2 = comment_references,
+        _variantField_28 = comment_tokens,
+        _variantField_29 = comment_type;
+
   LinkedNodeBuilder.compilationUnit({
     List<LinkedNodeBuilder> compilationUnit_declarations,
     LinkedNodeBuilder compilationUnit_scriptTag,
     int compilationUnit_beginToken,
     int compilationUnit_endToken,
+    int codeLength,
+    int codeOffset,
     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_34 = codeLength,
+        _variantField_33 = codeOffset,
         _variantField_3 = compilationUnit_directives;
 
   LinkedNodeBuilder.constructorDeclaration({
@@ -10255,9 +10491,9 @@
     LinkedNodeBuilder constructorDeclaration_body,
     int constructorDeclaration_constKeyword,
     LinkedNodeBuilder constructorDeclaration_name,
+    int constructorDeclaration_factoryKeyword,
     LinkedNodeBuilder constructorDeclaration_parameters,
     int constructorDeclaration_externalKeyword,
-    int constructorDeclaration_factoryKeyword,
     int constructorDeclaration_period,
     int constructorDeclaration_separator,
     LinkedNodeBuilder constructorDeclaration_redirectedConstructor,
@@ -10271,9 +10507,9 @@
         _variantField_6 = constructorDeclaration_body,
         _variantField_15 = constructorDeclaration_constKeyword,
         _variantField_7 = constructorDeclaration_name,
+        _variantField_17 = constructorDeclaration_factoryKeyword,
         _variantField_8 = constructorDeclaration_parameters,
         _variantField_16 = constructorDeclaration_externalKeyword,
-        _variantField_17 = constructorDeclaration_factoryKeyword,
         _variantField_18 = constructorDeclaration_period,
         _variantField_19 = constructorDeclaration_separator,
         _variantField_9 = constructorDeclaration_redirectedConstructor,
@@ -10291,8 +10527,8 @@
     LinkedNodeBuilder annotatedNode_comment,
     List<LinkedNodeBuilder> annotatedNode_metadata,
     int enumDeclaration_enumKeyword,
-    int enumDeclaration_leftBracket,
     int enumDeclaration_rightBracket,
+    int enumDeclaration_leftBracket,
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder namedCompilationUnitMember_name,
@@ -10301,8 +10537,8 @@
         _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_15 = enumDeclaration_enumKeyword,
-        _variantField_16 = enumDeclaration_leftBracket,
         _variantField_17 = enumDeclaration_rightBracket,
+        _variantField_16 = enumDeclaration_leftBracket,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
         _variantField_14 = namedCompilationUnitMember_name;
@@ -10310,14 +10546,14 @@
   LinkedNodeBuilder.formalParameterList({
     List<LinkedNodeBuilder> formalParameterList_parameters,
     int formalParameterList_leftDelimiter,
-    int formalParameterList_leftParenthesis,
     int formalParameterList_rightDelimiter,
+    int formalParameterList_leftParenthesis,
     int formalParameterList_rightParenthesis,
   })  : _kind = idl.LinkedNodeKind.formalParameterList,
         _variantField_2 = formalParameterList_parameters,
         _variantField_15 = formalParameterList_leftDelimiter,
-        _variantField_16 = formalParameterList_leftParenthesis,
         _variantField_17 = formalParameterList_rightDelimiter,
+        _variantField_16 = formalParameterList_leftParenthesis,
         _variantField_18 = formalParameterList_rightParenthesis;
 
   LinkedNodeBuilder.hideCombinator({
@@ -10457,16 +10693,16 @@
     List<LinkedNodeBuilder> switchStatement_members,
     int switchStatement_leftParenthesis,
     LinkedNodeBuilder switchStatement_expression,
-    int switchStatement_rightParenthesis,
     int switchStatement_switchKeyword,
+    int switchStatement_rightParenthesis,
     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_16 = switchStatement_rightParenthesis,
         _variantField_18 = switchStatement_leftBracket,
         _variantField_19 = switchStatement_rightBracket;
 
@@ -10507,12 +10743,14 @@
     List<LinkedNodeBuilder> annotatedNode_metadata,
     LinkedNodeBuilder variableDeclarationList_type,
     int variableDeclarationList_keyword,
+    int variableDeclarationList_lateKeyword,
   })  : _kind = idl.LinkedNodeKind.variableDeclarationList,
         _variantField_2 = variableDeclarationList_variables,
         _variantField_11 = annotatedNode_comment,
         _variantField_4 = annotatedNode_metadata,
         _variantField_6 = variableDeclarationList_type,
-        _variantField_15 = variableDeclarationList_keyword;
+        _variantField_15 = variableDeclarationList_keyword,
+        _variantField_16 = variableDeclarationList_lateKeyword;
 
   LinkedNodeBuilder.withClause({
     List<LinkedNodeBuilder> withClause_mixinTypes,
@@ -10616,15 +10854,15 @@
     List<LinkedNodeBuilder> annotatedNode_metadata,
     LinkedNodeBuilder fieldDeclaration_fields,
     int fieldDeclaration_covariantKeyword,
-    int fieldDeclaration_semicolon,
     int fieldDeclaration_staticKeyword,
+    int fieldDeclaration_semicolon,
   })  : _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;
+        _variantField_17 = fieldDeclaration_staticKeyword,
+        _variantField_16 = fieldDeclaration_semicolon;
 
   LinkedNodeBuilder.genericTypeAlias({
     LinkedNodeBuilder annotatedNode_comment,
@@ -10634,6 +10872,7 @@
     int genericTypeAlias_equals,
     int typeAlias_typedefKeyword,
     int typeAlias_semicolon,
+    bool typeAlias_hasSelfReference,
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder namedCompilationUnitMember_name,
@@ -10646,6 +10885,7 @@
         _variantField_16 = genericTypeAlias_equals,
         _variantField_18 = typeAlias_typedefKeyword,
         _variantField_19 = typeAlias_semicolon,
+        _variantField_27 = typeAlias_hasSelfReference,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
         _variantField_14 = namedCompilationUnitMember_name,
@@ -10677,6 +10917,7 @@
     int codeLength,
     int codeOffset,
     LinkedNodeBuilder namedCompilationUnitMember_name,
+    List<String> mixinDeclaration_superInvokedNames,
     bool simplyBoundable_isSimplyBounded,
   })  : _kind = idl.LinkedNodeKind.mixinDeclaration,
         _variantField_11 = annotatedNode_comment,
@@ -10691,6 +10932,7 @@
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset,
         _variantField_14 = namedCompilationUnitMember_name,
+        _variantField_36 = mixinDeclaration_superInvokedNames,
         _variantField_31 = simplyBoundable_isSimplyBounded;
 
   LinkedNodeBuilder.partDirective({
@@ -10744,7 +10986,7 @@
     LinkedNodeBuilder typeParameter_bound,
     int typeParameter_extendsKeyword,
     LinkedNodeBuilder typeParameter_name,
-    int typeParameter_id,
+    LinkedNodeTypeBuilder typeParameter_defaultType,
     int codeLength,
     int codeOffset,
   })  : _kind = idl.LinkedNodeKind.typeParameter,
@@ -10753,7 +10995,7 @@
         _variantField_6 = typeParameter_bound,
         _variantField_15 = typeParameter_extendsKeyword,
         _variantField_7 = typeParameter_name,
-        _variantField_16 = typeParameter_id,
+        _variantField_23 = typeParameter_defaultType,
         _variantField_34 = codeLength,
         _variantField_33 = codeOffset;
 
@@ -10785,12 +11027,16 @@
     LinkedNodeBuilder annotation_arguments,
     int annotation_atSign,
     LinkedNodeBuilder annotation_constructorName,
+    int annotation_element,
+    LinkedNodeTypeBuilder annotation_elementType,
     LinkedNodeBuilder annotation_name,
     int annotation_period,
   })  : _kind = idl.LinkedNodeKind.annotation,
         _variantField_6 = annotation_arguments,
         _variantField_15 = annotation_atSign,
         _variantField_7 = annotation_constructorName,
+        _variantField_17 = annotation_element,
+        _variantField_23 = annotation_elementType,
         _variantField_8 = annotation_name,
         _variantField_16 = annotation_period;
 
@@ -10809,31 +11055,31 @@
     LinkedNodeBuilder assertInitializer_condition,
     int assertInitializer_assertKeyword,
     LinkedNodeBuilder assertInitializer_message,
-    int assertInitializer_comma,
     int assertInitializer_leftParenthesis,
+    int assertInitializer_comma,
     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_16 = assertInitializer_comma,
         _variantField_18 = assertInitializer_rightParenthesis;
 
   LinkedNodeBuilder.assertStatement({
     LinkedNodeBuilder assertStatement_condition,
     int assertStatement_assertKeyword,
     LinkedNodeBuilder assertStatement_message,
-    int assertStatement_comma,
     int assertStatement_leftParenthesis,
+    int assertStatement_comma,
     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_16 = assertStatement_comma,
         _variantField_18 = assertStatement_rightParenthesis,
         _variantField_19 = assertStatement_semicolon;
 
@@ -10841,15 +11087,15 @@
     LinkedNodeBuilder assignmentExpression_leftHandSide,
     int assignmentExpression_element,
     LinkedNodeBuilder assignmentExpression_rightHandSide,
-    int assignmentExpression_operator,
     LinkedNodeTypeBuilder assignmentExpression_elementType,
+    int assignmentExpression_operator,
     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_16 = assignmentExpression_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.awaitExpression({
@@ -10883,9 +11129,9 @@
     LinkedNodeBuilder catchClause_body,
     int catchClause_catchKeyword,
     LinkedNodeBuilder catchClause_exceptionParameter,
+    int catchClause_leftParenthesis,
     LinkedNodeBuilder catchClause_exceptionType,
     int catchClause_comma,
-    int catchClause_leftParenthesis,
     int catchClause_onKeyword,
     int catchClause_rightParenthesis,
     LinkedNodeBuilder catchClause_stackTraceParameter,
@@ -10893,13 +11139,20 @@
         _variantField_6 = catchClause_body,
         _variantField_15 = catchClause_catchKeyword,
         _variantField_7 = catchClause_exceptionParameter,
+        _variantField_17 = catchClause_leftParenthesis,
         _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.commentReference({
+    LinkedNodeBuilder commentReference_identifier,
+    int commentReference_newKeyword,
+  })  : _kind = idl.LinkedNodeKind.commentReference,
+        _variantField_6 = commentReference_identifier,
+        _variantField_15 = commentReference_newKeyword;
+
   LinkedNodeBuilder.conditionalExpression({
     LinkedNodeBuilder conditionalExpression_condition,
     int conditionalExpression_colon,
@@ -10919,44 +11172,44 @@
     LinkedNodeBuilder configuration_name,
     int configuration_ifKeyword,
     LinkedNodeBuilder configuration_value,
+    int configuration_rightParenthesis,
     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_17 = configuration_rightParenthesis,
         _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,
+    int constructorFieldInitializer_period,
   })  : _kind = idl.LinkedNodeKind.constructorFieldInitializer,
         _variantField_6 = constructorFieldInitializer_expression,
         _variantField_15 = constructorFieldInitializer_equals,
         _variantField_7 = constructorFieldInitializer_fieldName,
-        _variantField_16 = constructorFieldInitializer_period,
-        _variantField_17 = constructorFieldInitializer_thisKeyword;
+        _variantField_17 = constructorFieldInitializer_thisKeyword,
+        _variantField_16 = constructorFieldInitializer_period;
 
   LinkedNodeBuilder.constructorName({
     LinkedNodeBuilder constructorName_name,
     int constructorName_element,
     LinkedNodeBuilder constructorName_type,
-    int constructorName_period,
     LinkedNodeTypeBuilder constructorName_elementType,
+    int constructorName_period,
   })  : _kind = idl.LinkedNodeKind.constructorName,
         _variantField_6 = constructorName_name,
         _variantField_15 = constructorName_element,
         _variantField_7 = constructorName_type,
-        _variantField_16 = constructorName_period,
-        _variantField_23 = constructorName_elementType;
+        _variantField_23 = constructorName_elementType,
+        _variantField_16 = constructorName_period;
 
   LinkedNodeBuilder.continueStatement({
     LinkedNodeBuilder continueStatement_label,
@@ -10971,44 +11224,44 @@
     LinkedNodeBuilder defaultFormalParameter_defaultValue,
     int defaultFormalParameter_separator,
     LinkedNodeBuilder defaultFormalParameter_parameter,
-    bool defaultFormalParameter_isNamed,
     int codeLength,
     int codeOffset,
+    idl.LinkedNodeFormalParameterKind defaultFormalParameter_kind,
   })  : _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;
+        _variantField_33 = codeOffset,
+        _variantField_26 = defaultFormalParameter_kind;
 
   LinkedNodeBuilder.doStatement({
     LinkedNodeBuilder doStatement_body,
     int doStatement_leftParenthesis,
     LinkedNodeBuilder doStatement_condition,
-    int doStatement_rightParenthesis,
     int doStatement_doKeyword,
+    int doStatement_rightParenthesis,
     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_16 = doStatement_rightParenthesis,
         _variantField_18 = doStatement_semicolon,
         _variantField_19 = doStatement_whileKeyword;
 
   LinkedNodeBuilder.expressionFunctionBody({
     LinkedNodeBuilder expressionFunctionBody_expression,
     int expressionFunctionBody_arrow,
-    int expressionFunctionBody_keyword,
     int expressionFunctionBody_semicolon,
+    int expressionFunctionBody_keyword,
   })  : _kind = idl.LinkedNodeKind.expressionFunctionBody,
         _variantField_6 = expressionFunctionBody_expression,
         _variantField_15 = expressionFunctionBody_arrow,
-        _variantField_16 = expressionFunctionBody_keyword,
-        _variantField_17 = expressionFunctionBody_semicolon;
+        _variantField_17 = expressionFunctionBody_semicolon,
+        _variantField_16 = expressionFunctionBody_keyword;
 
   LinkedNodeBuilder.expressionStatement({
     LinkedNodeBuilder expressionStatement_expression,
@@ -11046,30 +11299,30 @@
     LinkedNodeBuilder forMixin_forLoopParts,
     int forMixin_awaitKeyword,
     LinkedNodeBuilder forElement_body,
-    int forMixin_forKeyword,
     int forMixin_leftParenthesis,
+    int forMixin_forKeyword,
     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_16 = forMixin_forKeyword,
         _variantField_19 = forMixin_rightParenthesis;
 
   LinkedNodeBuilder.forStatement({
     LinkedNodeBuilder forMixin_forLoopParts,
     int forMixin_awaitKeyword,
     LinkedNodeBuilder forStatement_body,
-    int forMixin_forKeyword,
     int forMixin_leftParenthesis,
+    int forMixin_forKeyword,
     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_16 = forMixin_forKeyword,
         _variantField_19 = forMixin_rightParenthesis;
 
   LinkedNodeBuilder.forPartsWithDeclarations({
@@ -11106,17 +11359,17 @@
   LinkedNodeBuilder.ifElement({
     LinkedNodeBuilder ifMixin_condition,
     int ifMixin_elseKeyword,
+    int ifMixin_leftParenthesis,
     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_17 = ifMixin_leftParenthesis,
         _variantField_8 = ifElement_thenElement,
         _variantField_16 = ifMixin_ifKeyword,
-        _variantField_17 = ifMixin_leftParenthesis,
         _variantField_18 = ifMixin_rightParenthesis,
         _variantField_9 = ifElement_elseElement;
 
@@ -11124,36 +11377,36 @@
     LinkedNodeBuilder ifMixin_condition,
     int ifMixin_elseKeyword,
     LinkedNodeBuilder ifStatement_elseStatement,
+    int ifMixin_leftParenthesis,
     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_17 = ifMixin_leftParenthesis,
         _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,
+    int indexExpression_period,
+    int indexExpression_rightBracket,
     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_16 = indexExpression_period,
+        _variantField_18 = indexExpression_rightBracket,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.instanceCreationExpression({
@@ -11246,14 +11499,14 @@
   LinkedNodeBuilder.postfixExpression({
     LinkedNodeBuilder postfixExpression_operand,
     int postfixExpression_element,
-    int postfixExpression_operator,
     LinkedNodeTypeBuilder postfixExpression_elementType,
+    int 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_16 = postfixExpression_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.prefixedIdentifier({
@@ -11270,14 +11523,14 @@
   LinkedNodeBuilder.prefixExpression({
     LinkedNodeBuilder prefixExpression_operand,
     int prefixExpression_element,
-    int prefixExpression_operator,
     LinkedNodeTypeBuilder prefixExpression_elementType,
+    int 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_16 = prefixExpression_operator,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.propertyAccess({
@@ -11295,16 +11548,16 @@
     LinkedNodeBuilder redirectingConstructorInvocation_arguments,
     int redirectingConstructorInvocation_element,
     LinkedNodeBuilder redirectingConstructorInvocation_constructorName,
-    int redirectingConstructorInvocation_period,
     int redirectingConstructorInvocation_thisKeyword,
     LinkedNodeTypeBuilder redirectingConstructorInvocation_elementType,
+    int redirectingConstructorInvocation_period,
   })  : _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_16 = redirectingConstructorInvocation_period;
 
   LinkedNodeBuilder.returnStatement({
     LinkedNodeBuilder returnStatement_expression,
@@ -11326,16 +11579,16 @@
     LinkedNodeBuilder superConstructorInvocation_arguments,
     int superConstructorInvocation_element,
     LinkedNodeBuilder superConstructorInvocation_constructorName,
-    int superConstructorInvocation_period,
     int superConstructorInvocation_superKeyword,
     LinkedNodeTypeBuilder superConstructorInvocation_elementType,
+    int superConstructorInvocation_period,
   })  : _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;
+        _variantField_23 = superConstructorInvocation_elementType,
+        _variantField_16 = superConstructorInvocation_period;
 
   LinkedNodeBuilder.throwExpression({
     LinkedNodeBuilder throwExpression_expression,
@@ -11368,25 +11621,25 @@
     LinkedNodeBuilder whileStatement_body,
     int whileStatement_leftParenthesis,
     LinkedNodeBuilder whileStatement_condition,
-    int whileStatement_rightParenthesis,
     int whileStatement_whileKeyword,
+    int whileStatement_rightParenthesis,
   })  : _kind = idl.LinkedNodeKind.whileStatement,
         _variantField_6 = whileStatement_body,
         _variantField_15 = whileStatement_leftParenthesis,
         _variantField_7 = whileStatement_condition,
-        _variantField_16 = whileStatement_rightParenthesis,
-        _variantField_17 = whileStatement_whileKeyword;
+        _variantField_17 = whileStatement_whileKeyword,
+        _variantField_16 = whileStatement_rightParenthesis;
 
   LinkedNodeBuilder.yieldStatement({
     LinkedNodeBuilder yieldStatement_expression,
     int yieldStatement_yieldKeyword,
-    int yieldStatement_star,
     int yieldStatement_semicolon,
+    int yieldStatement_star,
   })  : _kind = idl.LinkedNodeKind.yieldStatement,
         _variantField_6 = yieldStatement_expression,
         _variantField_15 = yieldStatement_yieldKeyword,
-        _variantField_16 = yieldStatement_star,
-        _variantField_17 = yieldStatement_semicolon;
+        _variantField_17 = yieldStatement_semicolon,
+        _variantField_16 = yieldStatement_star;
 
   LinkedNodeBuilder.booleanLiteral({
     int booleanLiteral_literal,
@@ -11453,13 +11706,15 @@
 
   LinkedNodeBuilder.simpleIdentifier({
     int simpleIdentifier_element,
-    int simpleIdentifier_token,
     LinkedNodeTypeBuilder simpleIdentifier_elementType,
+    int simpleIdentifier_token,
+    bool simpleIdentifier_isDeclaration,
     LinkedNodeTypeBuilder expression_type,
   })  : _kind = idl.LinkedNodeKind.simpleIdentifier,
         _variantField_15 = simpleIdentifier_element,
-        _variantField_16 = simpleIdentifier_token,
         _variantField_23 = simpleIdentifier_elementType,
+        _variantField_16 = simpleIdentifier_token,
+        _variantField_27 = simpleIdentifier_isDeclaration,
         _variantField_25 = expression_type;
 
   LinkedNodeBuilder.simpleStringLiteral({
@@ -11494,13 +11749,6 @@
         _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;
-
   /// Flush [informative] data recursively.
   void flushInformative() {
     _variantField_24?.flushInformative();
@@ -11509,8 +11757,8 @@
     _variantField_4?.forEach((b) => b.flushInformative());
     _variantField_6?.flushInformative();
     _variantField_7?.flushInformative();
-    _variantField_8?.flushInformative();
     _variantField_23?.flushInformative();
+    _variantField_8?.flushInformative();
     _variantField_9?.flushInformative();
     _variantField_12?.flushInformative();
     _variantField_5?.forEach((b) => b.flushInformative());
@@ -11519,6 +11767,7 @@
     _variantField_10?.flushInformative();
     _variantField_25?.flushInformative();
     _variantField_14?.flushInformative();
+    _variantField_35?.flushInformative();
     _variantField_32?.flushInformative();
   }
 
@@ -11609,6 +11858,16 @@
     this._variantField_32?.collectApiSignature(signature);
     signature.addInt(this._variantField_33 ?? 0);
     signature.addInt(this._variantField_34 ?? 0);
+    signature.addBool(this._variantField_35 != null);
+    this._variantField_35?.collectApiSignature(signature);
+    if (this._variantField_36 == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._variantField_36.length);
+      for (var x in this._variantField_36) {
+        signature.addString(x);
+      }
+    }
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -11618,8 +11877,8 @@
     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;
@@ -11630,7 +11889,9 @@
     fb.Offset offset_variantField_25;
     fb.Offset offset_variantField_30;
     fb.Offset offset_variantField_14;
+    fb.Offset offset_variantField_36;
     fb.Offset offset_variantField_20;
+    fb.Offset offset_variantField_35;
     fb.Offset offset_variantField_22;
     fb.Offset offset_variantField_32;
     if (_variantField_24 != null) {
@@ -11653,12 +11914,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);
     }
@@ -11691,9 +11952,16 @@
     if (_variantField_14 != null) {
       offset_variantField_14 = _variantField_14.finish(fbBuilder);
     }
+    if (!(_variantField_36 == null || _variantField_36.isEmpty)) {
+      offset_variantField_36 = fbBuilder.writeList(
+          _variantField_36.map((b) => fbBuilder.writeString(b)).toList());
+    }
     if (_variantField_20 != null) {
       offset_variantField_20 = fbBuilder.writeString(_variantField_20);
     }
+    if (_variantField_35 != null) {
+      offset_variantField_35 = _variantField_35.finish(fbBuilder);
+    }
     if (_variantField_22 != null) {
       offset_variantField_22 = fbBuilder.writeString(_variantField_22);
     }
@@ -11722,24 +11990,24 @@
     if (offset_variantField_7 != null) {
       fbBuilder.addOffset(7, offset_variantField_7);
     }
+    if (_variantField_17 != null && _variantField_17 != 0) {
+      fbBuilder.addUint32(17, _variantField_17);
+    }
+    if (offset_variantField_23 != null) {
+      fbBuilder.addOffset(23, offset_variantField_23);
+    }
     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 (_variantField_27 == true) {
       fbBuilder.addBool(27, true);
     }
@@ -11774,16 +12042,17 @@
     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 (offset_variantField_30 != null) {
       fbBuilder.addOffset(30, offset_variantField_30);
     }
@@ -11796,12 +12065,18 @@
     if (_kind != null && _kind != idl.LinkedNodeKind.adjacentStrings) {
       fbBuilder.addUint8(0, _kind.index);
     }
+    if (offset_variantField_36 != null) {
+      fbBuilder.addOffset(36, offset_variantField_36);
+    }
     if (offset_variantField_20 != null) {
       fbBuilder.addOffset(20, offset_variantField_20);
     }
     if (_variantField_31 == true) {
       fbBuilder.addBool(31, true);
     }
+    if (offset_variantField_35 != null) {
+      fbBuilder.addOffset(35, offset_variantField_35);
+    }
     if (offset_variantField_22 != null) {
       fbBuilder.addOffset(22, offset_variantField_22);
     }
@@ -11835,12 +12110,12 @@
   idl.LinkedNode _variantField_6;
   int _variantField_15;
   idl.LinkedNode _variantField_7;
+  int _variantField_17;
+  idl.LinkedNodeType _variantField_23;
   idl.LinkedNode _variantField_8;
   int _variantField_16;
-  int _variantField_17;
   int _variantField_18;
   int _variantField_19;
-  idl.LinkedNodeType _variantField_23;
   bool _variantField_27;
   idl.LinkedNode _variantField_9;
   idl.LinkedNode _variantField_12;
@@ -11852,15 +12127,17 @@
   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;
   String _variantField_30;
   idl.LinkedNode _variantField_14;
   bool _isSynthetic;
   idl.LinkedNodeKind _kind;
+  List<String> _variantField_36;
   String _variantField_20;
   bool _variantField_31;
+  idl.TopLevelInferenceError _variantField_35;
   String _variantField_22;
   idl.LinkedNodeVariablesDeclaration _variantField_32;
 
@@ -11941,6 +12218,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 ??=
@@ -12313,6 +12599,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 ??=
@@ -12957,6 +13251,14 @@
   }
 
   @override
+  int get commentReference_newKeyword {
+    assert(kind == idl.LinkedNodeKind.commentReference);
+    _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 ??=
@@ -13970,6 +14272,288 @@
   }
 
   @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 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 genericFunctionType_id {
+    assert(kind == idl.LinkedNodeKind.genericFunctionType);
+    _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
+  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 ??=
@@ -14518,16 +15102,16 @@
   }
 
   @override
-  int get typeParameter_id {
-    assert(kind == idl.LinkedNodeKind.typeParameter);
+  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 typeParameterList_rightBracket {
-    assert(kind == idl.LinkedNodeKind.typeParameterList);
+  int get variableDeclarationList_lateKeyword {
+    assert(kind == idl.LinkedNodeKind.variableDeclarationList);
     _variantField_16 ??=
         const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
     return _variantField_16;
@@ -14550,176 +15134,6 @@
   }
 
   @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 ??=
@@ -14822,6 +15236,16 @@
   }
 
   @override
+  int get normalFormalParameter_requiredKeyword {
+    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
+        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
+        kind == idl.LinkedNodeKind.simpleFormalParameter);
+    _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 ??=
@@ -14954,86 +15378,6 @@
   }
 
   @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
   bool get booleanLiteral_value {
     assert(kind == idl.LinkedNodeKind.booleanLiteral);
     _variantField_27 ??=
@@ -15050,18 +15394,11 @@
   }
 
   @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;
@@ -15076,6 +15413,23 @@
   }
 
   @override
+  bool get simpleIdentifier_isDeclaration {
+    assert(kind == idl.LinkedNodeKind.simpleIdentifier);
+    _variantField_27 ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 27, false);
+    return _variantField_27;
+  }
+
+  @override
+  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;
+  }
+
+  @override
   idl.LinkedNode get catchClause_stackTraceParameter {
     assert(kind == idl.LinkedNodeKind.catchClause);
     _variantField_9 ??=
@@ -15176,6 +15530,7 @@
   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 ||
@@ -15198,6 +15553,7 @@
   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 ||
@@ -15298,6 +15654,17 @@
   }
 
   @override
+  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
   double get doubleLiteral_value {
     assert(kind == idl.LinkedNodeKind.doubleLiteral);
     _variantField_21 ??=
@@ -15353,16 +15720,6 @@
   }
 
   @override
-  idl.LinkedNodeFormalParameterKind get formalParameter_kind {
-    assert(kind == idl.LinkedNodeKind.fieldFormalParameter ||
-        kind == idl.LinkedNodeKind.functionTypedFormalParameter ||
-        kind == idl.LinkedNodeKind.simpleFormalParameter);
-    _variantField_26 ??= const _LinkedNodeFormalParameterKindReader().vTableGet(
-        _bc, _bcOffset, 26, idl.LinkedNodeFormalParameterKind.required);
-    return _variantField_26;
-  }
-
-  @override
   String get interpolationString_value {
     assert(kind == idl.LinkedNodeKind.interpolationString);
     _variantField_30 ??=
@@ -15436,6 +15793,14 @@
   }
 
   @override
+  List<String> get mixinDeclaration_superInvokedNames {
+    assert(kind == idl.LinkedNodeKind.mixinDeclaration);
+    _variantField_36 ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 36, const <String>[]);
+    return _variantField_36;
+  }
+
+  @override
   String get namespaceDirective_selectedUri {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective);
@@ -15473,6 +15838,15 @@
   }
 
   @override
+  idl.TopLevelInferenceError get topLevelTypeInferenceError {
+    assert(kind == idl.LinkedNodeKind.simpleFormalParameter ||
+        kind == idl.LinkedNodeKind.variableDeclaration);
+    _variantField_35 ??= const _TopLevelInferenceErrorReader()
+        .vTableGet(_bc, _bcOffset, 35, null);
+    return _variantField_35;
+  }
+
+  @override
   String get uriBasedDirective_uriContent {
     assert(kind == idl.LinkedNodeKind.exportDirective ||
         kind == idl.LinkedNodeKind.importDirective ||
@@ -15557,6 +15931,8 @@
         _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
       if (typeAlias_semicolon != 0)
         _result["typeAlias_semicolon"] = typeAlias_semicolon;
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
       if (namedCompilationUnitMember_name != null)
@@ -15578,6 +15954,8 @@
       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();
@@ -15602,15 +15980,15 @@
       if (methodDeclaration_formalParameters != null)
         _result["methodDeclaration_formalParameters"] =
             methodDeclaration_formalParameters.toJson();
+      if (methodDeclaration_operatorKeyword != 0)
+        _result["methodDeclaration_operatorKeyword"] =
+            methodDeclaration_operatorKeyword;
       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;
@@ -15640,28 +16018,27 @@
       if (fieldFormalParameter_typeParameters != null)
         _result["fieldFormalParameter_typeParameters"] =
             fieldFormalParameter_typeParameters.toJson();
+      if (fieldFormalParameter_thisKeyword != 0)
+        _result["fieldFormalParameter_thisKeyword"] =
+            fieldFormalParameter_thisKeyword;
       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_requiredKeyword != 0)
+        _result["normalFormalParameter_requiredKeyword"] =
+            normalFormalParameter_requiredKeyword;
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
       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();
@@ -15682,20 +16059,19 @@
       if (functionTypedFormalParameter_typeParameters != null)
         _result["functionTypedFormalParameter_typeParameters"] =
             functionTypedFormalParameter_typeParameters.toJson();
+      if (normalFormalParameter_requiredKeyword != 0)
+        _result["normalFormalParameter_requiredKeyword"] =
+            normalFormalParameter_requiredKeyword;
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
       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();
@@ -15713,23 +16089,25 @@
       if (simpleFormalParameter_keyword != 0)
         _result["simpleFormalParameter_keyword"] =
             simpleFormalParameter_keyword;
+      if (normalFormalParameter_requiredKeyword != 0)
+        _result["normalFormalParameter_requiredKeyword"] =
+            normalFormalParameter_requiredKeyword;
       if (normalFormalParameter_covariantKeyword != 0)
         _result["normalFormalParameter_covariantKeyword"] =
             normalFormalParameter_covariantKeyword;
-      if (normalFormalParameter_isCovariant != false)
-        _result["normalFormalParameter_isCovariant"] =
-            normalFormalParameter_isCovariant;
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
       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 (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
     }
     if (kind == idl.LinkedNodeKind.variableDeclaration) {
       if (actualType != null) _result["actualType"] = actualType.toJson();
@@ -15745,8 +16123,13 @@
         _result["variableDeclaration_equals"] = variableDeclaration_equals;
       if (variableDeclaration_name != null)
         _result["variableDeclaration_name"] = variableDeclaration_name.toJson();
+      if (inheritsCovariant != false)
+        _result["inheritsCovariant"] = inheritsCovariant;
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
+      if (topLevelTypeInferenceError != null)
+        _result["topLevelTypeInferenceError"] =
+            topLevelTypeInferenceError.toJson();
       if (variableDeclaration_declaration != null)
         _result["variableDeclaration_declaration"] =
             variableDeclaration_declaration.toJson();
@@ -15763,11 +16146,11 @@
       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 (binaryExpression_operator != 0)
+        _result["binaryExpression_operator"] = binaryExpression_operator;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -15843,6 +16226,14 @@
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
+    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.compilationUnit) {
       if (compilationUnit_declarations.isNotEmpty)
         _result["compilationUnit_declarations"] = compilationUnit_declarations
@@ -15855,6 +16246,8 @@
         _result["compilationUnit_beginToken"] = compilationUnit_beginToken;
       if (compilationUnit_endToken != 0)
         _result["compilationUnit_endToken"] = compilationUnit_endToken;
+      if (codeLength != 0) _result["codeLength"] = codeLength;
+      if (codeOffset != 0) _result["codeOffset"] = codeOffset;
       if (compilationUnit_directives.isNotEmpty)
         _result["compilationUnit_directives"] = compilationUnit_directives
             .map((_value) => _value.toJson())
@@ -15880,15 +16273,15 @@
       if (constructorDeclaration_name != null)
         _result["constructorDeclaration_name"] =
             constructorDeclaration_name.toJson();
+      if (constructorDeclaration_factoryKeyword != 0)
+        _result["constructorDeclaration_factoryKeyword"] =
+            constructorDeclaration_factoryKeyword;
       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;
@@ -15920,10 +16313,10 @@
             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 (enumDeclaration_leftBracket != 0)
+        _result["enumDeclaration_leftBracket"] = enumDeclaration_leftBracket;
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
       if (namedCompilationUnitMember_name != null)
@@ -15939,12 +16332,12 @@
       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_leftParenthesis != 0)
+        _result["formalParameterList_leftParenthesis"] =
+            formalParameterList_leftParenthesis;
       if (formalParameterList_rightParenthesis != 0)
         _result["formalParameterList_rightParenthesis"] =
             formalParameterList_rightParenthesis;
@@ -16117,12 +16510,12 @@
       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_rightParenthesis != 0)
+        _result["switchStatement_rightParenthesis"] =
+            switchStatement_rightParenthesis;
       if (switchStatement_leftBracket != 0)
         _result["switchStatement_leftBracket"] = switchStatement_leftBracket;
       if (switchStatement_rightBracket != 0)
@@ -16183,6 +16576,9 @@
       if (variableDeclarationList_keyword != 0)
         _result["variableDeclarationList_keyword"] =
             variableDeclarationList_keyword;
+      if (variableDeclarationList_lateKeyword != 0)
+        _result["variableDeclarationList_lateKeyword"] =
+            variableDeclarationList_lateKeyword;
     }
     if (kind == idl.LinkedNodeKind.withClause) {
       if (withClause_mixinTypes.isNotEmpty)
@@ -16312,11 +16708,11 @@
       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 (fieldDeclaration_semicolon != 0)
+        _result["fieldDeclaration_semicolon"] = fieldDeclaration_semicolon;
     }
     if (kind == idl.LinkedNodeKind.genericTypeAlias) {
       if (annotatedNode_comment != null)
@@ -16336,6 +16732,8 @@
         _result["typeAlias_typedefKeyword"] = typeAlias_typedefKeyword;
       if (typeAlias_semicolon != 0)
         _result["typeAlias_semicolon"] = typeAlias_semicolon;
+      if (typeAlias_hasSelfReference != false)
+        _result["typeAlias_hasSelfReference"] = typeAlias_hasSelfReference;
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
       if (namedCompilationUnitMember_name != null)
@@ -16392,6 +16790,9 @@
       if (namedCompilationUnitMember_name != null)
         _result["namedCompilationUnitMember_name"] =
             namedCompilationUnitMember_name.toJson();
+      if (mixinDeclaration_superInvokedNames.isNotEmpty)
+        _result["mixinDeclaration_superInvokedNames"] =
+            mixinDeclaration_superInvokedNames;
       if (simplyBoundable_isSimplyBounded != false)
         _result["simplyBoundable_isSimplyBounded"] =
             simplyBoundable_isSimplyBounded;
@@ -16456,7 +16857,9 @@
         _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 (typeParameter_defaultType != null)
+        _result["typeParameter_defaultType"] =
+            typeParameter_defaultType.toJson();
       if (codeLength != 0) _result["codeLength"] = codeLength;
       if (codeOffset != 0) _result["codeOffset"] = codeOffset;
     }
@@ -16494,6 +16897,10 @@
       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 (annotation_period != 0)
@@ -16519,11 +16926,11 @@
       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_comma != 0)
+        _result["assertInitializer_comma"] = assertInitializer_comma;
       if (assertInitializer_rightParenthesis != 0)
         _result["assertInitializer_rightParenthesis"] =
             assertInitializer_rightParenthesis;
@@ -16537,11 +16944,11 @@
             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_comma != 0)
+        _result["assertStatement_comma"] = assertStatement_comma;
       if (assertStatement_rightParenthesis != 0)
         _result["assertStatement_rightParenthesis"] =
             assertStatement_rightParenthesis;
@@ -16557,12 +16964,12 @@
       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 (assignmentExpression_operator != 0)
+        _result["assignmentExpression_operator"] =
+            assignmentExpression_operator;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -16599,13 +17006,13 @@
       if (catchClause_exceptionParameter != null)
         _result["catchClause_exceptionParameter"] =
             catchClause_exceptionParameter.toJson();
+      if (catchClause_leftParenthesis != 0)
+        _result["catchClause_leftParenthesis"] = catchClause_leftParenthesis;
       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)
@@ -16614,6 +17021,13 @@
         _result["catchClause_stackTraceParameter"] =
             catchClause_stackTraceParameter.toJson();
     }
+    if (kind == idl.LinkedNodeKind.commentReference) {
+      if (commentReference_identifier != null)
+        _result["commentReference_identifier"] =
+            commentReference_identifier.toJson();
+      if (commentReference_newKeyword != 0)
+        _result["commentReference_newKeyword"] = commentReference_newKeyword;
+    }
     if (kind == idl.LinkedNodeKind.conditionalExpression) {
       if (conditionalExpression_condition != null)
         _result["conditionalExpression_condition"] =
@@ -16639,14 +17053,14 @@
         _result["configuration_ifKeyword"] = configuration_ifKeyword;
       if (configuration_value != null)
         _result["configuration_value"] = configuration_value.toJson();
+      if (configuration_rightParenthesis != 0)
+        _result["configuration_rightParenthesis"] =
+            configuration_rightParenthesis;
       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;
     }
@@ -16660,12 +17074,12 @@
       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 (constructorFieldInitializer_period != 0)
+        _result["constructorFieldInitializer_period"] =
+            constructorFieldInitializer_period;
     }
     if (kind == idl.LinkedNodeKind.constructorName) {
       if (constructorName_name != null)
@@ -16674,11 +17088,11 @@
         _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 (constructorName_period != 0)
+        _result["constructorName_period"] = constructorName_period;
     }
     if (kind == idl.LinkedNodeKind.continueStatement) {
       if (continueStatement_label != null)
@@ -16699,11 +17113,12 @@
       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 (defaultFormalParameter_kind !=
+          idl.LinkedNodeFormalParameterKind.requiredPositional)
+        _result["defaultFormalParameter_kind"] =
+            defaultFormalParameter_kind.toString().split('.')[1];
     }
     if (kind == idl.LinkedNodeKind.doStatement) {
       if (doStatement_body != null)
@@ -16712,10 +17127,10 @@
         _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_rightParenthesis != 0)
+        _result["doStatement_rightParenthesis"] = doStatement_rightParenthesis;
       if (doStatement_semicolon != 0)
         _result["doStatement_semicolon"] = doStatement_semicolon;
       if (doStatement_whileKeyword != 0)
@@ -16727,12 +17142,12 @@
             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 (expressionFunctionBody_keyword != 0)
+        _result["expressionFunctionBody_keyword"] =
+            expressionFunctionBody_keyword;
     }
     if (kind == idl.LinkedNodeKind.expressionStatement) {
       if (expressionStatement_expression != null)
@@ -16773,10 +17188,10 @@
         _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_forKeyword != 0)
+        _result["forMixin_forKeyword"] = forMixin_forKeyword;
       if (forMixin_rightParenthesis != 0)
         _result["forMixin_rightParenthesis"] = forMixin_rightParenthesis;
     }
@@ -16787,10 +17202,10 @@
         _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_forKeyword != 0)
+        _result["forMixin_forKeyword"] = forMixin_forKeyword;
       if (forMixin_rightParenthesis != 0)
         _result["forMixin_rightParenthesis"] = forMixin_rightParenthesis;
     }
@@ -16832,12 +17247,12 @@
         _result["ifMixin_condition"] = ifMixin_condition.toJson();
       if (ifMixin_elseKeyword != 0)
         _result["ifMixin_elseKeyword"] = ifMixin_elseKeyword;
+      if (ifMixin_leftParenthesis != 0)
+        _result["ifMixin_leftParenthesis"] = ifMixin_leftParenthesis;
       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)
@@ -16851,13 +17266,13 @@
       if (ifStatement_elseStatement != null)
         _result["ifStatement_elseStatement"] =
             ifStatement_elseStatement.toJson();
+      if (ifMixin_leftParenthesis != 0)
+        _result["ifMixin_leftParenthesis"] = ifMixin_leftParenthesis;
       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;
     }
@@ -16868,15 +17283,15 @@
         _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 (indexExpression_period != 0)
+        _result["indexExpression_period"] = indexExpression_period;
+      if (indexExpression_rightBracket != 0)
+        _result["indexExpression_rightBracket"] = indexExpression_rightBracket;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -16975,11 +17390,11 @@
             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 (postfixExpression_operator != 0)
+        _result["postfixExpression_operator"] = postfixExpression_operator;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -17000,11 +17415,11 @@
         _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 (prefixExpression_operator != 0)
+        _result["prefixExpression_operator"] = prefixExpression_operator;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -17029,15 +17444,15 @@
       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 (redirectingConstructorInvocation_period != 0)
+        _result["redirectingConstructorInvocation_period"] =
+            redirectingConstructorInvocation_period;
     }
     if (kind == idl.LinkedNodeKind.returnStatement) {
       if (returnStatement_expression != null)
@@ -17065,15 +17480,15 @@
       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 (superConstructorInvocation_period != 0)
+        _result["superConstructorInvocation_period"] =
+            superConstructorInvocation_period;
     }
     if (kind == idl.LinkedNodeKind.throwExpression) {
       if (throwExpression_expression != null)
@@ -17110,11 +17525,11 @@
             whileStatement_leftParenthesis;
       if (whileStatement_condition != null)
         _result["whileStatement_condition"] = whileStatement_condition.toJson();
+      if (whileStatement_whileKeyword != 0)
+        _result["whileStatement_whileKeyword"] = whileStatement_whileKeyword;
       if (whileStatement_rightParenthesis != 0)
         _result["whileStatement_rightParenthesis"] =
             whileStatement_rightParenthesis;
-      if (whileStatement_whileKeyword != 0)
-        _result["whileStatement_whileKeyword"] = whileStatement_whileKeyword;
     }
     if (kind == idl.LinkedNodeKind.yieldStatement) {
       if (yieldStatement_expression != null)
@@ -17122,10 +17537,10 @@
             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 (yieldStatement_star != 0)
+        _result["yieldStatement_star"] = yieldStatement_star;
     }
     if (kind == idl.LinkedNodeKind.booleanLiteral) {
       if (booleanLiteral_literal != 0)
@@ -17187,11 +17602,14 @@
     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 (simpleIdentifier_token != 0)
+        _result["simpleIdentifier_token"] = simpleIdentifier_token;
+      if (simpleIdentifier_isDeclaration != false)
+        _result["simpleIdentifier_isDeclaration"] =
+            simpleIdentifier_isDeclaration;
       if (expression_type != null)
         _result["expression_type"] = expression_type.toJson();
     }
@@ -17223,11 +17641,6 @@
       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;
   }
 
@@ -17274,6 +17687,7 @@
         "functionTypeAlias_typeParameters": functionTypeAlias_typeParameters,
         "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
         "typeAlias_semicolon": typeAlias_semicolon,
+        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
@@ -17290,6 +17704,7 @@
         "genericFunctionType_functionKeyword":
             genericFunctionType_functionKeyword,
         "genericFunctionType_returnType": genericFunctionType_returnType,
+        "genericFunctionType_id": genericFunctionType_id,
         "genericFunctionType_formalParameters":
             genericFunctionType_formalParameters,
         "genericFunctionType_question": genericFunctionType_question,
@@ -17307,9 +17722,9 @@
         "methodDeclaration_externalKeyword": methodDeclaration_externalKeyword,
         "methodDeclaration_formalParameters":
             methodDeclaration_formalParameters,
+        "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
         "methodDeclaration_returnType": methodDeclaration_returnType,
         "methodDeclaration_modifierKeyword": methodDeclaration_modifierKeyword,
-        "methodDeclaration_operatorKeyword": methodDeclaration_operatorKeyword,
         "methodDeclaration_propertyKeyword": methodDeclaration_propertyKeyword,
         "methodDeclaration_actualProperty": methodDeclaration_actualProperty,
         "methodDeclaration_typeParameters": methodDeclaration_typeParameters,
@@ -17328,17 +17743,18 @@
         "fieldFormalParameter_keyword": fieldFormalParameter_keyword,
         "fieldFormalParameter_typeParameters":
             fieldFormalParameter_typeParameters,
+        "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
         "fieldFormalParameter_formalParameters":
             fieldFormalParameter_formalParameters,
         "fieldFormalParameter_period": fieldFormalParameter_period,
-        "fieldFormalParameter_thisKeyword": fieldFormalParameter_thisKeyword,
+        "normalFormalParameter_requiredKeyword":
+            normalFormalParameter_requiredKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
+        "inheritsCovariant": inheritsCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -17354,13 +17770,14 @@
             functionTypedFormalParameter_returnType,
         "functionTypedFormalParameter_typeParameters":
             functionTypedFormalParameter_typeParameters,
+        "normalFormalParameter_requiredKeyword":
+            normalFormalParameter_requiredKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
+        "inheritsCovariant": inheritsCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -17372,16 +17789,18 @@
         "normalFormalParameter_metadata": normalFormalParameter_metadata,
         "simpleFormalParameter_type": simpleFormalParameter_type,
         "simpleFormalParameter_keyword": simpleFormalParameter_keyword,
+        "normalFormalParameter_requiredKeyword":
+            normalFormalParameter_requiredKeyword,
         "normalFormalParameter_covariantKeyword":
             normalFormalParameter_covariantKeyword,
-        "normalFormalParameter_isCovariant": normalFormalParameter_isCovariant,
+        "inheritsCovariant": inheritsCovariant,
         "normalFormalParameter_identifier": normalFormalParameter_identifier,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
-        "formalParameter_kind": formalParameter_kind,
         "normalFormalParameter_comment": normalFormalParameter_comment,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
       };
     }
     if (kind == idl.LinkedNodeKind.variableDeclaration) {
@@ -17392,10 +17811,12 @@
         "variableDeclaration_initializer": variableDeclaration_initializer,
         "variableDeclaration_equals": variableDeclaration_equals,
         "variableDeclaration_name": variableDeclaration_name,
+        "inheritsCovariant": inheritsCovariant,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "topLevelTypeInferenceError": topLevelTypeInferenceError,
         "variableDeclaration_declaration": variableDeclaration_declaration,
       };
     }
@@ -17405,8 +17826,8 @@
         "binaryExpression_leftOperand": binaryExpression_leftOperand,
         "binaryExpression_element": binaryExpression_element,
         "binaryExpression_rightOperand": binaryExpression_rightOperand,
-        "binaryExpression_operator": binaryExpression_operator,
         "binaryExpression_elementType": binaryExpression_elementType,
+        "binaryExpression_operator": binaryExpression_operator,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -17474,12 +17895,23 @@
         "kind": kind,
       };
     }
+    if (kind == idl.LinkedNodeKind.comment) {
+      return {
+        "comment_references": comment_references,
+        "comment_tokens": comment_tokens,
+        "comment_type": comment_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,
+        "codeLength": codeLength,
+        "codeOffset": codeOffset,
         "compilationUnit_directives": compilationUnit_directives,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -17495,11 +17927,11 @@
         "constructorDeclaration_constKeyword":
             constructorDeclaration_constKeyword,
         "constructorDeclaration_name": constructorDeclaration_name,
+        "constructorDeclaration_factoryKeyword":
+            constructorDeclaration_factoryKeyword,
         "constructorDeclaration_parameters": constructorDeclaration_parameters,
         "constructorDeclaration_externalKeyword":
             constructorDeclaration_externalKeyword,
-        "constructorDeclaration_factoryKeyword":
-            constructorDeclaration_factoryKeyword,
         "constructorDeclaration_period": constructorDeclaration_period,
         "constructorDeclaration_separator": constructorDeclaration_separator,
         "constructorDeclaration_redirectedConstructor":
@@ -17524,8 +17956,8 @@
         "annotatedNode_comment": annotatedNode_comment,
         "annotatedNode_metadata": annotatedNode_metadata,
         "enumDeclaration_enumKeyword": enumDeclaration_enumKeyword,
-        "enumDeclaration_leftBracket": enumDeclaration_leftBracket,
         "enumDeclaration_rightBracket": enumDeclaration_rightBracket,
+        "enumDeclaration_leftBracket": enumDeclaration_leftBracket,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
@@ -17537,10 +17969,10 @@
       return {
         "formalParameterList_parameters": formalParameterList_parameters,
         "formalParameterList_leftDelimiter": formalParameterList_leftDelimiter,
-        "formalParameterList_leftParenthesis":
-            formalParameterList_leftParenthesis,
         "formalParameterList_rightDelimiter":
             formalParameterList_rightDelimiter,
+        "formalParameterList_leftParenthesis":
+            formalParameterList_leftParenthesis,
         "formalParameterList_rightParenthesis":
             formalParameterList_rightParenthesis,
         "isSynthetic": isSynthetic,
@@ -17669,8 +18101,8 @@
         "switchStatement_members": switchStatement_members,
         "switchStatement_leftParenthesis": switchStatement_leftParenthesis,
         "switchStatement_expression": switchStatement_expression,
-        "switchStatement_rightParenthesis": switchStatement_rightParenthesis,
         "switchStatement_switchKeyword": switchStatement_switchKeyword,
+        "switchStatement_rightParenthesis": switchStatement_rightParenthesis,
         "switchStatement_leftBracket": switchStatement_leftBracket,
         "switchStatement_rightBracket": switchStatement_rightBracket,
         "isSynthetic": isSynthetic,
@@ -17713,6 +18145,8 @@
         "annotatedNode_metadata": annotatedNode_metadata,
         "variableDeclarationList_type": variableDeclarationList_type,
         "variableDeclarationList_keyword": variableDeclarationList_keyword,
+        "variableDeclarationList_lateKeyword":
+            variableDeclarationList_lateKeyword,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17798,8 +18232,8 @@
         "annotatedNode_metadata": annotatedNode_metadata,
         "fieldDeclaration_fields": fieldDeclaration_fields,
         "fieldDeclaration_covariantKeyword": fieldDeclaration_covariantKeyword,
-        "fieldDeclaration_semicolon": fieldDeclaration_semicolon,
         "fieldDeclaration_staticKeyword": fieldDeclaration_staticKeyword,
+        "fieldDeclaration_semicolon": fieldDeclaration_semicolon,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -17813,6 +18247,7 @@
         "genericTypeAlias_equals": genericTypeAlias_equals,
         "typeAlias_typedefKeyword": typeAlias_typedefKeyword,
         "typeAlias_semicolon": typeAlias_semicolon,
+        "typeAlias_hasSelfReference": typeAlias_hasSelfReference,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
@@ -17852,6 +18287,8 @@
         "namedCompilationUnitMember_name": namedCompilationUnitMember_name,
         "isSynthetic": isSynthetic,
         "kind": kind,
+        "mixinDeclaration_superInvokedNames":
+            mixinDeclaration_superInvokedNames,
         "simplyBoundable_isSimplyBounded": simplyBoundable_isSimplyBounded,
       };
     }
@@ -17900,7 +18337,7 @@
         "typeParameter_bound": typeParameter_bound,
         "typeParameter_extendsKeyword": typeParameter_extendsKeyword,
         "typeParameter_name": typeParameter_name,
-        "typeParameter_id": typeParameter_id,
+        "typeParameter_defaultType": typeParameter_defaultType,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
         "isSynthetic": isSynthetic,
@@ -17933,6 +18370,8 @@
         "annotation_arguments": annotation_arguments,
         "annotation_atSign": annotation_atSign,
         "annotation_constructorName": annotation_constructorName,
+        "annotation_element": annotation_element,
+        "annotation_elementType": annotation_elementType,
         "annotation_name": annotation_name,
         "annotation_period": annotation_period,
         "isSynthetic": isSynthetic,
@@ -17954,8 +18393,8 @@
         "assertInitializer_condition": assertInitializer_condition,
         "assertInitializer_assertKeyword": assertInitializer_assertKeyword,
         "assertInitializer_message": assertInitializer_message,
-        "assertInitializer_comma": assertInitializer_comma,
         "assertInitializer_leftParenthesis": assertInitializer_leftParenthesis,
+        "assertInitializer_comma": assertInitializer_comma,
         "assertInitializer_rightParenthesis":
             assertInitializer_rightParenthesis,
         "isSynthetic": isSynthetic,
@@ -17967,8 +18406,8 @@
         "assertStatement_condition": assertStatement_condition,
         "assertStatement_assertKeyword": assertStatement_assertKeyword,
         "assertStatement_message": assertStatement_message,
-        "assertStatement_comma": assertStatement_comma,
         "assertStatement_leftParenthesis": assertStatement_leftParenthesis,
+        "assertStatement_comma": assertStatement_comma,
         "assertStatement_rightParenthesis": assertStatement_rightParenthesis,
         "assertStatement_semicolon": assertStatement_semicolon,
         "isSynthetic": isSynthetic,
@@ -17981,8 +18420,8 @@
         "assignmentExpression_element": assignmentExpression_element,
         "assignmentExpression_rightHandSide":
             assignmentExpression_rightHandSide,
-        "assignmentExpression_operator": assignmentExpression_operator,
         "assignmentExpression_elementType": assignmentExpression_elementType,
+        "assignmentExpression_operator": assignmentExpression_operator,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18020,9 +18459,9 @@
         "catchClause_body": catchClause_body,
         "catchClause_catchKeyword": catchClause_catchKeyword,
         "catchClause_exceptionParameter": catchClause_exceptionParameter,
+        "catchClause_leftParenthesis": catchClause_leftParenthesis,
         "catchClause_exceptionType": catchClause_exceptionType,
         "catchClause_comma": catchClause_comma,
-        "catchClause_leftParenthesis": catchClause_leftParenthesis,
         "catchClause_onKeyword": catchClause_onKeyword,
         "catchClause_rightParenthesis": catchClause_rightParenthesis,
         "catchClause_stackTraceParameter": catchClause_stackTraceParameter,
@@ -18030,6 +18469,14 @@
         "kind": kind,
       };
     }
+    if (kind == idl.LinkedNodeKind.commentReference) {
+      return {
+        "commentReference_identifier": commentReference_identifier,
+        "commentReference_newKeyword": commentReference_newKeyword,
+        "isSynthetic": isSynthetic,
+        "kind": kind,
+      };
+    }
     if (kind == idl.LinkedNodeKind.conditionalExpression) {
       return {
         "conditionalExpression_condition": conditionalExpression_condition,
@@ -18049,9 +18496,9 @@
         "configuration_name": configuration_name,
         "configuration_ifKeyword": configuration_ifKeyword,
         "configuration_value": configuration_value,
+        "configuration_rightParenthesis": configuration_rightParenthesis,
         "configuration_uri": configuration_uri,
         "configuration_leftParenthesis": configuration_leftParenthesis,
-        "configuration_rightParenthesis": configuration_rightParenthesis,
         "configuration_equalToken": configuration_equalToken,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18065,10 +18512,10 @@
             constructorFieldInitializer_equals,
         "constructorFieldInitializer_fieldName":
             constructorFieldInitializer_fieldName,
-        "constructorFieldInitializer_period":
-            constructorFieldInitializer_period,
         "constructorFieldInitializer_thisKeyword":
             constructorFieldInitializer_thisKeyword,
+        "constructorFieldInitializer_period":
+            constructorFieldInitializer_period,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18078,8 +18525,8 @@
         "constructorName_name": constructorName_name,
         "constructorName_element": constructorName_element,
         "constructorName_type": constructorName_type,
-        "constructorName_period": constructorName_period,
         "constructorName_elementType": constructorName_elementType,
+        "constructorName_period": constructorName_period,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18099,9 +18546,9 @@
             defaultFormalParameter_defaultValue,
         "defaultFormalParameter_separator": defaultFormalParameter_separator,
         "defaultFormalParameter_parameter": defaultFormalParameter_parameter,
-        "defaultFormalParameter_isNamed": defaultFormalParameter_isNamed,
         "codeLength": codeLength,
         "codeOffset": codeOffset,
+        "defaultFormalParameter_kind": defaultFormalParameter_kind,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18111,8 +18558,8 @@
         "doStatement_body": doStatement_body,
         "doStatement_leftParenthesis": doStatement_leftParenthesis,
         "doStatement_condition": doStatement_condition,
-        "doStatement_rightParenthesis": doStatement_rightParenthesis,
         "doStatement_doKeyword": doStatement_doKeyword,
+        "doStatement_rightParenthesis": doStatement_rightParenthesis,
         "doStatement_semicolon": doStatement_semicolon,
         "doStatement_whileKeyword": doStatement_whileKeyword,
         "isSynthetic": isSynthetic,
@@ -18123,8 +18570,8 @@
       return {
         "expressionFunctionBody_expression": expressionFunctionBody_expression,
         "expressionFunctionBody_arrow": expressionFunctionBody_arrow,
-        "expressionFunctionBody_keyword": expressionFunctionBody_keyword,
         "expressionFunctionBody_semicolon": expressionFunctionBody_semicolon,
+        "expressionFunctionBody_keyword": expressionFunctionBody_keyword,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18170,8 +18617,8 @@
         "forMixin_forLoopParts": forMixin_forLoopParts,
         "forMixin_awaitKeyword": forMixin_awaitKeyword,
         "forElement_body": forElement_body,
-        "forMixin_forKeyword": forMixin_forKeyword,
         "forMixin_leftParenthesis": forMixin_leftParenthesis,
+        "forMixin_forKeyword": forMixin_forKeyword,
         "forMixin_rightParenthesis": forMixin_rightParenthesis,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18182,8 +18629,8 @@
         "forMixin_forLoopParts": forMixin_forLoopParts,
         "forMixin_awaitKeyword": forMixin_awaitKeyword,
         "forStatement_body": forStatement_body,
-        "forMixin_forKeyword": forMixin_forKeyword,
         "forMixin_leftParenthesis": forMixin_leftParenthesis,
+        "forMixin_forKeyword": forMixin_forKeyword,
         "forMixin_rightParenthesis": forMixin_rightParenthesis,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18225,9 +18672,9 @@
       return {
         "ifMixin_condition": ifMixin_condition,
         "ifMixin_elseKeyword": ifMixin_elseKeyword,
+        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
         "ifElement_thenElement": ifElement_thenElement,
         "ifMixin_ifKeyword": ifMixin_ifKeyword,
-        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
         "ifMixin_rightParenthesis": ifMixin_rightParenthesis,
         "ifElement_elseElement": ifElement_elseElement,
         "isSynthetic": isSynthetic,
@@ -18239,9 +18686,9 @@
         "ifMixin_condition": ifMixin_condition,
         "ifMixin_elseKeyword": ifMixin_elseKeyword,
         "ifStatement_elseStatement": ifStatement_elseStatement,
+        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
         "ifStatement_thenStatement": ifStatement_thenStatement,
         "ifMixin_ifKeyword": ifMixin_ifKeyword,
-        "ifMixin_leftParenthesis": ifMixin_leftParenthesis,
         "ifMixin_rightParenthesis": ifMixin_rightParenthesis,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18252,10 +18699,10 @@
         "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,
+        "indexExpression_period": indexExpression_period,
+        "indexExpression_rightBracket": indexExpression_rightBracket,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18359,8 +18806,8 @@
       return {
         "postfixExpression_operand": postfixExpression_operand,
         "postfixExpression_element": postfixExpression_element,
-        "postfixExpression_operator": postfixExpression_operator,
         "postfixExpression_elementType": postfixExpression_elementType,
+        "postfixExpression_operator": postfixExpression_operator,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18380,8 +18827,8 @@
       return {
         "prefixExpression_operand": prefixExpression_operand,
         "prefixExpression_element": prefixExpression_element,
-        "prefixExpression_operator": prefixExpression_operator,
         "prefixExpression_elementType": prefixExpression_elementType,
+        "prefixExpression_operator": prefixExpression_operator,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18405,12 +18852,12 @@
             redirectingConstructorInvocation_element,
         "redirectingConstructorInvocation_constructorName":
             redirectingConstructorInvocation_constructorName,
-        "redirectingConstructorInvocation_period":
-            redirectingConstructorInvocation_period,
         "redirectingConstructorInvocation_thisKeyword":
             redirectingConstructorInvocation_thisKeyword,
         "redirectingConstructorInvocation_elementType":
             redirectingConstructorInvocation_elementType,
+        "redirectingConstructorInvocation_period":
+            redirectingConstructorInvocation_period,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18440,11 +18887,11 @@
             superConstructorInvocation_element,
         "superConstructorInvocation_constructorName":
             superConstructorInvocation_constructorName,
-        "superConstructorInvocation_period": superConstructorInvocation_period,
         "superConstructorInvocation_superKeyword":
             superConstructorInvocation_superKeyword,
         "superConstructorInvocation_elementType":
             superConstructorInvocation_elementType,
+        "superConstructorInvocation_period": superConstructorInvocation_period,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18483,8 +18930,8 @@
         "whileStatement_body": whileStatement_body,
         "whileStatement_leftParenthesis": whileStatement_leftParenthesis,
         "whileStatement_condition": whileStatement_condition,
-        "whileStatement_rightParenthesis": whileStatement_rightParenthesis,
         "whileStatement_whileKeyword": whileStatement_whileKeyword,
+        "whileStatement_rightParenthesis": whileStatement_rightParenthesis,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18493,8 +18940,8 @@
       return {
         "yieldStatement_expression": yieldStatement_expression,
         "yieldStatement_yieldKeyword": yieldStatement_yieldKeyword,
-        "yieldStatement_star": yieldStatement_star,
         "yieldStatement_semicolon": yieldStatement_semicolon,
+        "yieldStatement_star": yieldStatement_star,
         "isSynthetic": isSynthetic,
         "kind": kind,
       };
@@ -18574,8 +19021,9 @@
     if (kind == idl.LinkedNodeKind.simpleIdentifier) {
       return {
         "simpleIdentifier_element": simpleIdentifier_element,
-        "simpleIdentifier_token": simpleIdentifier_token,
         "simpleIdentifier_elementType": simpleIdentifier_elementType,
+        "simpleIdentifier_token": simpleIdentifier_token,
+        "simpleIdentifier_isDeclaration": simpleIdentifier_isDeclaration,
         "expression_type": expression_type,
         "isSynthetic": isSynthetic,
         "kind": kind,
@@ -18615,14 +19063,6 @@
         "kind": kind,
       };
     }
-    if (kind == idl.LinkedNodeKind.comment) {
-      return {
-        "comment_tokens": comment_tokens,
-        "comment_type": comment_type,
-        "isSynthetic": isSynthetic,
-        "kind": kind,
-      };
-    }
     throw StateError("Unexpected $kind");
   }
 
@@ -19129,6 +19569,8 @@
   int _interfaceClass;
   List<LinkedNodeTypeBuilder> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19196,6 +19638,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 +19670,8 @@
       int interfaceClass,
       List<LinkedNodeTypeBuilder> interfaceTypeArguments,
       idl.LinkedNodeTypeKind kind,
+      idl.EntityRefNullabilitySuffix nullabilitySuffix,
+      int typeParameterElement,
       int typeParameterId})
       : _functionFormalParameters = functionFormalParameters,
         _functionReturnType = functionReturnType,
@@ -19221,6 +19681,8 @@
         _interfaceClass = interfaceClass,
         _interfaceTypeArguments = interfaceTypeArguments,
         _kind = kind,
+        _nullabilitySuffix = nullabilitySuffix,
+        _typeParameterElement = typeParameterElement,
         _typeParameterId = typeParameterId;
 
   /// Flush [informative] data recursively.
@@ -19262,6 +19724,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 +19735,8 @@
         x?.collectApiSignature(signature);
       }
     }
+    signature.addInt(
+        this._nullabilitySuffix == null ? 0 : this._nullabilitySuffix.index);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
@@ -19314,10 +19779,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 +19793,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 +19831,8 @@
   int _interfaceClass;
   List<idl.LinkedNodeType> _interfaceTypeArguments;
   idl.LinkedNodeTypeKind _kind;
+  idl.EntityRefNullabilitySuffix _nullabilitySuffix;
+  int _typeParameterElement;
   int _typeParameterId;
 
   @override
@@ -19391,7 +19865,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 +19873,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 +19899,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 +19944,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 +19962,8 @@
         "interfaceClass": interfaceClass,
         "interfaceTypeArguments": interfaceTypeArguments,
         "kind": kind,
+        "nullabilitySuffix": nullabilitySuffix,
+        "typeParameterElement": typeParameterElement,
         "typeParameterId": typeParameterId,
       };
 
@@ -19486,7 +19980,7 @@
 
   @override
   idl.LinkedNodeFormalParameterKind get kind =>
-      _kind ??= idl.LinkedNodeFormalParameterKind.required;
+      _kind ??= idl.LinkedNodeFormalParameterKind.requiredPositional;
 
   set kind(idl.LinkedNodeFormalParameterKind value) {
     this._kind = value;
@@ -19537,7 +20031,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 +20069,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 +20092,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 +20223,29 @@
 class LinkedNodeUnitBuilder extends Object
     with _LinkedNodeUnitMixin
     implements idl.LinkedNodeUnit {
+  bool _isSynthetic;
+  List<int> _lineStarts;
   LinkedNodeBuilder _node;
   UnlinkedTokensBuilder _tokens;
   String _uriStr;
 
   @override
+  bool get isSynthetic => _isSynthetic ??= false;
+
+  set isSynthetic(bool value) {
+    this._isSynthetic = 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
   LinkedNodeBuilder get node => _node;
 
   set node(LinkedNodeBuilder value) {
@@ -19754,13 +20267,20 @@
   }
 
   LinkedNodeUnitBuilder(
-      {LinkedNodeBuilder node, UnlinkedTokensBuilder tokens, String uriStr})
-      : _node = node,
+      {bool isSynthetic,
+      List<int> lineStarts,
+      LinkedNodeBuilder node,
+      UnlinkedTokensBuilder tokens,
+      String uriStr})
+      : _isSynthetic = isSynthetic,
+        _lineStarts = lineStarts,
+        _node = node,
         _tokens = tokens,
         _uriStr = uriStr;
 
   /// Flush [informative] data recursively.
   void flushInformative() {
+    _lineStarts = null;
     _node?.flushInformative();
     _tokens?.flushInformative();
   }
@@ -19772,12 +20292,17 @@
     this._tokens?.collectApiSignature(signature);
     signature.addBool(this._node != null);
     this._node?.collectApiSignature(signature);
+    signature.addBool(this._isSynthetic == true);
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_lineStarts;
     fb.Offset offset_node;
     fb.Offset offset_tokens;
     fb.Offset offset_uriStr;
+    if (!(_lineStarts == null || _lineStarts.isEmpty)) {
+      offset_lineStarts = fbBuilder.writeListUint32(_lineStarts);
+    }
     if (_node != null) {
       offset_node = _node.finish(fbBuilder);
     }
@@ -19788,6 +20313,12 @@
       offset_uriStr = fbBuilder.writeString(_uriStr);
     }
     fbBuilder.startTable();
+    if (_isSynthetic == true) {
+      fbBuilder.addBool(3, true);
+    }
+    if (offset_lineStarts != null) {
+      fbBuilder.addOffset(4, offset_lineStarts);
+    }
     if (offset_node != null) {
       fbBuilder.addOffset(2, offset_node);
     }
@@ -19817,11 +20348,26 @@
 
   _LinkedNodeUnitImpl(this._bc, this._bcOffset);
 
+  bool _isSynthetic;
+  List<int> _lineStarts;
   idl.LinkedNode _node;
   idl.UnlinkedTokens _tokens;
   String _uriStr;
 
   @override
+  bool get isSynthetic {
+    _isSynthetic ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+    return _isSynthetic;
+  }
+
+  @override
+  List<int> get lineStarts {
+    _lineStarts ??=
+        const fb.Uint32ListReader().vTableGet(_bc, _bcOffset, 4, const <int>[]);
+    return _lineStarts;
+  }
+
+  @override
   idl.LinkedNode get node {
     _node ??= const _LinkedNodeReader().vTableGet(_bc, _bcOffset, 2, null);
     return _node;
@@ -19845,6 +20391,8 @@
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (isSynthetic != false) _result["isSynthetic"] = isSynthetic;
+    if (lineStarts.isNotEmpty) _result["lineStarts"] = lineStarts;
     if (node != null) _result["node"] = node.toJson();
     if (tokens != null) _result["tokens"] = tokens.toJson();
     if (uriStr != '') _result["uriStr"] = uriStr;
@@ -19853,6 +20401,8 @@
 
   @override
   Map<String, Object> toMap() => {
+        "isSynthetic": isSynthetic,
+        "lineStarts": lineStarts,
         "node": node,
         "tokens": tokens,
         "uriStr": uriStr,
@@ -25875,7 +26425,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 +26630,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 +26761,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 +26823,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;
@@ -28718,6 +29269,300 @@
   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<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<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<int> lineStarts,
+      List<String> parts})
+      : _apiSignature = apiSignature,
+        _exports = exports,
+        _hasLibraryDirective = hasLibraryDirective,
+        _hasPartOfDirective = hasPartOfDirective,
+        _imports = imports,
+        _lineStarts = lineStarts,
+        _parts = parts;
+
+  /// Flush [informative] data recursively.
+  void 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);
+  }
+
+  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_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 (!(_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_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<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<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 (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,
+        "lineStarts": lineStarts,
+        "parts": parts,
+      };
+
+  @override
+  String toString() => convert.json.encode(toJson());
+}
+
 class UnlinkedVariableBuilder extends Object
     with _UnlinkedVariableMixin
     implements idl.UnlinkedVariable {
@@ -28730,6 +29575,7 @@
   bool _isConst;
   bool _isCovariant;
   bool _isFinal;
+  bool _isLate;
   bool _isStatic;
   String _name;
   int _nameOffset;
@@ -28824,6 +29670,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 +29746,7 @@
       bool isConst,
       bool isCovariant,
       bool isFinal,
+      bool isLate,
       bool isStatic,
       String name,
       int nameOffset,
@@ -28906,6 +29761,7 @@
         _isConst = isConst,
         _isCovariant = isCovariant,
         _isFinal = isFinal,
+        _isLate = isLate,
         _isStatic = isStatic,
         _name = name,
         _nameOffset = nameOffset,
@@ -28944,6 +29800,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 +29857,9 @@
     if (_isFinal == true) {
       fbBuilder.addBool(7, true);
     }
+    if (_isLate == true) {
+      fbBuilder.addBool(16, true);
+    }
     if (_isStatic == true) {
       fbBuilder.addBool(4, true);
     }
@@ -29044,6 +29904,7 @@
   bool _isConst;
   bool _isCovariant;
   bool _isFinal;
+  bool _isLate;
   bool _isStatic;
   String _name;
   int _nameOffset;
@@ -29111,6 +29972,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 +30034,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 +30055,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..b7053cb 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,
@@ -1071,14 +1099,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 +1155,8 @@
 
   BANG_EQ,
 
+  BANG_EQ_EQ,
+
   BAR,
 
   BAR_BAR,
@@ -1178,6 +1211,8 @@
 
   EQ_EQ,
 
+  EQ_EQ_EQ,
+
   EXPORT,
 
   EXTENDS,
@@ -1208,6 +1243,10 @@
 
   GT_GT_EQ,
 
+  GT_GT_GT,
+
+  GT_GT_GT_EQ,
+
   HASH,
 
   HEXADECIMAL,
@@ -1234,6 +1273,8 @@
 
   IS,
 
+  LATE,
+
   LIBRARY,
 
   LT,
@@ -1302,6 +1343,8 @@
 
   QUESTION_QUESTION_EQ,
 
+  REQUIRED,
+
   RETHROW,
 
   RETURN,
@@ -1541,6 +1584,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 +1734,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
@@ -1849,18 +1898,18 @@
 
   variantField_7:LinkedNode (id: 7);
 
+  variantField_17:uint (id: 17);
+
+  variantField_23:LinkedNodeType (id: 23);
+
   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_27:bool (id: 27);
 
   variantField_9:LinkedNode (id: 9);
@@ -1883,12 +1932,12 @@
 
   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);
-
   variantField_30:string (id: 30);
 
   variantField_14:LinkedNode (id: 14);
@@ -1897,10 +1946,14 @@
 
   kind:LinkedNodeKind (id: 0);
 
+  variantField_36:[string] (id: 36);
+
   variantField_20:string (id: 20);
 
   variantField_31:bool (id: 31);
 
+  variantField_35:TopLevelInferenceError (id: 35);
+
   variantField_22:string (id: 22);
 
   variantField_32:LinkedNodeVariablesDeclaration (id: 32);
@@ -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,11 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 table LinkedNodeUnit {
+  isSynthetic:bool (id: 3);
+
+  /// Offsets of the first character of each line in the source code.
+  lineStarts:[uint] (id: 4);
+
   node:LinkedNode (id: 2);
 
   tokens:UnlinkedTokens (id: 1);
@@ -3017,6 +3079,31 @@
   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);
+
+  /// 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 +3145,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..d0e04f4 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.
@@ -849,6 +881,12 @@
   @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;
 
@@ -1086,6 +1124,7 @@
   @VariantId(34, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
     LinkedNodeKind.constructorDeclaration,
     LinkedNodeKind.defaultFormalParameter,
     LinkedNodeKind.enumDeclaration,
@@ -1105,6 +1144,7 @@
   @VariantId(33, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
+    LinkedNodeKind.compilationUnit,
     LinkedNodeKind.constructorDeclaration,
     LinkedNodeKind.defaultFormalParameter,
     LinkedNodeKind.enumDeclaration,
@@ -1127,12 +1167,21 @@
   ])
   int get combinator_keyword;
 
+  @VariantId(2, variant: LinkedNodeKind.comment)
+  List<LinkedNode> get comment_references;
+
   @VariantId(28, variant: LinkedNodeKind.comment)
   List<int> get comment_tokens;
 
   @VariantId(29, variant: LinkedNodeKind.comment)
   LinkedNodeCommentType get comment_type;
 
+  @VariantId(6, variant: LinkedNodeKind.commentReference)
+  LinkedNode get commentReference_identifier;
+
+  @VariantId(15, variant: LinkedNodeKind.commentReference)
+  int get commentReference_newKeyword;
+
   @VariantId(15, variant: LinkedNodeKind.compilationUnit)
   int get compilationUnit_beginToken;
 
@@ -1268,8 +1317,8 @@
   @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;
@@ -1457,13 +1506,6 @@
   @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;
 
@@ -1593,6 +1635,9 @@
   @VariantId(15, variant: LinkedNodeKind.genericFunctionType)
   int get genericFunctionType_functionKeyword;
 
+  @VariantId(17, variant: LinkedNodeKind.genericFunctionType)
+  int get genericFunctionType_id;
+
   @VariantId(16, variant: LinkedNodeKind.genericFunctionType)
   int get genericFunctionType_question;
 
@@ -1695,6 +1740,14 @@
   @VariantId(7, variant: LinkedNodeKind.indexExpression)
   LinkedNode get indexExpression_target;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  bool get inheritsCovariant;
+
   @VariantId(6, variant: LinkedNodeKind.instanceCreationExpression)
   LinkedNode get instanceCreationExpression_arguments;
 
@@ -1845,6 +1898,9 @@
   @VariantId(6, variant: LinkedNodeKind.mixinDeclaration)
   LinkedNode get mixinDeclaration_onClause;
 
+  @VariantId(36, variant: LinkedNodeKind.mixinDeclaration)
+  List<String> get mixinDeclaration_superInvokedNames;
+
   @VariantId(14, variantList: [
     LinkedNodeKind.classDeclaration,
     LinkedNodeKind.classTypeAlias,
@@ -1916,13 +1972,6 @@
   ])
   LinkedNode get normalFormalParameter_identifier;
 
-  @VariantId(27, variantList: [
-    LinkedNodeKind.fieldFormalParameter,
-    LinkedNodeKind.functionTypedFormalParameter,
-    LinkedNodeKind.simpleFormalParameter,
-  ])
-  bool get normalFormalParameter_isCovariant;
-
   @VariantId(4, variantList: [
     LinkedNodeKind.fieldFormalParameter,
     LinkedNodeKind.functionTypedFormalParameter,
@@ -1930,6 +1979,13 @@
   ])
   List<LinkedNode> get normalFormalParameter_metadata;
 
+  @VariantId(18, variantList: [
+    LinkedNodeKind.fieldFormalParameter,
+    LinkedNodeKind.functionTypedFormalParameter,
+    LinkedNodeKind.simpleFormalParameter,
+  ])
+  int get normalFormalParameter_requiredKeyword;
+
   @VariantId(15, variant: LinkedNodeKind.nullLiteral)
   int get nullLiteral_literal;
 
@@ -2062,6 +2118,9 @@
   @VariantId(23, variant: LinkedNodeKind.simpleIdentifier)
   LinkedNodeType get simpleIdentifier_elementType;
 
+  @VariantId(27, variant: LinkedNodeKind.simpleIdentifier)
+  bool get simpleIdentifier_isDeclaration;
+
   @VariantId(16, variant: LinkedNodeKind.simpleIdentifier)
   int get simpleIdentifier_token;
 
@@ -2173,6 +2232,12 @@
   @VariantId(15, variant: LinkedNodeKind.throwExpression)
   int get throwExpression_throwKeyword;
 
+  @VariantId(35, variantList: [
+    LinkedNodeKind.simpleFormalParameter,
+    LinkedNodeKind.variableDeclaration,
+  ])
+  TopLevelInferenceError get topLevelTypeInferenceError;
+
   @VariantId(15, variant: LinkedNodeKind.topLevelVariableDeclaration)
   int get topLevelVariableDeclaration_semicolon;
 
@@ -2194,6 +2259,12 @@
   @VariantId(16, variant: LinkedNodeKind.tryStatement)
   int get tryStatement_tryKeyword;
 
+  @VariantId(27, variantList: [
+    LinkedNodeKind.functionTypeAlias,
+    LinkedNodeKind.genericTypeAlias,
+  ])
+  bool get typeAlias_hasSelfReference;
+
   @VariantId(19, variantList: [
     LinkedNodeKind.classTypeAlias,
     LinkedNodeKind.functionTypeAlias,
@@ -2244,12 +2315,12 @@
   @VariantId(6, variant: LinkedNodeKind.typeParameter)
   LinkedNode get typeParameter_bound;
 
+  @VariantId(23, variant: LinkedNodeKind.typeParameter)
+  LinkedNodeType get typeParameter_defaultType;
+
   @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;
 
@@ -2298,6 +2369,9 @@
   @VariantId(15, variant: LinkedNodeKind.variableDeclarationList)
   int get variableDeclarationList_keyword;
 
+  @VariantId(16, variant: LinkedNodeKind.variableDeclarationList)
+  int get variableDeclarationList_lateKeyword;
+
   @VariantId(6, variant: LinkedNodeKind.variableDeclarationList)
   LinkedNode get variableDeclarationList_type;
 
@@ -2364,9 +2438,10 @@
 
 /// Kinds of formal parameters.
 enum LinkedNodeFormalParameterKind {
-  required,
+  requiredPositional,
   optionalPositional,
-  optionalNamed
+  optionalNamed,
+  requiredNamed
 }
 
 /// Kinds of [LinkedNode].
@@ -2389,6 +2464,7 @@
   classDeclaration,
   classTypeAlias,
   comment,
+  commentReference,
   compilationUnit,
   conditionalExpression,
   configuration,
@@ -2532,10 +2608,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 +2624,13 @@
   @Id(5)
   LinkedNodeTypeKind get kind;
 
+  @Id(10)
+  EntityRefNullabilitySuffix get nullabilitySuffix;
+
   @Id(6)
+  int get typeParameterElement;
+
+  @Id(7)
   int get typeParameterId;
 }
 
@@ -2585,6 +2667,14 @@
 
 /// Information about a single library in a [LinkedNodeLibrary].
 abstract class LinkedNodeUnit extends base.SummaryClass {
+  @Id(3)
+  bool get isSynthetic;
+
+  /// Offsets of the first character of each line in the source code.
+  @informative
+  @Id(4)
+  List<int> get lineStarts;
+
   @Id(2)
   LinkedNode get node;
 
@@ -4257,14 +4347,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 +4512,7 @@
   BACKSLASH,
   BANG,
   BANG_EQ,
+  BANG_EQ_EQ,
   BAR,
   BAR_BAR,
   BAR_EQ,
@@ -4446,6 +4540,7 @@
   EOF,
   EQ,
   EQ_EQ,
+  EQ_EQ_EQ,
   EXPORT,
   EXTENDS,
   EXTERNAL,
@@ -4461,6 +4556,8 @@
   GT_EQ,
   GT_GT,
   GT_GT_EQ,
+  GT_GT_GT,
+  GT_GT_GT_EQ,
   HASH,
   HEXADECIMAL,
   HIDE,
@@ -4474,6 +4571,7 @@
   INT,
   INTERFACE,
   IS,
+  LATE,
   LIBRARY,
   LT,
   LT_EQ,
@@ -4508,6 +4606,7 @@
   QUESTION_PERIOD,
   QUESTION_QUESTION,
   QUESTION_QUESTION_EQ,
+  REQUIRED,
   RETHROW,
   RETURN,
   SCRIPT_TAG,
@@ -4735,6 +4834,43 @@
   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;
+
+  /// 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 +4923,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..9723dd5 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';
@@ -317,12 +318,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) {
@@ -2455,8 +2458,14 @@
           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);
@@ -2467,7 +2476,7 @@
         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 +2577,9 @@
             initializerForInference);
 
   @override
+  bool get isLate => unlinkedVariable.isLate;
+
+  @override
   bool get isStatic => unlinkedVariable.isStatic;
 
   @override
@@ -4290,10 +4302,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 +4317,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -4309,16 +4328,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 +4432,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 +4447,9 @@
       parameterKind == ParameterKind.POSITIONAL;
 
   @override
+  bool get isOptionalNamed => parameterKind == ParameterKind.NAMED;
+
+  @override
   bool get isOptionalPositional => parameterKind == ParameterKind.POSITIONAL;
 
   @override
@@ -4421,6 +4458,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
@@ -5481,9 +5524,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..6f8720e 100644
--- a/pkg/analyzer/lib/src/summary/resynthesize.dart
+++ b/pkg/analyzer/lib/src/summary/resynthesize.dart
@@ -1491,7 +1491,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..b50d8cd 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(
@@ -711,7 +729,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 +845,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 +903,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 +920,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 +1006,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/summary_file_builder.dart b/pkg/analyzer/lib/src/summary/summary_file_builder.dart
index f774d2a..c558609 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';
@@ -129,10 +130,14 @@
     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..28dc74a 100644
--- a/pkg/analyzer/lib/src/summary/summary_sdk.dart
+++ b/pkg/analyzer/lib/src/summary/summary_sdk.dart
@@ -349,9 +349,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_reader.dart b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
index 15cab36..4927499 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_reader.dart
@@ -48,6 +48,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');
     }
@@ -84,7 +88,10 @@
       _getToken(data.annotation_period),
       _readNode(data.annotation_constructorName),
       _readNode(data.annotation_arguments),
-    );
+    )..element = _elementOfComponents(
+        data.annotation_element,
+        data.annotation_elementType,
+      );
   }
 
   ArgumentList _read_argumentList(LinkedNode data) {
@@ -259,7 +266,7 @@
       case LinkedNodeCommentType.documentation:
         return astFactory.documentationComment(
           tokens,
-          // TODO(scheglov) references
+          _readNodeList(data.comment_references),
         );
       case LinkedNodeCommentType.endOfLine:
         return astFactory.endOfLineComment(
@@ -270,16 +277,23 @@
     }
   }
 
-  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(
+      _getToken(data.commentReference_newKeyword),
+      _readNode(data.commentReference_identifier),
     );
   }
 
+  CompilationUnit _read_compilationUnit(LinkedNode data) {
+    return astFactory.compilationUnit2(
+        beginToken: _getToken(data.compilationUnit_beginToken),
+        scriptTag: _readNode(data.compilationUnit_scriptTag),
+        directives: _readNodeList(data.compilationUnit_directives),
+        declarations: _readNodeList(data.compilationUnit_declarations),
+        endToken: _getToken(data.compilationUnit_endToken),
+        featureSet: null);
+  }
+
   ConditionalExpression _read_conditionalExpression(LinkedNode data) {
     return astFactory.conditionalExpression(
       _readNode(data.conditionalExpression_condition),
@@ -365,9 +379,7 @@
   DefaultFormalParameter _read_defaultFormalParameter(LinkedNode data) {
     var node = astFactory.defaultFormalParameter(
       _readNode(data.defaultFormalParameter_parameter),
-      data.defaultFormalParameter_isNamed
-          ? ParameterKind.NAMED
-          : ParameterKind.POSITIONAL,
+      _toParameterKind(data.defaultFormalParameter_kind),
       _getToken(data.defaultFormalParameter_separator),
       _readNodeLazy(data.defaultFormalParameter_defaultValue),
     );
@@ -498,6 +510,7 @@
       comment: _readNode(data.normalFormalParameter_comment),
       type: _readNode(data.fieldFormalParameter_type),
       parameters: _readNode(data.fieldFormalParameter_formalParameters),
+      requiredKeyword: _getToken(data.normalFormalParameter_requiredKeyword),
     );
     LazyFormalParameter.setData(node, data);
     return node;
@@ -624,20 +637,28 @@
       _getToken(data.typeAlias_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),
+      comment: _readNodeLazy(data.normalFormalParameter_comment),
       covariantKeyword: _getToken(data.normalFormalParameter_covariantKeyword),
-      comment: _readNode(data.normalFormalParameter_comment),
-      metadata: _readNodeList(data.normalFormalParameter_metadata),
-      typeParameters:
-          _readNode(data.functionTypedFormalParameter_typeParameters),
+      identifier: _readNode(data.normalFormalParameter_identifier),
+      metadata: _readNodeListLazy(data.normalFormalParameter_metadata),
+      parameters: _readNodeLazy(
+        data.functionTypedFormalParameter_formalParameters,
+      ),
+      requiredKeyword: _getToken(data.normalFormalParameter_requiredKeyword),
+      returnType: _readNodeLazy(data.functionTypedFormalParameter_returnType),
+      typeParameters: _readNode(
+        data.functionTypedFormalParameter_typeParameters,
+      ),
     );
     LazyFormalParameter.setData(node, data);
     return node;
@@ -653,13 +674,14 @@
     );
     node.type = _readType(data.genericFunctionType_type);
     LazyGenericFunctionType.setData(node, data);
+    _unitContext.addGenericFunctionType(data.genericFunctionType_id, node);
     return node;
   }
 
   GenericTypeAlias _read_genericTypeAlias(LinkedNode data) {
     var node = astFactory.genericTypeAlias(
       _readNodeLazy(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
+      _readNodeListLazy(data.annotatedNode_metadata),
       _getToken(data.typeAlias_typedefKeyword),
       _readNode(data.namedCompilationUnitMember_name),
       _readNode(data.genericTypeAlias_typeParameters),
@@ -668,6 +690,10 @@
       _getToken(data.typeAlias_semicolon),
     );
     LazyGenericTypeAlias.setData(node, data);
+    LazyGenericTypeAlias.setHasSelfReference(
+      node,
+      data.typeAlias_hasSelfReference,
+    );
     return node;
   }
 
@@ -742,12 +768,15 @@
   }
 
   InstanceCreationExpression _read_instanceCreationExpression(LinkedNode data) {
-    return astFactory.instanceCreationExpression(
+    var node = astFactory.instanceCreationExpression(
       _getToken(data.instanceCreationExpression_keyword),
       _readNode(data.instanceCreationExpression_constructorName),
       _readNode(data.instanceCreationExpression_arguments),
       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) {
@@ -862,7 +891,7 @@
   MixinDeclaration _read_mixinDeclaration(LinkedNode data) {
     var node = astFactory.mixinDeclaration(
       _readNodeLazy(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
+      _readNodeListLazy(data.annotatedNode_metadata),
       _getToken(data.mixinDeclaration_mixinKeyword),
       _readNode(data.namedCompilationUnitMember_name),
       _readNode(data.classOrMixinDeclaration_typeParameters),
@@ -872,7 +901,7 @@
       _readNodeListLazy(data.classOrMixinDeclaration_members),
       _getToken(data.classOrMixinDeclaration_rightBracket),
     );
-    LazyMixinDeclaration.setData(node, data);
+    LazyMixinDeclaration(node, data);
     return node;
   }
 
@@ -934,7 +963,7 @@
   PartOfDirective _read_partOfDirective(LinkedNode data) {
     var node = astFactory.partOfDirective(
       _readNode(data.annotatedNode_comment),
-      _readNodeList(data.annotatedNode_metadata),
+      _readNodeListLazy(data.annotatedNode_metadata),
       _getToken(data.directive_keyword),
       _getToken(data.partOfDirective_ofKeyword),
       _readNode(data.partOfDirective_uri),
@@ -1049,14 +1078,17 @@
       comment: _readNode(data.normalFormalParameter_comment),
       metadata: _readNodeList(data.normalFormalParameter_metadata),
       keyword: _getToken(data.simpleFormalParameter_keyword),
+      requiredKeyword: _getToken(data.normalFormalParameter_requiredKeyword),
     );
     LazyFormalParameter.setData(node, data);
+    LazyAst.setInheritsCovariant(node, data.inheritsCovariant);
     return node;
   }
 
   SimpleIdentifier _read_simpleIdentifier(LinkedNode data) {
     return astFactory.simpleIdentifier(
       _getToken(data.simpleIdentifier_token),
+      isDeclaration: data.simpleIdentifier_isDeclaration,
     )
       ..staticElement = _elementOfComponents(
         data.simpleIdentifier_element,
@@ -1201,7 +1233,6 @@
       _readNodeLazy(data.typeParameter_bound),
     );
     LazyTypeParameter.setData(node, data);
-    _unitContext.addTypeParameter(data.typeParameter_id, node);
     return node;
   }
 
@@ -1220,17 +1251,21 @@
       _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: _readNodeLazy(data.annotatedNode_comment),
+      keyword: _getToken(data.variableDeclarationList_keyword),
+      lateKeyword: _getToken(data.variableDeclarationList_lateKeyword),
+      metadata: _readNodeListLazy(data.annotatedNode_metadata),
+      type: _readNodeLazy(data.variableDeclarationList_type),
+      variables: _readNodeList(data.variableDeclarationList_variables),
     );
+    LazyVariableDeclarationList.setData(node, data);
+    return node;
   }
 
   VariableDeclarationStatement _read_variableDeclarationStatement(
@@ -1307,6 +1342,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:
@@ -1536,4 +1573,21 @@
   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');
+    }
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
index 76a97c7..2cc58d4 100644
--- a/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/ast_binary_writer.dart
@@ -13,19 +13,21 @@
 import 'package:analyzer/src/summary/idl.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';
 
 /// Serializer of fully resolved ASTs into flat buffers.
 class AstBinaryWriter extends ThrowingAstVisitor<LinkedNodeBuilder> {
   final LinkingBundleContext _linkingContext;
-  final TokensContext _tokensContext;
+  final _tokensWriter = TokensWriter();
 
   /// This field is set temporary while visiting [FieldDeclaration] or
   /// [TopLevelVariableDeclaration] to store data shared among all variables
   /// in these declarations.
   LinkedNodeVariablesDeclarationBuilder _variablesDeclaration;
 
-  AstBinaryWriter(this._linkingContext, this._tokensContext);
+  AstBinaryWriter(this._linkingContext);
+
+  UnlinkedTokensBuilder get tokensBuilder => _tokensWriter.tokensBuilder;
 
   @override
   LinkedNodeBuilder visitAdjacentStrings(AdjacentStrings node) {
@@ -36,10 +38,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),
     );
@@ -229,18 +234,35 @@
     return LinkedNodeBuilder.comment(
       comment_tokens: _getTokens(node.tokens),
       comment_type: type,
+      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),
     );
   }
 
   @override
   LinkedNodeBuilder visitCompilationUnit(CompilationUnit node) {
-    return LinkedNodeBuilder.compilationUnit(
+    var builder = LinkedNodeBuilder.compilationUnit(
       compilationUnit_beginToken: _getToken(node.beginToken),
       compilationUnit_declarations: _writeNodeList(node.declarations),
       compilationUnit_directives: _writeNodeList(node.directives),
       compilationUnit_endToken: _getToken(node.endToken),
       compilationUnit_scriptTag: node.scriptTag?.accept(this),
     );
+    _storeCodeOffsetLength(builder, node);
+    return builder;
   }
 
   @override
@@ -342,7 +364,7 @@
   LinkedNodeBuilder visitDefaultFormalParameter(DefaultFormalParameter node) {
     var builder = LinkedNodeBuilder.defaultFormalParameter(
       defaultFormalParameter_defaultValue: node.defaultValue?.accept(this),
-      defaultFormalParameter_isNamed: node.isNamed,
+      defaultFormalParameter_kind: _toParameterKind(node),
       defaultFormalParameter_parameter: node.parameter.accept(this),
       defaultFormalParameter_separator: _getToken(node.separator),
     );
@@ -600,6 +622,8 @@
       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);
@@ -632,6 +656,10 @@
       genericFunctionType_typeParameters: node.typeParameters?.accept(this),
     );
     _writeActualReturnType(builder, node);
+
+    var id = LazyAst.getGenericFunctionTypeId(node);
+    builder.genericFunctionType_id = id;
+
     return builder;
   }
 
@@ -639,8 +667,10 @@
   LinkedNodeBuilder visitGenericTypeAlias(GenericTypeAlias node) {
     var builder = LinkedNodeBuilder.genericTypeAlias(
       genericTypeAlias_equals: _getToken(node.equals),
-      genericTypeAlias_functionType: node.functionType.accept(this),
+      genericTypeAlias_functionType: node.functionType?.accept(this),
       genericTypeAlias_typeParameters: node.typeParameters?.accept(this),
+      typeAlias_hasSelfReference:
+          LazyGenericTypeAlias.getHasSelfReference(node),
     );
     _storeTypeAlias(builder, node);
     _storeIsSimpleBounded(builder, node);
@@ -858,6 +888,7 @@
       mixinDeclaration_onClause: node.onClause?.accept(this),
     );
     _storeClassOrMixinDeclaration(builder, node);
+    LazyMixinDeclaration.get(node).put(builder);
     return builder;
   }
 
@@ -1054,7 +1085,9 @@
       simpleFormalParameter_keyword: _getToken(node.keyword),
       simpleFormalParameter_type: node.type?.accept(this),
     );
+    builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
     _storeNormalFormalParameter(builder, node);
+    _storeInheritsCovariant(builder, node);
     return builder;
   }
 
@@ -1072,6 +1105,7 @@
     return LinkedNodeBuilder.simpleIdentifier(
       simpleIdentifier_element: elementComponents.rawElement,
       simpleIdentifier_elementType: elementComponents.definingType,
+      simpleIdentifier_isDeclaration: node is DeclaredSimpleIdentifier,
       simpleIdentifier_token: _getToken(node.token),
       expression_type: _writeType(node.staticType),
     );
@@ -1236,14 +1270,13 @@
   @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));
+      typeParameter_bound: node.bound?.accept(this),
+      typeParameter_defaultType: _writeType(LazyAst.getDefaultType(node)),
+      typeParameter_extendsKeyword: _getToken(node.extendsKeyword),
+      typeParameter_name: node.name.accept(this),
+    );
     _storeDeclaration(builder, node);
     _storeCodeOffsetLength(builder, node);
-    builder.typeParameter_id = _linkingContext.idOfTypeParameter(
-      node.declaredElement,
-    );
     return builder;
   }
 
@@ -1264,7 +1297,9 @@
       variableDeclaration_name: node.name.accept(this),
       variableDeclaration_declaration: _variablesDeclaration,
     );
+    builder.topLevelTypeInferenceError = LazyAst.getTypeInferenceError(node);
     _writeActualType(builder, node);
+    _storeInheritsCovariant(builder, node);
     return builder;
   }
 
@@ -1277,6 +1312,7 @@
 
     var builder = LinkedNodeBuilder.variableDeclarationList(
       variableDeclarationList_keyword: _getToken(node.keyword),
+      variableDeclarationList_lateKeyword: _getToken(node.lateKeyword),
       variableDeclarationList_type: node.type?.accept(this),
       variableDeclarationList_variables: _writeNodeList(node.variables),
     );
@@ -1326,10 +1362,15 @@
   }
 
   LinkedNodeBuilder writeNode(AstNode node) {
+    _tokensWriter.writeTokens(node.beginToken, node.endToken);
     return node.accept(this);
   }
 
   _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);
@@ -1341,7 +1382,7 @@
   }
 
   int _getToken(Token token) {
-    return _tokensContext.indexOfToken(token);
+    return _tokensWriter.indexOfToken(token);
   }
 
   List<int> _getTokens(List<Token> tokenList) {
@@ -1433,14 +1474,6 @@
   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);
   }
@@ -1474,6 +1507,11 @@
       ..ifMixin_rightParenthesis = _getToken(node.rightParenthesis);
   }
 
+  void _storeInheritsCovariant(LinkedNodeBuilder builder, AstNode node) {
+    var value = LazyAst.getInheritsCovariant(node);
+    builder.inheritsCovariant = value;
+  }
+
   void _storeInvocationExpression(
       LinkedNodeBuilder builder, InvocationExpression node) {
     _storeExpression(builder, node);
@@ -1514,7 +1552,8 @@
       ..normalFormalParameter_covariantKeyword =
           _getToken(node.covariantKeyword)
       ..normalFormalParameter_identifier = node.identifier?.accept(this)
-      ..normalFormalParameter_metadata = _writeNodeList(node.metadata);
+      ..normalFormalParameter_metadata = _writeNodeList(node.metadata)
+      ..normalFormalParameter_requiredKeyword = _getToken(node.requiredKeyword);
   }
 
   void _storeStatement(LinkedNodeBuilder builder, Statement node) {}
@@ -1576,6 +1615,20 @@
   LinkedNodeTypeBuilder _writeType(DartType type) {
     return _linkingContext.writeType(type);
   }
+
+  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.
diff --git a/pkg/analyzer/lib/src/summary2/ast_resolver.dart b/pkg/analyzer/lib/src/summary2/ast_resolver.dart
index a8a0d5a..a98c541 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,8 +22,9 @@
     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;
 
@@ -31,20 +33,18 @@
         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/builder/source_library_builder.dart b/pkg/analyzer/lib/src/summary2/builder/source_library_builder.dart
index dab6481..76261f8 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;
@@ -85,6 +88,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 +123,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 +143,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,79 +167,6 @@
         }
       }
     }
-//    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'));
     }
@@ -284,6 +220,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,13 +247,13 @@
   }
 
   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, 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);
@@ -309,6 +263,7 @@
         linker.elementFactory,
         element,
         unitReference,
+        linker.contextFeatures.isEnabled(Feature.non_nullable),
         libraryScope,
       );
       unitContext.unit.accept(resolver);
@@ -342,7 +297,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/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/declaration_splicer.dart b/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
new file mode 100644
index 0000000..f562b51
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/declaration_splicer.dart
@@ -0,0 +1,593 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/element/builder.dart';
+import 'package:analyzer/src/dart/element/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+
+/// This class takes a [CompilationUnitElement] lazily resynthesized from a
+/// fully resolved, but partial AST (contains only APIs), and full unresolved
+/// AST - and splices them into a single AST with all declaration nodes
+/// fully resolved, and function bodies and variable initializers unresolved.
+///
+class DeclarationSplicer {
+  final CompilationUnitElementImpl _unitElement;
+
+  _ElementWalker _walker;
+
+  DeclarationSplicer(this._unitElement);
+
+  void splice(CompilationUnit full) {
+    var partialNode = _unitElement.linkedContext.readUnitEagerly();
+    _walk(_ElementWalker.forCompilationUnit(_unitElement), () {
+      _directives(full, partialNode);
+      _declarations(full, partialNode);
+    });
+  }
+
+  FunctionBody _body(FunctionBody full) {
+    _buildLocalElements(full);
+    return full;
+  }
+
+  void _buildLocalElements(AstNode node) {
+    if (node == null) return;
+
+    var holder = ElementHolder();
+    var elementBuilder = LocalElementBuilder(holder, _unitElement);
+    node.accept(elementBuilder);
+
+    ElementImpl element = _walker.element;
+    element.encloseElements(holder.functions);
+    element.encloseElements(holder.labels);
+    element.encloseElements(holder.localVariables);
+  }
+
+  void _classDeclaration(ClassDeclaration full, ClassDeclaration partial) {
+    var element = _walker.getClass();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forClass(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      var fullList = full.members;
+      var partialList = partial.members;
+      for (var i = 0; i < fullList.length; ++i) {
+        _node(fullList[i], partialList[i]);
+      }
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _classTypeAlias(ClassTypeAlias full, ClassTypeAlias partial) {
+    var element = _walker.getClass();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forClass(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _constructorDeclaration(
+    ConstructorDeclaration full,
+    ConstructorDeclaration partial,
+  ) {
+    var element = _walker.getConstructor();
+    _match(partial.name, element);
+    (partial as ConstructorDeclarationImpl).declaredElement = element;
+    _walk(_ElementWalker.forExecutable(element), () {
+      _formalParameterList(full.parameters, partial.parameters);
+      _constructorInitializers(full.initializers, partial.initializers);
+      partial.body = _body(full.body);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _constructorInitializers(
+    List<ConstructorInitializer> full,
+    List<ConstructorInitializer> partial,
+  ) {
+    if (full.isNotEmpty && partial.isEmpty) {
+      partial.addAll(full);
+    }
+    partial.forEach(_buildLocalElements);
+  }
+
+  void _declarations(CompilationUnit full, CompilationUnit partial) {
+    var fullList = full.declarations;
+    var partialList = partial.declarations;
+    for (var i = 0; i < fullList.length; ++i) {
+      var partialNode = _node(fullList[i], partialList[i]);
+      fullList[i] = partialNode;
+    }
+  }
+
+  void _directives(CompilationUnit full, CompilationUnit partial) {
+    var libraryElement = _unitElement.library;
+    var exportIndex = 0;
+    var importIndex = 0;
+    var partIndex = 0;
+    for (var directive in full.directives) {
+      if (directive is ExportDirective) {
+        var element = libraryElement.exports[exportIndex++];
+        _metadata(directive.metadata, element);
+      } else if (directive is ImportDirective) {
+        var element = libraryElement.imports[importIndex++];
+        _metadata(directive.metadata, element);
+      } else if (directive is LibraryDirective) {
+        var element = libraryElement;
+        _metadata(directive.metadata, element);
+      } else if (directive is PartDirective) {
+        var element = libraryElement.parts[partIndex++];
+        _metadata(directive.metadata, element);
+      }
+    }
+  }
+
+  void _enumConstantDeclaration(
+      EnumConstantDeclaration full, EnumConstantDeclaration partial) {
+    var element = _walker.getVariable();
+    _match(partial.name, element);
+    _metadata(partial.metadata, element);
+  }
+
+  void _enumDeclaration(EnumDeclaration full, EnumDeclaration partial) {
+    var element = _walker.getEnum();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forClass(element), () {
+      var fullList = full.constants;
+      var partialList = partial.constants;
+      for (var i = 0; i < fullList.length; ++i) {
+        _node(fullList[i], partialList[i]);
+      }
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _fieldDeclaration(FieldDeclaration full, FieldDeclaration partial) {
+    _node(full.fields, partial.fields);
+
+    var first = partial.fields.variables[0];
+    _metadata(partial.metadata, first.declaredElement);
+  }
+
+  void _fieldFormalParameter(
+    FieldFormalParameter full,
+    FieldFormalParameter partial,
+  ) {
+    var element = _walker.getParameter();
+    _match(partial.identifier, element);
+    _walk(_ElementWalker.forParameter(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.parameters, partial.parameters);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _formalParameterList(
+    FormalParameterList full,
+    FormalParameterList partial,
+  ) {
+    var fullList = full.parameters;
+    var partialList = partial.parameters;
+    for (var i = 0; i < fullList.length; ++i) {
+      _node(fullList[i], partialList[i]);
+    }
+  }
+
+  void _functionDeclaration(
+    FunctionDeclaration full,
+    FunctionDeclaration partial,
+  ) {
+    var element = partial.propertyKeyword == null
+        ? _walker.getFunction()
+        : _walker.getAccessor();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forExecutable(element), () {
+      _node(full.functionExpression, partial.functionExpression);
+    });
+    (partial.functionExpression as FunctionExpressionImpl).declaredElement =
+        element;
+    _metadata(partial.metadata, element);
+    _node(full.returnType, partial.returnType);
+  }
+
+  void _functionExpression(
+    FunctionExpression full,
+    FunctionExpression partial,
+  ) {
+    _node(full.typeParameters, partial.typeParameters);
+    _node(full.parameters, partial.parameters);
+    partial.body = _body(full.body);
+  }
+
+  void _functionTypeAlias(FunctionTypeAlias full, FunctionTypeAlias partial) {
+    var element = _walker.getTypedef();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forGenericTypeAlias(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.parameters, partial.parameters);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _functionTypedFormalParameter(
+    FunctionTypedFormalParameter full,
+    FunctionTypedFormalParameter partial,
+  ) {
+    var element = _walker.getParameter();
+    _match(partial.identifier, element);
+    _walk(_ElementWalker.forParameter(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.parameters, partial.parameters);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  void _genericFunctionType(
+    GenericFunctionType full,
+    GenericFunctionType partial,
+  ) {
+    var element = (partial as GenericFunctionTypeImpl).declaredElement;
+    _walk(_ElementWalker.forGenericFunctionType(element), () {
+      _node(full.returnType, partial.returnType);
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.parameters, partial.parameters);
+    });
+  }
+
+  void _genericTypeAlias(GenericTypeAlias full, GenericTypeAlias partial) {
+    var element = _walker.getTypedef();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forGenericTypeAlias(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.functionType, partial.functionType);
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  /// Updates [node] to point to [element], after ensuring that the
+  /// element has the expected name.
+  E _match<E extends Element>(SimpleIdentifier node, E element) {
+    // TODO(scheglov) has troubles with getter/setter.
+//    if (element.name != node.name) {
+//      throw new StateError(
+//        'Expected an element matching `${node.name}`, got `${element.name}`',
+//      );
+//    }
+    if (node != null) {
+      node.staticElement = element;
+    }
+    return element;
+  }
+
+  /// Associate [nodes] with the corresponding [ElementAnnotation]s.
+  void _metadata(List<Annotation> nodes, Element element) {
+    var elements = element.metadata;
+    if (nodes.length != elements.length) {
+      throw StateError('Found ${nodes.length} annotation nodes and '
+          '${elements.length} element annotations');
+    }
+    for (var i = 0; i < nodes.length; i++) {
+      var node = nodes[i];
+      node.elementAnnotation = elements[i];
+      _buildLocalElements(node);
+    }
+  }
+
+  void _methodDeclaration(MethodDeclaration full, MethodDeclaration partial) {
+    var element = partial.propertyKeyword == null
+        ? _walker.getFunction()
+        : _walker.getAccessor();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forExecutable(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      _node(full.parameters, partial.parameters);
+      partial.body = _body(full.body);
+    });
+    _metadata(partial.metadata, element);
+    _node(full.returnType, partial.returnType);
+  }
+
+  void _mixinDeclaration(MixinDeclaration full, MixinDeclaration partial) {
+    var element = _walker.getMixin();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forClass(element), () {
+      _node(full.typeParameters, partial.typeParameters);
+      var fullList = full.members;
+      var partialList = partial.members;
+      for (var i = 0; i < fullList.length; ++i) {
+        _node(fullList[i], partialList[i]);
+      }
+    });
+    _metadata(partial.metadata, element);
+  }
+
+  AstNode _node(AstNode full, AstNode partial) {
+    if (full == null && partial == null) {
+      return partial;
+    } else if (full is ClassDeclaration && partial is ClassDeclaration) {
+      _classDeclaration(full, partial);
+      return partial;
+    } else if (full is ClassTypeAlias && partial is ClassTypeAlias) {
+      _classTypeAlias(full, partial);
+      return partial;
+    } else if (full is ConstructorDeclaration &&
+        partial is ConstructorDeclaration) {
+      _constructorDeclaration(full, partial);
+      return partial;
+    } else if (full is DefaultFormalParameter &&
+        partial is DefaultFormalParameter) {
+      _node(full.parameter, partial.parameter);
+      return partial;
+    } else if (full is EnumConstantDeclaration &&
+        partial is EnumConstantDeclaration) {
+      _enumConstantDeclaration(full, partial);
+      return partial;
+    } else if (full is EnumDeclaration && partial is EnumDeclaration) {
+      _enumDeclaration(full, partial);
+      return partial;
+    } else if (full is FieldDeclaration && partial is FieldDeclaration) {
+      _fieldDeclaration(full, partial);
+      return partial;
+    } else if (full is FieldFormalParameter &&
+        partial is FieldFormalParameter) {
+      _fieldFormalParameter(full, partial);
+      return partial;
+    } else if (full is FormalParameterList && partial is FormalParameterList) {
+      _formalParameterList(full, partial);
+      return partial;
+    } else if (full is FunctionDeclaration && partial is FunctionDeclaration) {
+      _functionDeclaration(full, partial);
+      return partial;
+    } else if (full is FunctionExpression && partial is FunctionExpression) {
+      _functionExpression(full, partial);
+      return partial;
+    } else if (full is FunctionTypedFormalParameter &&
+        partial is FunctionTypedFormalParameter) {
+      _functionTypedFormalParameter(full, partial);
+      return partial;
+    } else if (full is FunctionTypeAlias && partial is FunctionTypeAlias) {
+      _functionTypeAlias(full, partial);
+      return partial;
+    } else if (full is GenericFunctionType && partial is GenericFunctionType) {
+      _genericFunctionType(full, partial);
+      return partial;
+    } else if (full is GenericTypeAlias && partial is GenericTypeAlias) {
+      _genericTypeAlias(full, partial);
+      return partial;
+    } else if (full is MethodDeclaration && partial is MethodDeclaration) {
+      _methodDeclaration(full, partial);
+      return partial;
+    } else if (full is MixinDeclaration && partial is MixinDeclaration) {
+      _mixinDeclaration(full, partial);
+      return partial;
+    } else if (full is SimpleFormalParameter &&
+        partial is SimpleFormalParameter) {
+      _simpleFormalParameter(full, partial);
+      return partial;
+    } else if (full is TopLevelVariableDeclaration &&
+        partial is TopLevelVariableDeclaration) {
+      _topLevelVariableDeclaration(full, partial);
+      return partial;
+    } else if (full is TypeName && partial is TypeName) {
+      _typeName(full, partial);
+      return partial;
+    } else if (full is TypeParameter && partial is TypeParameter) {
+      _typeParameter(full, partial);
+      return partial;
+    } else if (full is TypeParameterList && partial is TypeParameterList) {
+      _typeParameterList(full, partial);
+      return partial;
+    } else if (full is VariableDeclaration && partial is VariableDeclaration) {
+      _variableDeclaration(full, partial);
+      return partial;
+    } else if (full is VariableDeclarationList &&
+        partial is VariableDeclarationList) {
+      _variableDeclarationList(full, partial);
+      return partial;
+    } else {
+      throw UnimplementedError(
+        '${full.runtimeType} and ${partial.runtimeType}',
+      );
+    }
+  }
+
+  void _simpleFormalParameter(
+    SimpleFormalParameter full,
+    SimpleFormalParameter partial,
+  ) {
+    var element = _walker.getParameter();
+    _match(partial.identifier, element);
+    (partial as SimpleFormalParameterImpl).declaredElement = element;
+    _metadata(partial.metadata, element);
+    _node(full.type, partial.type);
+  }
+
+  void _topLevelVariableDeclaration(
+    TopLevelVariableDeclaration full,
+    TopLevelVariableDeclaration partial,
+  ) {
+    _node(full.variables, partial.variables);
+
+    var first = partial.variables.variables[0];
+    _metadata(partial.metadata, first.declaredElement);
+  }
+
+  void _typeName(TypeName full, TypeName partial) {
+    var fullList = full.typeArguments?.arguments;
+    var partialList = partial.typeArguments?.arguments;
+    if (fullList != null && partialList != null) {
+      for (var i = 0; i < fullList.length; ++i) {
+        _node(fullList[i], partialList[i]);
+      }
+    }
+  }
+
+  void _typeParameter(TypeParameter full, TypeParameter partial) {
+    var element = _walker.getTypeParameter();
+    _match(partial.name, element);
+    _node(full.bound, partial.bound);
+    _metadata(partial.metadata, element);
+  }
+
+  void _typeParameterList(TypeParameterList full, TypeParameterList partial) {
+    var fullList = full.typeParameters;
+    var partialList = partial.typeParameters;
+    for (var i = 0; i < fullList.length; ++i) {
+      _node(fullList[i], partialList[i]);
+    }
+  }
+
+  void _variableDeclaration(
+    VariableDeclaration full,
+    VariableDeclaration partial,
+  ) {
+    var element = _walker.getVariable();
+    _match(partial.name, element);
+    _walk(_ElementWalker.forVariable(element), () {
+      partial.initializer = full.initializer;
+      _buildLocalElements(partial.initializer);
+    });
+  }
+
+  void _variableDeclarationList(
+    VariableDeclarationList full,
+    VariableDeclarationList partial,
+  ) {
+    _node(full.type, partial.type);
+
+    var fullList = full.variables;
+    var partialList = partial.variables;
+    for (var i = 0; i < fullList.length; ++i) {
+      _node(fullList[i], partialList[i]);
+    }
+  }
+
+  void _walk(_ElementWalker walker, void f()) {
+    var outer = _walker;
+    _walker = walker;
+    f();
+    _walker = outer;
+  }
+}
+
+class _ElementWalker {
+  final Element element;
+
+  List<PropertyAccessorElement> _accessors;
+  int _accessorIndex = 0;
+
+  List<ClassElement> _classes;
+  int _classIndex = 0;
+
+  List<ConstructorElement> _constructors;
+  int _constructorIndex = 0;
+
+  List<ClassElement> _enums;
+  int _enumIndex = 0;
+
+  List<ExecutableElement> _functions;
+  int _functionIndex = 0;
+
+  List<ClassElement> _mixins;
+  int _mixinIndex = 0;
+
+  List<ParameterElement> _parameters;
+  int _parameterIndex = 0;
+
+  List<FunctionTypeAliasElement> _typedefs;
+  int _typedefIndex = 0;
+
+  List<TypeParameterElement> _typeParameters;
+  int _typeParameterIndex = 0;
+
+  List<VariableElement> _variables;
+  int _variableIndex = 0;
+
+  _ElementWalker.forClass(ClassElement element)
+      : element = element,
+        _accessors = element.accessors.where(_isNotSynthetic).toList(),
+        _constructors = element.isMixinApplication
+            ? null
+            : element.constructors.where(_isNotSynthetic).toList(),
+        _functions = element.methods,
+        _typeParameters = element.typeParameters,
+        _variables = element.fields.where(_isNotSynthetic).toList();
+
+  _ElementWalker.forCompilationUnit(CompilationUnitElement element)
+      : element = element,
+        _accessors = element.accessors.where(_isNotSynthetic).toList(),
+        _classes = element.types,
+        _enums = element.enums,
+        _functions = element.functions,
+        _mixins = element.mixins,
+        _typedefs = element.functionTypeAliases,
+        _variables = element.topLevelVariables.where(_isNotSynthetic).toList();
+
+  _ElementWalker.forExecutable(ExecutableElement element)
+      : element = element,
+        _parameters = element.parameters,
+        _typeParameters = element.typeParameters;
+
+  _ElementWalker.forGenericFunctionType(GenericFunctionTypeElement element)
+      : element = element,
+        _parameters = element.parameters,
+        _typeParameters = element.typeParameters;
+
+  _ElementWalker.forGenericTypeAlias(FunctionTypeAliasElement element)
+      : element = element,
+        _parameters = element.parameters,
+        _typeParameters = element.typeParameters;
+
+  _ElementWalker.forParameter(ParameterElement element)
+      : element = element,
+        _parameters = element.parameters,
+        _typeParameters = element.typeParameters;
+
+  _ElementWalker.forVariable(VariableElement element) : element = element;
+
+  PropertyAccessorElement getAccessor() {
+    return _accessors[_accessorIndex++];
+  }
+
+  ClassElement getClass() {
+    return _classes[_classIndex++];
+  }
+
+  ConstructorElement getConstructor() {
+    return _constructors[_constructorIndex++];
+  }
+
+  ClassElement getEnum() {
+    return _enums[_enumIndex++];
+  }
+
+  ExecutableElement getFunction() {
+    return _functions[_functionIndex++];
+  }
+
+  ClassElement getMixin() {
+    return _mixins[_mixinIndex++];
+  }
+
+  ParameterElement getParameter() {
+    return _parameters[_parameterIndex++];
+  }
+
+  FunctionTypeAliasElement getTypedef() {
+    return _typedefs[_typedefIndex++];
+  }
+
+  TypeParameterElement getTypeParameter() {
+    return _typeParameters[_typeParameterIndex++];
+  }
+
+  VariableElement getVariable() {
+    return _variables[_variableIndex++];
+  }
+
+  static bool _isNotSynthetic(Element e) => !e.isSynthetic;
+}
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/function_type_builder.dart b/pkg/analyzer/lib/src/summary2/function_type_builder.dart
new file mode 100644
index 0000000..39425e6
--- /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 as TypeParameterElement)
+              ?.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/lazy_ast.dart b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
index 77b9527..9f7fd21 100644
--- a/pkg/analyzer/lib/src/summary2/lazy_ast.dart
+++ b/pkg/analyzer/lib/src/summary2/lazy_ast.dart
@@ -5,21 +5,38 @@
 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_reader.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 +45,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 +57,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 +84,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 {
@@ -561,8 +599,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);
 
@@ -585,6 +626,16 @@
     return LazyAst.getType(node);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(FormalParameter node) {
+    var lazy = get(node);
+    if (!lazy._hasTypeInferenceError) {
+      var error = lazy.data.topLevelTypeInferenceError;
+      LazyAst.setTypeInferenceError(node, error);
+      lazy._hasTypeInferenceError = true;
+    }
+    return LazyAst.getTypeInferenceError(node);
+  }
+
   static void readDefaultValue(
     AstBinaryReader reader,
     DefaultFormalParameter node,
@@ -600,6 +651,25 @@
     }
   }
 
+  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,
+        );
+      } else if (node is FieldFormalParameter) {
+        node.parameters = reader.readNode(
+          lazy.data.fieldFormalParameter_formalParameters,
+        );
+      }
+      lazy._hasFormalParameters = true;
+    }
+  }
+
   static void readMetadata(
     AstBinaryReader reader,
     FormalParameter node,
@@ -615,6 +685,23 @@
     }
   }
 
+  static void readTypeNode(
+    AstBinaryReader reader,
+    FormalParameter node,
+  ) {
+    if (reader.isLazy) {
+      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 +715,7 @@
   bool _hasDocumentationComment = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyFunctionDeclaration(this.data);
 
@@ -691,6 +779,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));
   }
@@ -743,6 +844,7 @@
 
 class LazyFunctionTypeAlias {
   static const _key = 'lazyAst';
+  static const _hasSelfReferenceKey = 'lazyAst_hasSelfReferenceKey';
 
   final LinkedNode data;
 
@@ -750,6 +852,7 @@
   bool _hasFormalParameters = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyFunctionTypeAlias(this.data);
 
@@ -757,6 +860,10 @@
     return node.getProperty(_key);
   }
 
+  static bool getHasSelfReference(FunctionTypeAlias node) {
+    return node.getProperty(_hasSelfReferenceKey);
+  }
+
   static DartType getReturnType(
     AstBinaryReader reader,
     FunctionTypeAlias node,
@@ -813,10 +920,27 @@
     }
   }
 
+  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);
   }
+
+  static void setHasSelfReference(FunctionTypeAlias node, bool value) {
+    node.setProperty(_hasSelfReferenceKey, value);
+  }
 }
 
 class LazyGenericFunctionType {
@@ -826,6 +950,7 @@
 
   bool _hasFormalParameters = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyGenericFunctionType(this.data);
 
@@ -861,6 +986,19 @@
     }
   }
 
+  static void readReturnTypeNode(
+    AstBinaryReader reader,
+    GenericFunctionType node,
+  ) {
+    var lazy = get(node);
+    if (lazy != null && !lazy._hasReturnTypeNode) {
+      node.returnType = reader.readNode(
+        lazy.data.genericFunctionType_returnType,
+      );
+      lazy._hasReturnTypeNode = true;
+    }
+  }
+
   static void setData(GenericFunctionType node, LinkedNode data) {
     node.setProperty(_key, LazyGenericFunctionType(data));
   }
@@ -868,11 +1006,13 @@
 
 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,6 +1020,10 @@
     return node.getProperty(_key);
   }
 
+  static bool getHasSelfReference(GenericTypeAlias node) {
+    return node.getProperty(_hasSelfReferenceKey);
+  }
+
   static void readDocumentationComment(
     AstBinaryReader reader,
     GenericTypeAlias node,
@@ -906,10 +1050,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 +1085,7 @@
   bool _hasFormalParameters = false;
   bool _hasMetadata = false;
   bool _hasReturnType = false;
+  bool _hasReturnTypeNode = false;
 
   LazyMethodDeclaration(this.data);
 
@@ -944,6 +1108,16 @@
     return LazyAst.getReturnType(node);
   }
 
+  static bool isAbstract(MethodDeclaration node) {
+    var lazy = get(node);
+    if (lazy != null) {
+      return lazy.data.methodDeclaration_body.kind ==
+          LinkedNodeKind.emptyFunctionBody;
+    } else {
+      return node.isAbstract;
+    }
+  }
+
   static void readBody(
     AstBinaryReader reader,
     MethodDeclaration node,
@@ -998,6 +1172,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,11 +1199,35 @@
   bool _hasOnClause = false;
   bool _hasImplementsClause = false;
   bool _hasMembers = false;
+  bool _hasMetadata = false;
 
-  LazyMixinDeclaration(this.data);
+  List<String> _superInvokedNames;
+
+  LazyMixinDeclaration(MixinDeclaration node, this.data) {
+    node.setProperty(_key, this);
+    if (data != null) {
+      LazyAst.setSimplyBounded(node, data.simplyBoundable_isSimplyBounded);
+    }
+  }
+
+  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) {
-    return node.getProperty(_key);
+    LazyMixinDeclaration lazy = node.getProperty(_key);
+    if (lazy == null) {
+      return LazyMixinDeclaration(node, null);
+    }
+    return lazy;
   }
 
   static void readDocumentationComment(
@@ -1024,7 +1235,7 @@
     MixinDeclaration node,
   ) {
     var lazy = get(node);
-    if (lazy != null && !lazy._hasDocumentationComment) {
+    if (lazy.data != null && !lazy._hasDocumentationComment) {
       node.documentationComment = reader.readNode(
         lazy.data.annotatedNode_comment,
       );
@@ -1037,7 +1248,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 +1261,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 +1271,33 @@
     }
   }
 
+  static void readMetadata(
+    AstBinaryReader reader,
+    MixinDeclaration node,
+  ) {
+    var lazy = LazyMixinDeclaration.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 {
@@ -1132,6 +1353,8 @@
   final LinkedNode data;
 
   bool _hasBound = false;
+  bool _hasDefaultType = false;
+  bool _hasMetadata = false;
 
   LazyTypeParameter(this.data);
 
@@ -1139,6 +1362,17 @@
     return node.getProperty(_key);
   }
 
+  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 +1381,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 +1408,7 @@
 
   bool _hasInitializer = false;
   bool _hasType = false;
+  bool _hasTypeInferenceError = false;
 
   LazyVariableDeclaration(this.data);
 
@@ -1181,6 +1431,17 @@
     return LazyAst.getType(node);
   }
 
+  static TopLevelInferenceError getTypeInferenceError(
+      VariableDeclaration node) {
+    var lazy = get(node);
+    if (!lazy._hasTypeInferenceError) {
+      var error = lazy.data.topLevelTypeInferenceError;
+      LazyAst.setTypeInferenceError(node, error);
+      lazy._hasTypeInferenceError = true;
+    }
+    return LazyAst.getTypeInferenceError(node);
+  }
+
   static void readInitializer(
     AstBinaryReader reader,
     VariableDeclaration node,
@@ -1200,3 +1461,36 @@
     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,
+  ) {
+    if (reader.isLazy) {
+      var lazy = get(node);
+      if (!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..7ee0e37 100644
--- a/pkg/analyzer/lib/src/summary2/link.dart
+++ b/pkg/analyzer/lib/src/summary2/link.dart
@@ -2,8 +2,9 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'package:analyzer/dart/analysis/features.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart' show AstNode, CompilationUnit;
+import 'package:analyzer/dart/ast/ast.dart' show CompilationUnit;
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
@@ -22,9 +23,9 @@
 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';
 
 LinkResult link(
   AnalysisOptions analysisOptions,
@@ -83,6 +84,10 @@
     );
   }
 
+  FeatureSet get contextFeatures {
+    return analysisContext.analysisOptions.contextFeatures;
+  }
+
   void link(List<LinkedNodeBundle> inputBundles,
       List<LinkInputLibrary> inputLibraries) {
     for (var input in inputBundles) {
@@ -101,12 +106,6 @@
     _createLinkingBundle();
   }
 
-  void _addExporters() {
-    for (var library in builders.values) {
-      library.addExporters();
-    }
-  }
-
   void _addSyntheticConstructors() {
     for (var library in builders.values) {
       library.addSyntheticConstructors();
@@ -115,24 +114,43 @@
 
   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 +159,6 @@
       }
     }
 
-    for (var library in builders.values) {
-      library.buildInitialExportScope();
-    }
-
     var both = new Set<SourceLibraryBuilder>();
     for (var exported in exportees) {
       if (exporters.contains(exported)) {
@@ -183,20 +197,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 writer = AstBinaryWriter(linkingBundleContext);
         var unitLinkedNode = writer.writeNode(unit);
         builder.node.units.add(
           LinkedNodeUnitBuilder(
-            uriStr: unit2.uriStr,
-            tokens: tokensResult.tokens,
+            isSynthetic: unitContext.isSynthetic,
+            uriStr: unitContext.uriStr,
+            lineStarts: unit.lineInfo.lineStarts,
+            tokens: writer.tokensBuilder,
             node: unitLinkedNode,
           ),
         );
@@ -236,6 +247,10 @@
     TopLevelInference(this).infer();
   }
 
+  void _resolveConstantInitializers() {
+    ConstantInitializersResolver(this).perform();
+  }
+
   void _resolveConstructors() {
     for (var library in builders.values) {
       library.resolveConstructors();
@@ -255,12 +270,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 +294,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 {
diff --git a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
index bb079ee..7688746 100644
--- a/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_bundle_context.dart
@@ -20,17 +20,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 +53,33 @@
   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);
       libraryContext.units.add(
         LinkedUnitContext(
           this,
           libraryContext,
           unitIndex++,
-          unitUriStr,
+          uriStr,
+          reference,
+          inputUnit.isSynthetic,
           null,
           unit: inputUnit.unit,
         ),
@@ -104,12 +124,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..37c4ef9 100644
--- a/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_element_factory.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/resolver/scope.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisContext;
-import 'package:analyzer/src/summary/idl.dart';
 import 'package:analyzer/src/summary2/core_types.dart';
 import 'package:analyzer/src/summary2/linked_bundle_context.dart';
 import 'package:analyzer/src/summary2/linked_unit_context.dart';
@@ -58,6 +57,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,37 +69,15 @@
     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;
-//      }
-//    }
-
-    throw UnimplementedError('$reference');
-  }
 }
 
 class _ElementRequest {
@@ -134,6 +113,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 +133,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 +171,6 @@
       return reference.element;
     }
 
-    // TODO(scheglov) support other elements
     throw StateError('Not found: $input');
   }
 
@@ -184,6 +188,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 +222,21 @@
     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;
+    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 +251,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 +282,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 +309,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 +354,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 +376,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..ac704b4 100644
--- a/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
+++ b/pkg/analyzer/lib/src/summary2/linked_unit_context.dart
@@ -5,6 +5,9 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/dart/element/visitor.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/utilities_dart.dart';
@@ -12,6 +15,7 @@
 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/reference.dart';
 import 'package:analyzer/src/summary2/tokens_context.dart';
 
 /// The context of a unit - the context of the bundle, and the unit tokens.
@@ -20,6 +24,8 @@
   final LinkedLibraryContext libraryContext;
   final int indexInLibrary;
   final String uriStr;
+  final Reference reference;
+  final bool isSynthetic;
   final LinkedNodeUnit data;
   final TokensContext tokensContext;
 
@@ -28,19 +34,25 @@
   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 elements for generic function types.
+  final Map<int, GenericFunctionTypeElementImpl> _genericFunctionTypes = {};
+
+  /// 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,
+  LinkedUnitContext(
+      this.bundleContext,
+      this.libraryContext,
+      this.indexInLibrary,
+      this.uriStr,
+      this.reference,
+      this.isSynthetic,
+      this.data,
       {CompilationUnit unit})
       : tokensContext = data != null ? TokensContext(data.tokens) : null {
     _astReader = AstBinaryReader(this);
@@ -50,11 +62,34 @@
     _hasDirectivesRead = _unit != null;
   }
 
+  LinkedUnitContext._(
+      this.bundleContext,
+      this.libraryContext,
+      this.indexInLibrary,
+      this.uriStr,
+      this.reference,
+      this.isSynthetic,
+      this.data,
+      this.tokensContext);
+
+  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;
+
   CompilationUnit get unit => _unit;
 
   CompilationUnit get unit_withDeclarations {
     if (_unit == null) {
       _unit = _astReader.readNode(data.node);
+      _unit.lineInfo = LineInfo(data.lineStarts);
     }
     return _unit;
   }
@@ -71,13 +106,29 @@
     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;
+  /// Every [GenericFunctionType] node has [GenericFunctionTypeElement], which
+  /// is created during reading of this node.
+  void addGenericFunctionType(int id, GenericFunctionTypeImpl node) {
+    if (this.reference == null) return;
+
+    LazyAst.setGenericFunctionTypeId(node, id);
+
+    var element = _genericFunctionTypes[id];
+    if (element == null) {
+      element = GenericFunctionTypeElementImpl.forLinkedNode(
+        this.reference.element,
+        null,
+        node,
+      );
+      _genericFunctionTypes[id] = element;
+    }
+
+    node.declaredElement = element;
+
+    var containerRef = this.reference.getChild('@genericFunctionType');
+    var reference = containerRef.getChild('$id');
+    reference.element = element;
+    element.reference = reference;
   }
 
   /// Return the [LibraryElement] referenced in the [node].
@@ -92,14 +143,24 @@
       return LazyClassDeclaration.get(node).data.codeLength;
     } else if (node is ClassTypeAlias) {
       return LazyClassTypeAlias.get(node).data.codeLength;
+    } else if (node is CompilationUnit) {
+      return data.node.codeLength;
     } else if (node is ConstructorDeclaration) {
       return LazyConstructorDeclaration.get(node).data.codeLength;
+    } else if (node is EnumDeclaration) {
+      return LazyEnumDeclaration.get(node).data.codeLength;
     } else if (node is FormalParameter) {
       return LazyFormalParameter.get(node).data.codeLength;
     } else if (node is FunctionDeclaration) {
       return LazyFunctionDeclaration.get(node).data.codeLength;
+    } else if (node is FunctionTypeAliasImpl) {
+      return LazyFunctionTypeAlias.get(node).data.codeLength;
+    } else if (node is GenericTypeAlias) {
+      return LazyGenericTypeAlias.get(node).data.codeLength;
     } else if (node is MethodDeclaration) {
       return LazyMethodDeclaration.get(node).data.codeLength;
+    } else if (node is MixinDeclaration) {
+      return LazyMixinDeclaration.get(node).data.codeLength;
     } else if (node is TypeParameter) {
       return LazyTypeParameter.get(node).data.codeLength;
     } else if (node is VariableDeclaration) {
@@ -113,14 +174,24 @@
       return LazyClassDeclaration.get(node).data.codeOffset;
     } else if (node is ClassTypeAlias) {
       return LazyClassTypeAlias.get(node).data.codeOffset;
+    } else if (node is CompilationUnit) {
+      return data.node.codeOffset;
     } else if (node is ConstructorDeclaration) {
       return LazyConstructorDeclaration.get(node).data.codeOffset;
+    } else if (node is EnumDeclaration) {
+      return LazyEnumDeclaration.get(node).data.codeOffset;
     } else if (node is FormalParameter) {
       return LazyFormalParameter.get(node).data.codeOffset;
     } else if (node is FunctionDeclaration) {
       return LazyFunctionDeclaration.get(node).data.codeOffset;
+    } else if (node is FunctionTypeAliasImpl) {
+      return LazyFunctionTypeAlias.get(node).data.codeOffset;
+    } else if (node is GenericTypeAlias) {
+      return LazyGenericTypeAlias.get(node).data.codeOffset;
     } else if (node is MethodDeclaration) {
       return LazyMethodDeclaration.get(node).data.codeOffset;
+    } else if (node is MixinDeclaration) {
+      return LazyMixinDeclaration.get(node).data.codeOffset;
     } else if (node is TypeParameter) {
       return LazyTypeParameter.get(node).data.codeOffset;
     } else if (node is VariableDeclaration) {
@@ -160,6 +231,23 @@
     }
   }
 
+  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(AstNode node) {
+    LazyDirective.readMetadata(_astReader, node);
+    return node.offset;
+  }
+
   Comment getDocumentationComment(AstNode node) {
     if (node is ClassDeclaration) {
       LazyClassDeclaration.readDocumentationComment(_astReader, node);
@@ -215,6 +303,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) {
@@ -240,6 +338,18 @@
     } 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;
@@ -252,21 +362,11 @@
     } 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 id = LazyAst.getGenericFunctionTypeId(node);
+    return reference.getChild('@genericFunctionType').getChild('$id');
   }
 
   GenericFunctionType getGeneticTypeAliasFunction(GenericTypeAlias node) {
@@ -274,6 +374,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,6 +398,18 @@
     }
   }
 
+  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}');
+    }
+  }
+
   InterfaceType getInterfaceType(LinkedNodeType linkedType) {
     var type = readType(linkedType);
     if (type is InterfaceType && !type.element.isEnum) {
@@ -324,7 +445,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 +473,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,32 +495,6 @@
         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>[];
   }
 
@@ -405,13 +513,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;
     }
@@ -438,6 +560,28 @@
     }
   }
 
+  TypeAnnotation getReturnTypeNode(AstNode node) {
+    if (node is FunctionTypeAlias) {
+      LazyFunctionTypeAlias.readReturnTypeNode(_astReader, node);
+      return node.returnType;
+    } else if (node is GenericFunctionType) {
+      LazyGenericFunctionType.readReturnTypeNode(_astReader, node);
+      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}');
+    }
+  }
+
+  String getSelectedUri(UriBasedDirective node) {
+    return LazyDirective.getSelectedUri(node);
+  }
+
   String getSimpleName(LinkedNode node) {
     return getTokenLexeme(node.simpleIdentifier_token);
   }
@@ -487,6 +631,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 +655,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,6 +676,8 @@
       return node.typeParameters;
     } else if (node is MixinDeclaration) {
       return node.typeParameters;
+    } else if (node is SimpleFormalParameter) {
+      return null;
     } else {
       throw UnimplementedError('${node.runtimeType}');
     }
@@ -540,18 +704,26 @@
   }
 
   bool hasImplicitReturnType(AstNode node) {
+    if (node is FunctionDeclaration) {
+      LazyFunctionDeclaration.readFunctionExpression(_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;
   }
@@ -571,7 +743,7 @@
     } else if (node is FunctionDeclaration) {
       return false;
     } else if (node is MethodDeclaration) {
-      return node.isAbstract;
+      return LazyMethodDeclaration.isAbstract(node);
     }
     throw UnimplementedError('${node.runtimeType}');
   }
@@ -593,16 +765,6 @@
       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}');
   }
 
@@ -614,14 +776,17 @@
     return isConstKeyword(node.variableDeclarationList_keyword);
   }
 
-  bool isCovariant(AstNode node) {
-    if (node is FormalParameter) {
+  bool isExplicitlyCovariant(AstNode node) {
+    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) {
@@ -674,6 +839,19 @@
     }
   }
 
+  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 isLibraryKeyword(int token) {
     return tokensContext.type(token) == UnlinkedTokenType.LIBRARY;
   }
@@ -712,7 +890,7 @@
     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;
@@ -739,13 +917,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 +941,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 +979,48 @@
     }
   }
 
+  /// Read new resolved [CompilationUnit] from the [data], and in contrast to
+  /// reading AST for element model, read it eagerly. We can do this, because
+  /// the element model is fully accessible, so we don't need to worry about
+  /// potential forward references.
+  ///
+  /// The new instance of [CompilationUnit] is required because the client of
+  /// this method is going to modify the unit - merge parsed, not yet resolved
+  /// function bodies into it, and resolve them.
+  CompilationUnit readUnitEagerly() {
+    reference.element.accept(
+      _TypeParameterReader(),
+    );
+    _RecursiveTypeReader(this).read(unit);
+
+    var context = LinkedUnitContext._(
+      bundleContext,
+      libraryContext,
+      indexInLibrary,
+      uriStr,
+      reference,
+      isSynthetic,
+      data,
+      TokensContext(data.tokens),
+    );
+    context._genericFunctionTypes.addAll(_genericFunctionTypes);
+    var astReader = AstBinaryReader(context);
+    return astReader.readNode(data.node);
+  }
+
+  void setInheritsCovariant(AstNode node, bool value) {
+    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 +1029,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 +1042,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 +1066,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;
   }
@@ -860,17 +1104,15 @@
   }
 
   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;
         }
       }
     }
@@ -904,4 +1146,109 @@
     }
     return typeParameterList?.typeParameterList_typeParameters;
   }
+
+  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');
+    }
+  }
+}
+
+/// Ensure that all [GenericFunctionType] and [TypeParameter] nodes are read,
+/// so their elements are created and set in [Reference]s.
+class _RecursiveTypeReader {
+  final LinkedUnitContext context;
+
+  _RecursiveTypeReader(this.context);
+
+  void read(AstNode node) {
+    if (node == null) {
+    } else if (node is ClassDeclaration) {
+      _readTypeParameters(node);
+      node.members.forEach(read);
+    } else if (node is ClassTypeAlias) {
+      _readTypeParameters(node);
+    } else if (node is CompilationUnit) {
+      for (var declaration in node.declarations) {
+        read(declaration);
+      }
+    } else if (node is ConstructorDeclaration) {
+      _readFormalParameters(node);
+    } else if (node is EnumDeclaration) {
+    } else if (node is FieldDeclaration) {
+      read(node.fields);
+    } else if (node is FunctionDeclaration) {
+      _readTypeParameters(node);
+      _readFormalParameters(node);
+      _readReturnType(node);
+    } else if (node is FunctionTypeAlias) {
+      _readTypeParameters(node);
+      _readFormalParameters(node);
+      _readReturnType(node);
+    } else if (node is GenericFunctionType) {
+      _readTypeParameters(node);
+      _readFormalParameters(node);
+      _readReturnType(node);
+    } else if (node is GenericTypeAlias) {
+      _readTypeParameters(node);
+      LazyGenericTypeAlias.readFunctionType(context._astReader, node);
+      read(node.functionType);
+    } else if (node is MethodDeclaration) {
+      _readTypeParameters(node);
+      _readFormalParameters(node);
+      _readReturnType(node);
+    } else if (node is MixinDeclaration) {
+      _readTypeParameters(node);
+      node.members.forEach(read);
+    } else if (node is TopLevelVariableDeclaration) {
+      read(node.variables);
+    } else if (node is TypeName) {
+      node.typeArguments?.arguments?.forEach(read);
+    } else if (node is VariableDeclarationList) {
+      LazyVariableDeclarationList.readTypeNode(context._astReader, node);
+      read(node.type);
+    } else {
+      throw StateError('${node.runtimeType}');
+    }
+  }
+
+  void _readFormalParameters(AstNode node) {
+    var formalParameters = context.getFormalParameters(node);
+    if (formalParameters == null) return;
+
+    for (var formalParameter in formalParameters) {
+      if (formalParameter is SimpleFormalParameter) {
+        read(formalParameter.type);
+      }
+    }
+  }
+
+  void _readReturnType(AstNode node) {
+    var returnType = context.getReturnTypeNode(node);
+    read(returnType);
+  }
+
+  void _readTypeParameters(AstNode node) {
+    var typeParameters = context.getTypeParameters2(node);
+    if (typeParameters == null) return;
+
+    for (var typeParameter in typeParameters.typeParameters) {
+      var bound = context.getTypeParameterBound(typeParameter);
+      read(bound);
+    }
+  }
+}
+
+class _TypeParameterReader extends RecursiveElementVisitor<void> {
+  @override
+  void visitTypeParameterElement(TypeParameterElement element) {
+    super.visitTypeParameterElement(element);
+  }
 }
diff --git a/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart b/pkg/analyzer/lib/src/summary2/linking_bundle_context.dart
index 06d86ce..fd4148c 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,16 @@
   );
 
   final Map<TypeParameterElement, int> _typeParameters = Map.identity();
-  int _nextTypeParameterId = 1;
   int _nextSyntheticTypeParameterId = 0x10000;
 
+  final Map<GenericFunctionTypeElement, int> _genericFunctionTypes =
+      Map.identity();
+  int _nextGenericFunctionTypeId = 1;
+
   LinkingBundleContext(this.dynamicReference);
 
-  void addTypeParameter(TypeParameterElement element) {
-    _typeParameters[element] = _nextTypeParameterId++;
+  int idOfGenericFunctionType(GenericFunctionTypeElement element) {
+    return _genericFunctionTypes[element];
   }
 
   int idOfTypeParameter(TypeParameterElement element) {
@@ -46,15 +48,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);
   }
@@ -73,6 +72,10 @@
     return reference.index;
   }
 
+  int nextGenericFunctionTypeId() {
+    return _nextGenericFunctionTypeId++;
+  }
+
   LinkedNodeTypeBuilder writeType(DartType type) {
     if (type == null) return null;
 
@@ -91,13 +94,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 +123,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 +180,7 @@
           .toList(),
       functionReturnType: writeType(type.returnType),
       functionTypeParameters: typeParameterBuilders,
+      nullabilitySuffix: _nullabilitySuffix(type),
     );
 
     for (var typeParameter in typeParameters) {
@@ -172,4 +190,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..7c9e52f 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 CompilationUnitElement _unitElement;
 
   Scope scope;
 
-  MetadataResolver(this._linker, this._libraryElement);
+  MetadataResolver(this._linker, this._libraryElement, this._unitElement);
 
   @override
   void visitAnnotation(Annotation node) {
-    // TODO(scheglov) get rid of?
-    node.elementAnnotation = ElementAnnotationImpl(null);
+    node.elementAnnotation = ElementAnnotationImpl(_unitElement);
+
+    var holder = ElementHolder();
+    node.accept(LocalElementBuilder(holder, null));
 
     var astResolver = AstResolver(_linker, _libraryElement, scope);
-    // TODO(scheglov) enclosing elements?
     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..95c0ae7 100644
--- a/pkg/analyzer/lib/src/summary2/reference.dart
+++ b/pkg/analyzer/lib/src/summary2/reference.dart
@@ -71,8 +71,6 @@
 
   bool get isTypeAlias => parent != null && parent.name == '@typeAlias';
 
-  int get numOfChildren => _children != null ? _children.length : 0;
-
   /// Return the child with the given name, or `null` if does not exist.
   Reference operator [](String name) {
     return _children != null ? _children[name] : null;
@@ -84,5 +82,20 @@
     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;
+    }
+  }
+
   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..cfaee14 100644
--- a/pkg/analyzer/lib/src/summary2/reference_resolver.dart
+++ b/pkg/analyzer/lib/src/summary2/reference_resolver.dart
@@ -3,502 +3,22 @@
 // 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
@@ -511,9 +31,11 @@
 /// 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;
 
   Reference reference;
   Scope scope;
@@ -523,9 +45,10 @@
     this.nodesToBuildType,
     this.elementFactory,
     this._libraryElement,
-    this.reference,
+    this.unitReference,
+    this.nnbd,
     this.scope,
-  );
+  ) : reference = unitReference;
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {}
@@ -538,13 +61,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);
@@ -554,6 +73,7 @@
     node.implementsClause?.accept(this);
     node.withClause?.accept(this);
     node.members.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -567,13 +87,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 +98,7 @@
     node.superclass?.accept(this);
     node.withClause?.accept(this);
     node.implementsClause?.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -642,7 +159,7 @@
   void visitFieldFormalParameter(FieldFormalParameter node) {
     node.type?.accept(this);
     node.parameters?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
@@ -655,22 +172,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 +211,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 +227,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 +261,29 @@
     var outerScope = scope;
     var outerReference = reference;
 
-    var name = '${outerReference.numOfChildren}';
-    reference = reference.getChild(name);
+    var id = linkingContext.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 +297,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 +320,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);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -805,22 +356,20 @@
     var outerReference = reference;
 
     var name = node.name.name;
-    reference = reference.getChild('@class').getChild(name);
+    reference = reference.getChild('@mixin').getChild(name);
 
-    _createTypeParameterElements(node.typeParameters);
-    var element = ClassElementImpl.forLinkedNode(
-      outerReference.element,
-      reference,
-      node,
-    );
+    MixinElementImpl 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.onClause?.accept(this);
     node.implementsClause?.accept(this);
     node.members.accept(this);
+    nodesToBuildType.addDeclaration(node);
 
     scope = outerScope;
     reference = outerReference;
@@ -834,7 +383,7 @@
   @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     node.type?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
@@ -866,7 +415,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 +445,7 @@
   @override
   void visitVariableDeclarationList(VariableDeclarationList node) {
     node.type?.accept(this);
-    nodesToBuildType.add(node);
+    nodesToBuildType.addDeclaration(node);
   }
 
   @override
@@ -891,9 +454,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 +474,16 @@
       _createTypeParameterElement(typeParameter);
     }
   }
+
+  NullabilitySuffix _getNullabilitySuffix(bool hasQuestion) {
+    if (nnbd) {
+      if (hasQuestion) {
+        return NullabilitySuffix.question;
+      } else {
+        return NullabilitySuffix.none;
+      }
+    } else {
+      return NullabilitySuffix.star;
+    }
+  }
 }
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..eb8f654 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_context.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_context.dart
@@ -4,15 +4,9 @@
 
 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;
@@ -22,36 +16,6 @@
       : _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];
   }
@@ -167,6 +131,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 +187,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 +219,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 +249,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 +319,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..6668845 100644
--- a/pkg/analyzer/lib/src/summary2/tokens_writer.dart
+++ b/pkg/analyzer/lib/src/summary2/tokens_writer.dart
@@ -6,25 +6,10 @@
 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() {
@@ -40,8 +25,20 @@
     );
   }
 
+  UnlinkedTokensBuilder get tokensBuilder => _tokens;
+
+  int indexOfToken(Token token) {
+    if (token == null) return 0;
+
+    var index = _tokenToIndex[token];
+    if (index == null) {
+      throw StateError('Unexpected token: $token');
+    }
+    return index;
+  }
+
   /// Write all the tokens from the [first] to the [last] inclusively.
-  TokensResult writeTokens(Token first, Token last) {
+  void writeTokens(Token first, Token last) {
     if (first is CommentToken) {
       first = (first as CommentToken).parent;
     }
@@ -67,8 +64,6 @@
 
       if (token == last) break;
     }
-
-    return TokensResult(_tokens, _indexToToken, _tokenToIndex);
   }
 
   int _addToken(
@@ -91,8 +86,7 @@
     _tokens.precedingComment.add(precedingComment);
     _tokens.type.add(type);
 
-    var index = _indexToToken.length;
-    _indexToToken.add(token);
+    var index = _tokenToIndex.length;
     _tokenToIndex[token] = index;
     return index;
   }
@@ -196,6 +190,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 +246,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 +278,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 +308,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 +378,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..5b35375 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,53 @@
   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.libraryScope;
+          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) {
+    if (node.isConst && node.type != null) {
+      for (var variable in node.variables) {
+        if (variable.initializer != null) {
+          var astResolver = AstResolver(linker, _library, _scope);
+          astResolver.rewriteAst(variable.initializer);
+          astResolver.resolve(variable.initializer);
+        }
+      }
+    }
+  }
+}
+
 class TopLevelInference {
   final Linker linker;
 
@@ -38,8 +87,11 @@
   DynamicTypeImpl get _dynamicType => DynamicTypeImpl.instance;
 
   void infer() {
+    var initializerInference = _InitializerInference(linker);
+    initializerInference.createNodes();
+
     _performOverrideInference();
-    _InitializerInference(linker).perform();
+    initializerInference.perform();
     _inferConstructorFieldFormals();
   }
 
@@ -84,17 +136,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 +183,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 +218,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 +246,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 +289,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 +297,7 @@
   @override
   void evaluateScc(List<_InferenceNode> scc) {
     for (var node in scc) {
-      node.markCircular();
+      node.markCircular(scc);
     }
   }
 
@@ -206,17 +323,12 @@
 
   _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;
         for (var element in unit.topLevelVariables) {
@@ -224,22 +336,34 @@
         }
       }
     }
+  }
+
+  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..cc1830b
--- /dev/null
+++ b/pkg/analyzer/lib/src/summary2/type_alias.dart
@@ -0,0 +1,135 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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) {
+        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_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_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
index ced02d0..ce217cf 100644
--- a/pkg/analyzer/lib/src/test_utilities/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -107,6 +107,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..7e5bcbd 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;
+  }
 }
 
 /**
@@ -279,7 +287,15 @@
   WorkspacePackage findPackageFor(String filePath) {
     final Folder folder = provider.getFolder(filePath);
     if (provider.pathContext.isWithin(root, folder.path)) {
-      _theOnlyPackage ??= new PackageBuildWorkspacePackage(root, this);
+      List<String> uriParts =
+          (packageUriResolver as PackageBuildPackageUriResolver)
+              ._restoreUriParts('${folder.path}/lib/__fake__.dart');
+      if (uriParts == null || uriParts.isEmpty) {
+        _theOnlyPackage ??= new PackageBuildWorkspacePackage(null, root, this);
+      } else {
+        _theOnlyPackage ??=
+            new PackageBuildWorkspacePackage(uriParts[0], root, this);
+      }
       return _theOnlyPackage;
     } else {
       return null;
@@ -330,14 +346,23 @@
  * a given package in a PackageBuildWorkspace.
  */
 class PackageBuildWorkspacePackage extends WorkspacePackage {
+  /// A prefix for any URI of a path in this package.
+  final String _uriPrefix;
+
   final String root;
 
   final PackageBuildWorkspace workspace;
 
-  PackageBuildWorkspacePackage(this.root, this.workspace);
+  PackageBuildWorkspacePackage(String packageName, this.root, this.workspace)
+      : this._uriPrefix = 'package:$packageName/';
 
   @override
-  bool contains(String filePath) {
+  bool contains(Source source) {
+    if (source.uri.isScheme('package')) {
+      return source.uri.toString().startsWith(_uriPrefix);
+    }
+    String filePath = source.fullName;
+    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..1723adb 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.36.1-dev
+version: 0.36.3
 author: Dart Team <misc@dartlang.org>
 description: Static analyzer for Dart.
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/analyzer
@@ -11,10 +11,10 @@
   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/generated/checked_mode_compile_time_error_code_test.dart b/pkg/analyzer/test/generated/checked_mode_compile_time_error_code_test.dart
index 46f7960..4a01b55 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
@@ -227,10 +227,7 @@
   const A(String this.x);
 }
 var v = const A('foo');
-''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
-    ]);
+''', [StaticWarningCode.UNDEFINED_CLASS]);
   }
 
   test_fieldFormalParameterNotAssignableToField_implements() async {
@@ -362,10 +359,7 @@
   final Unresolved y;
 }
 var v = const A('foo');
-''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_FIELD_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
-    ]);
+''', [StaticWarningCode.UNDEFINED_CLASS]);
   }
 
   test_fieldTypeOk_generic() async {
@@ -489,10 +483,7 @@
   const A(Unresolved x);
 }
 var v = const A('foo');
-''', [
-      CheckedModeCompileTimeErrorCode.CONST_CONSTRUCTOR_PARAM_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
-    ]);
+''', [StaticWarningCode.UNDEFINED_CLASS]);
   }
 
   test_redirectingConstructor_paramTypeMismatch() async {
@@ -544,9 +535,6 @@
   test_topLevelVarNotAssignable_undefined() async {
     await assertErrorCodesInCode('''
 const Unresolved x = 'foo';
-''', [
-      CheckedModeCompileTimeErrorCode.VARIABLE_TYPE_MISMATCH,
-      StaticWarningCode.UNDEFINED_CLASS
-    ]);
+''', [StaticWarningCode.UNDEFINED_CLASS]);
   }
 }
diff --git a/pkg/analyzer/test/generated/compile_time_error_code.dart b/pkg/analyzer/test/generated/compile_time_error_code.dart
index 2daae3d..9d25dc4 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 {
+    // TODO(paulberry): remove when dartbug.com/28515 fixed.
+    if (AnalysisDriver.useSummary2) {
+      await assertNoErrorsInCode('''
+void g(T f<T>(T x)) {}
+''');
+    } else {
+      await assertErrorsInCode('''
+void g(T f<T>(T x)) {}
+''', [
+        // 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,10 @@
     int async;
   }
 }
-''', [ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER]);
+''', [
+      error(HintCode.UNUSED_LOCAL_VARIABLE, 32, 5),
+      error(ParserErrorCode.ASYNC_KEYWORD_USED_AS_IDENTIFIER, 32, 5),
+    ]);
   }
 
   test_invalidIdentifierInAsync_await() async {
@@ -2356,7 +2737,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 +2750,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 +2761,9 @@
 class A {
   A() async {}
 }
-''', [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR, 16, 5),
+    ]);
   }
 
   test_invalidModifierOnConstructor_asyncStar() async {
@@ -2382,7 +2771,9 @@
 class A {
   A() async* {}
 }
-''', [CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.INVALID_MODIFIER_ON_CONSTRUCTOR, 16, 5),
+    ]);
   }
 
   test_invalidModifierOnConstructor_syncStar() async {
@@ -2390,7 +2781,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 +2794,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 +2805,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 +2816,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 +2825,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 +2834,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 +2843,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 +2853,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 +2864,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 +2874,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 +2884,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 +2894,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 +2907,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 +2935,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 +2947,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 +2987,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 +3008,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 +3025,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 +3038,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 +3051,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 +3063,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 +3075,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 +3085,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 +3095,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 +3112,9 @@
 }
 class B extends Object with A {}
 ''',
-      [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
+      [
+        error(CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR, 49, 1),
+      ],
     );
   }
 
@@ -2686,40 +3126,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 +3186,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 +3198,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 +3219,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 +3253,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 +3262,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 +3272,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 +3282,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 +3292,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 +3404,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 +3443,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 +3454,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 +3464,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 +3474,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 +3486,10 @@
   A.a() {}
   A.b() {}
 }
-''', [CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS]);
+''', [
+      error(CompileTimeErrorCode.MULTIPLE_REDIRECTING_CONSTRUCTOR_INVOCATIONS,
+          28, 8),
+    ]);
   }
 
   test_multipleSuperInitializers() async {
@@ -3005,38 +3499,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 +3538,9 @@
 @A
 main() {
 }
-''', [CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.NO_ANNOTATION_CONSTRUCTOR_ARGUMENTS, 25, 2),
+    ]);
   }
 
   test_noDefaultSuperConstructorExplicit() async {
@@ -3058,7 +3551,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 +3563,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 +3585,9 @@
 @A.fromInt()
 main() {
 }
-''', [CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_CONSTANT_ANNOTATION_CONSTRUCTOR, 29, 12),
+    ]);
   }
 
   test_nonConstantAnnotationConstructor_unnamed() async {
@@ -3097,21 +3598,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 +3627,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 +3638,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 +3649,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 +3660,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 +3707,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 +3726,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 +3749,12 @@
       break;
   }
 }
-'''
-    ], [
-      CompileTimeErrorCode.NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY
+''', [
+      error(
+          CompileTimeErrorCode
+              .NON_CONSTANT_CASE_EXPRESSION_FROM_DEFERRED_LIBRARY,
+          87,
+          7),
     ]);
   }
 
@@ -3242,20 +3765,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 +3789,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 +3820,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 +3832,9 @@
   final int a;
   const A() : a = C;
 }
-''', [CompileTimeErrorCode.INVALID_CONSTANT]);
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 59, 1),
+    ]);
   }
 
   test_nonConstValueInInitializer_instanceCreation() async {
@@ -3321,27 +3850,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 +3877,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 +3891,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 +3960,8 @@
 class B extends A {
   const B() : super(a.c);
 }
-'''
-    ], <ErrorCode>[
-      CompileTimeErrorCode.INVALID_CONSTANT
+''', [
+      error(CompileTimeErrorCode.INVALID_CONSTANT, 114, 3),
     ]);
   }
 
@@ -3452,7 +3973,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 +3986,9 @@
 class B extends A {
   B();
 }
-''', [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, 57, 1),
+    ]);
   }
 
   test_nonGenerativeConstructor_implicit2() async {
@@ -3473,7 +3998,9 @@
 }
 class B extends A {
 }
-''', [CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.NON_GENERATIVE_CONSTRUCTOR, 41, 1),
+    ]);
   }
 
   test_notEnoughRequiredArguments_const() async {
@@ -3484,7 +4011,9 @@
 main() {
   const A();
 }
-''', [CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS]);
+''', [
+      error(CompileTimeErrorCode.NOT_ENOUGH_REQUIRED_ARGUMENTS, 48, 2),
+    ]);
   }
 
   test_notEnoughRequiredArguments_const_super() async {
@@ -3495,13 +4024,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 +4043,9 @@
 class A {
   operator +({p}) {}
 }
-''', [CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR]);
+''', [
+      error(CompileTimeErrorCode.OPTIONAL_PARAMETER_IN_OPERATOR, 24, 1),
+    ]);
   }
 
   test_optionalParameterInOperator_positional() async {
@@ -3517,28 +4053,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 +4090,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 +4104,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 +4120,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 +4134,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 +4148,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 +4163,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 +4177,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 +4192,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 +4206,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 +4220,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 +4234,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 +4248,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 +4262,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 +4276,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 +4290,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 +4305,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 +4324,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 +4361,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 +4398,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 +4418,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 +4428,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 +4457,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 +4479,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 +4491,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 +4501,9 @@
 class A {
   A() : this();
 }
-''', [CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_CONSTRUCTOR_REDIRECT, 18, 6),
+    ]);
   }
 
   test_recursiveFactoryRedirect() async {
@@ -3915,12 +4518,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 +4532,9 @@
 class A {
   factory A() = A;
 }
-''', [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 26, 1),
+    ]);
   }
 
   test_recursiveFactoryRedirect_diverging() async {
@@ -3943,7 +4548,9 @@
 main() {
   const C<int>();
 }
-''', [CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT]);
+''', [
+      error(CompileTimeErrorCode.RECURSIVE_FACTORY_REDIRECT, 35, 7),
+    ]);
   }
 
   test_recursiveFactoryRedirect_generic() async {
@@ -3958,12 +4565,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 +4586,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 +4611,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 +4623,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 +4635,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 +4652,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 +4665,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 +4676,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 +4686,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 +4697,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 +4720,9 @@
   v() {}
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 28, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_hideInBlock_local() async {
@@ -4106,7 +4733,9 @@
   var v = 2;
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 28, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_hideInBlock_subBlock() async {
@@ -4119,7 +4748,9 @@
   var v = 2;
 }
 print(x) {}
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 34, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_inInitializer_closure() async {
@@ -4127,7 +4758,9 @@
 main() {
   var v = () => v;
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 25, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_inInitializer_directly() async {
@@ -4135,7 +4768,9 @@
 main() {
   var v = v;
 }
-''', [CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION]);
+''', [
+      error(CompileTimeErrorCode.REFERENCED_BEFORE_DECLARATION, 19, 1),
+    ]);
   }
 
   test_referencedBeforeDeclaration_type_localFunction() async {
@@ -4143,8 +4778,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 +4790,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 +4802,9 @@
 f() {
   rethrow;
 }
-''', [CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH]);
+''', [
+      error(CompileTimeErrorCode.RETHROW_OUTSIDE_CATCH, 8, 7),
+    ]);
   }
 
   test_returnInGenerativeConstructor() async {
@@ -4169,7 +4812,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 +4822,9 @@
 class A {
   A() => null;
 }
-''', [CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR]);
+''', [
+      error(CompileTimeErrorCode.RETURN_IN_GENERATIVE_CONSTRUCTOR, 16, 8),
+    ]);
   }
 
   test_returnInGenerator_asyncStar() async {
@@ -4186,8 +4833,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 +4844,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 +4885,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 +4901,9 @@
     return null;
   }
 }
-''', [CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT], verify: false);
+''', [
+      error(CompileTimeErrorCode.SUPER_IN_INVALID_CONTEXT, 61, 5),
+    ]);
   }
 
   test_superInInvalidContext_instanceVariableInitializer() async {
@@ -4263,7 +4914,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 +4927,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 +4940,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 +4950,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 +4968,9 @@
 class Object {
   Object() : super();
 }
-''', [CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT]);
+''', [
+      error(CompileTimeErrorCode.SUPER_INITIALIZER_IN_OBJECT, 0, 0),
+    ]);
   }
 
   test_superInRedirectingConstructor_redirectionSuper() async {
@@ -4317,7 +4980,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 +4993,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 +5006,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 +5029,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 +5053,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 +5064,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 +5118,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,8 +5128,8 @@
 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),
     ]);
   }
 
@@ -4456,8 +5137,8 @@
     await assertErrorsInCode('''
 typedef A<T extends A<int>>();
 ''', [
-      CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF,
-      StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS
+      error(CompileTimeErrorCode.TYPE_ALIAS_CANNOT_REFERENCE_ITSELF, 0, 30),
+      error(StaticTypeWarningCode.TYPE_ARGUMENT_NOT_MATCHING_BOUNDS, 22, 3),
     ]);
   }
 
@@ -4469,15 +5150,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 +5169,9 @@
 @unresolved
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 11),
+    ]);
   }
 
   test_undefinedAnnotation_unresolved_invocation() async {
@@ -4494,7 +5179,9 @@
 @Unresolved()
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 13),
+    ]);
   }
 
   test_undefinedAnnotation_unresolved_prefixedIdentifier() async {
@@ -4503,7 +5190,9 @@
 @p.unresolved
 main() {
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 25, 13),
+    ]);
   }
 
   test_undefinedAnnotation_useLibraryScope() async {
@@ -4512,7 +5201,9 @@
 class A {
   static const foo = null;
 }
-''', [CompileTimeErrorCode.UNDEFINED_ANNOTATION]);
+''', [
+      error(CompileTimeErrorCode.UNDEFINED_ANNOTATION, 0, 4),
+    ]);
   }
 
   test_undefinedClass_const() async {
@@ -4520,7 +5211,9 @@
 f() {
   return const A();
 }
-''', [StaticWarningCode.UNDEFINED_CLASS]);
+''', [
+      error(StaticWarningCode.UNDEFINED_CLASS, 21, 1),
+    ]);
   }
 
   test_undefinedConstructorInInitializer_explicit_named() async {
@@ -4529,8 +5222,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 +5235,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 +5249,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 +5263,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 +5348,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 +5376,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 +5390,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 +5424,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 +5434,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 +5444,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 +5454,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 +5464,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 +5475,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 +5486,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 +5499,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 +5511,9 @@
 f() {
   yield* 0;
 }
-''', [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   test_yieldInNonGenerator_async() async {
@@ -4773,7 +5523,9 @@
 f() async {
   yield 0;
 }
-''', [CompileTimeErrorCode.YIELD_IN_NON_GENERATOR]);
+''', [
+      error(CompileTimeErrorCode.YIELD_IN_NON_GENERATOR, 0, 0),
+    ]);
   }
 
   test_yieldInNonGenerator_sync() async {
@@ -4783,14 +5535,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 +5554,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 +5565,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 +5576,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 +5588,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 +5599,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 +5610,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..57e5769 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,13 +77,6 @@
 
 @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('''
@@ -109,10 +100,6 @@
 
 @reflectiveTest
 class ControlFlowCollectionsTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [EnableString.control_flow_collections];
-
   test_awaitForIn_declaredVariableWrongType() async {
     await assertErrorCodesInCode('''
 import 'dart:async';
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index db29c01..f2ac4f2 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_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:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
@@ -20,6 +21,11 @@
 import 'test_support.dart';
 
 main() {
+  // With summary2 DeclarationResolver is not used.
+  if (AnalysisDriver.useSummary2) {
+    return;
+  }
+
   defineReflectiveSuite(() {
     defineReflectiveTests(DeclarationResolverMetadataTest);
     defineReflectiveTests(DeclarationResolverTest);
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..fe23034 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 assertNoErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -2402,9 +1910,7 @@
 
 class C extends A<int Function(String)> with M {}
 ''');
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    CompilationUnit unit = analysisResult.unit;
+    CompilationUnit unit = result.unit;
     ClassElement classC =
         resolutionMap.elementDeclaredByCompilationUnit(unit).getType('C');
     expect(classC.mixins, hasLength(1));
@@ -2412,7 +1918,7 @@
   }
 
   test_infer_mixin_with_substitution_new_syntax() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 abstract class A<T> {}
 
 class B {}
@@ -2421,10 +1927,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 +1935,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 +1955,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 +2082,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 +2183,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 +2225,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 +2233,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 +2244,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 +2252,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 +2261,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 +2269,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 +2285,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 +2293,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 +2307,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 +2323,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 +2335,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 +2351,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 +2446,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 +2503,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 +2582,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 +2602,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 +2613,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 +2641,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 +2661,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 +2782,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 +2795,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 +2809,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 +2831,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 +2844,8 @@
     }
     return 0;
   }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+}
+''');
   }
 
   test_mixin_of_mixin_type_argument_inference() async {
@@ -3500,14 +2853,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 +2868,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 +2913,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 +2921,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 +3008,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 +3114,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 +3127,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 +3140,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 +3227,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 +3344,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 +3360,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 +3442,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 +3460,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 +3488,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 +3670,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 +3692,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 +3719,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 +3753,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 +3774,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 +3787,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 +3809,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 +3845,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 +3869,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 +3903,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 +4022,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 +4053,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 +4071,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 +4158,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 +4174,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 +4278,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 +4308,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 +4321,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 +4334,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 +4347,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 +4364,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 +4402,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 +4415,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 +4454,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 +4621,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 +4685,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 +4728,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 +4741,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 +4804,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 +4817,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..20e6f2d 100644
--- a/pkg/analyzer/test/generated/parser_fasta_listener.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_listener.dart
@@ -244,9 +244,10 @@
   }
 
   @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');
   }
 
@@ -526,8 +527,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');
   }
 
@@ -701,12 +703,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
@@ -1014,11 +1016,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
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index ef81da6..104879f 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,13 @@
 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';
 
@@ -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);
@@ -1248,6 +1444,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 +1464,6 @@
   @override
   bool allowNativeClause = false;
 
-  @override
-  set enableLazyAssignmentOperators(bool value) {
-    // Lazy assignment operators are always enabled
-  }
-
   set enableOptionalNewAndConst(bool enable) {
     // ignored
   }
@@ -1305,10 +1509,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 +1606,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,9 +1627,8 @@
 
   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(
@@ -1435,11 +1637,19 @@
           .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);
+        configuration: Scanner.buildConfig(featureSet),
+        languageVersionChanged: languageVersionChanged);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -1454,15 +1664,11 @@
     // 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 +1720,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 +1905,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 +1978,188 @@
  */
 @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);
+  }
+}
 
 /**
  * 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;
-  }
-
   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); }',
+        featureSet: nonNullable);
   }
 
   void test_assignment_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
+    parseCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }',
+        featureSet: nonNullable);
   }
 
   void test_binary_expression_statement() {
-    final unit = parseNNBDCompilationUnit('D? foo(X? x) { X ?? x2; }');
+    final unit = parseCompilationUnit('D? foo(X? x) { X ?? x2; }',
+        featureSet: nonNullable);
     FunctionDeclaration funct = unit.declarations[0];
     BlockFunctionBody body = funct.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1820,24 +2172,28 @@
   }
 
   void test_conditional() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? 7 : y; }',
+        featureSet: nonNullable);
   }
 
   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; }',
+        featureSet: nonNullable);
   }
 
   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),
           expectedError(ParserErrorCode.MISSING_IDENTIFIER, 40, 1),
-        ]);
+        ],
+        featureSet: nonNullable);
   }
 
   void test_conditional_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
+    parseCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }',
+        featureSet: nonNullable);
   }
 
   void test_enableNonNullable_false() {
@@ -1846,49 +2202,59 @@
   }
 
   void test_for() {
-    parseNNBDCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }',
+        featureSet: nonNullable);
   }
 
   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) { } }',
+        featureSet: nonNullable);
   }
 
   void test_for_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
+    parseCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }',
+        featureSet: nonNullable);
   }
 
   void test_foreach() {
-    parseNNBDCompilationUnit('main() { for(int x in [7]) { } }');
+    parseCompilationUnit('main() { for(int x in [7]) { } }',
+        featureSet: nonNullable);
   }
 
   void test_foreach_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x in [7, null]) { } }');
+    parseCompilationUnit('main() { for(int? x in [7, null]) { } }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable() {
-    parseNNBDCompilationUnit('main() { C? Function() x = 7; }');
+    parseCompilationUnit('main() { C? Function() x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_1() {
-    parseNNBDCompilationUnit('main() { C Function()? x = 7; }');
+    parseCompilationUnit('main() { C Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_2() {
-    parseNNBDCompilationUnit('main() { C? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_3() {
-    parseNNBDCompilationUnit('main() { C? Function()? Function()? x = 7; }');
+    parseCompilationUnit('main() { C? Function()? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_gft_nullable_prefixed() {
-    parseNNBDCompilationUnit('main() { C.a? Function()? x = 7; }');
+    parseCompilationUnit('main() { C.a? Function()? x = 7; }',
+        featureSet: nonNullable);
   }
 
   void test_is_nullable() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { x is String? ? (x + y) : z; }');
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { x is String? ? (x + y) : z; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1903,8 +2269,9 @@
   }
 
   void test_is_nullable_parenthesis() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
+    CompilationUnit unit = parseCompilationUnit(
+        'main() { (x is String?) ? (x + y) : z; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     ExpressionStatement statement = body.block.statements[0];
@@ -1919,8 +2286,51 @@
     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)],
+        featureSet: nonNullable);
+  }
+
+  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());
+}
+''', featureSet: nonNullable);
+  }
+
   void test_nullCheck() {
-    var unit = parseNNBDCompilationUnit('f(int? y) { var x = y!; }');
+    var unit = parseCompilationUnit('f(int? y) { var x = y!; }',
+        featureSet: nonNullable);
     FunctionDeclaration function = unit.declarations[0];
     BlockFunctionBody body = function.functionExpression.body;
     VariableDeclarationStatement statement = body.block.statements[0];
@@ -1931,11 +2341,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];
@@ -1944,124 +2355,137 @@
   }
 
   void test_nullCheckFunctionResult() {
-    parseNNBDCompilationUnit('f() { var x = g()! + 7; }');
+    parseCompilationUnit('f() { var x = g()! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckIndexedValue() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y[0]! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckIndexedValue2() {
-    parseNNBDCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = super.y[0]! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckInExpression() {
-    parseNNBDCompilationUnit('f(int? y) { var x = y! + 7; }');
+    parseCompilationUnit('f(int? y) { var x = y! + 7; }',
+        featureSet: nonNullable);
   }
 
   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; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckMethodResult2() {
-    parseNNBDCompilationUnit('f() { var x = g?.m()! + 7; }');
+    parseCompilationUnit('f() { var x = g?.m()! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckMethodResult3() {
-    parseNNBDCompilationUnit('f() { var x = super.m()! + 7; }');
+    parseCompilationUnit('f() { var x = super.m()! + 7; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnConstConstructor() {
-    parseNNBDCompilationUnit('f() { var x = const Foo()!; }');
+    parseCompilationUnit('f() { var x = const Foo()!; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckOnConstructor() {
-    parseNNBDCompilationUnit('f() { var x = new Foo()!; }');
+    parseCompilationUnit('f() { var x = new Foo()!; }',
+        featureSet: nonNullable);
   }
 
   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!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralInt() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = 0!; }');
+    parseCompilationUnit('f() { var x = 0!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralList() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = [1,2]!; }');
+    parseCompilationUnit('f() { var x = [1,2]!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralMap() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1:2}!; }');
+    parseCompilationUnit('f() { var x = {1:2}!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralSet() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = {1,2}!; }');
+    parseCompilationUnit('f() { var x = {1,2}!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnLiteralString() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = "seven"!; }');
+    parseCompilationUnit('f() { var x = "seven"!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnNull() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = null!; }');
+    parseCompilationUnit('f() { var x = null!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnSymbol() {
     // Issues like this should be caught during later analysis
-    parseNNBDCompilationUnit('f() { var x = #seven!; }');
+    parseCompilationUnit('f() { var x = #seven!; }', featureSet: nonNullable);
   }
 
   void test_nullCheckOnValue() {
-    parseNNBDCompilationUnit('f(Point p) { var x = p.y! + 7; }');
+    parseCompilationUnit('f(Point p) { var x = p.y! + 7; }',
+        featureSet: nonNullable);
   }
 
   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; }',
+        featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess() {
-    parseNNBDCompilationUnit('f() { var x = g.p! + 7; }');
+    parseCompilationUnit('f() { var x = g.p! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess2() {
-    parseNNBDCompilationUnit('f() { var x = g?.p! + 7; }');
+    parseCompilationUnit('f() { var x = g?.p! + 7; }', featureSet: nonNullable);
   }
 
   void test_nullCheckPropertyAccess3() {
-    parseNNBDCompilationUnit('f() { var x = super.p! + 7; }');
+    parseCompilationUnit('f() { var x = super.p! + 7; }',
+        featureSet: nonNullable);
   }
 
   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!; }', featureSet: nonNullable);
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2073,7 +2497,8 @@
 
   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++!; }', featureSet: nonNullable);
     var function = unit.declarations[0] as FunctionDeclaration;
     var body = function.functionExpression.body as BlockFunctionBody;
     var statement = body.block.statements[0] as ExpressionStatement;
@@ -2105,21 +2530,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;
   }
@@ -2299,8 +2726,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 +2800,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 +2899,7 @@
     ForStatement forStatement = parseStatement(
       'await for (element in list) {}',
       inAsync: true,
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNotNull);
@@ -2434,10 +2913,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 +2967,7 @@
   void test_parseForStatement_each_identifier2() {
     ForStatement forStatement = parseStatement(
       'for (element in list) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.awaitKeyword, isNull);
@@ -2471,7 +2984,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 +3002,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 +3019,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 +3036,7 @@
   void test_parseForStatement_loop_c2() {
     ForStatement forStatement = parseStatement(
       'for (; i < count;) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2541,7 +3054,7 @@
   void test_parseForStatement_loop_cu2() {
     ForStatement forStatement = parseStatement(
       'for (; i < count; i++) {}',
-      parseControlFlowCollections: true,
+      featureSet: controlFlow,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2559,7 +3072,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 +3090,7 @@
   void test_parseForStatement_loop_i2() {
     ForStatement forStatement = parseStatement(
       'for (var i = 0;;) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2598,7 +3111,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 +3132,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 +3152,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 +3172,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 +3192,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 +3212,7 @@
   void test_parseForStatement_loop_u2() {
     ForStatement forStatement = parseStatement(
       'for (;; i++) {}',
-      parseSpreadCollections: true,
+      featureSet: spread,
     );
     assertNoErrors();
     expect(forStatement.forKeyword, isNotNull);
@@ -2754,101 +3267,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 +3502,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..3e203b1 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];
@@ -2467,6 +2512,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();
@@ -6375,7 +6434,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 +8208,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 +8226,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 +8244,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 +8265,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 +8284,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 +8302,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 +8321,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 +8339,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 +8358,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 +8376,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 +8397,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 +8415,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 +8433,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 +8453,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 +8471,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 +8488,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 +8508,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 +8526,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 +8543,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 +8562,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 +8579,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 +8599,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 +8617,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 +8634,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 +8654,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 +8674,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 +8692,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 +8709,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);
@@ -9275,12 +9361,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.
    */
@@ -9338,9 +9418,7 @@
     //
     // Scan the source.
     //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
+    ScannerResult result = scanString(content, includeComments: true);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -9354,7 +9432,7 @@
     //
     // 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;
@@ -9488,9 +9566,7 @@
     //
     // Scan the source.
     //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
+    ScannerResult result = scanString(content, includeComments: true);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -9502,7 +9578,8 @@
     }
     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);
     expect(unit, isNotNull);
@@ -9533,9 +9610,7 @@
     //
     // Scan the source.
     //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
+    ScannerResult result = scanString(content, includeComments: true);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -9546,7 +9621,8 @@
       }
     }
 
-    Parser parser = new Parser(source, listener);
+    Parser parser =
+        new Parser(source, listener, featureSet: FeatureSet.forTesting());
     parser.enableOptionalNewAndConst = enableOptionalNewAndConst;
     CompilationUnit unit = parser.parseCompilationUnit(token);
     unit.lineInfo = new LineInfo(result.lineStarts);
@@ -9872,13 +9948,9 @@
    * 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) {
@@ -9889,9 +9961,7 @@
     //
     // Scan the source.
     //
-    ScannerResult result = scanString(content,
-        includeComments: true,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
+    ScannerResult result = scanString(content, includeComments: true);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -9903,7 +9973,8 @@
     }
     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);
     expect(statement, isNotNull);
@@ -9935,8 +10006,7 @@
     //
     // Scan the source.
     //
-    ScannerResult result = scanString(content,
-        scanLazyAssignmentOperators: enableLazyAssignmentOperators);
+    ScannerResult result = scanString(content);
     Token token = result.tokens;
     if (result.hasErrors) {
       // The default recovery strategy used by scanString
@@ -9948,7 +10018,8 @@
     }
     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);
     expect(statements, hasLength(expectedCount));
@@ -12345,7 +12416,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 +16477,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..59f614f 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -152,7 +152,7 @@
 }
 
 @reflectiveTest
-class EnclosedScopeTest extends ResolverTestCase {
+class EnclosedScopeTest extends DriverResolutionTest {
   test_define_duplicate() async {
     Scope rootScope = new _RootScope();
     EnclosedScope scope = new EnclosedScope(rootScope);
@@ -332,7 +332,7 @@
 }
 
 @reflectiveTest
-class PrefixedNamespaceTest extends ResolverTestCase {
+class PrefixedNamespaceTest extends DriverResolutionTest {
   void test_lookup_missing() {
     ClassElement element = ElementFactory.classElement2('A');
     PrefixedNamespace namespace = new PrefixedNamespace('p', _toMap([element]));
@@ -361,7 +361,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 +574,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),
+    ]);
   }
 }
 
@@ -1834,6 +1822,7 @@
         AstTestFactory.functionTypedFormalParameter(
             AstTestFactory.typeName4('R'), 'g', [eNode]);
     ParameterElementImpl gElement = ElementFactory.requiredParameter('g');
+    gElement.typeParameters = [elementE];
     gNode.identifier.staticElement = gElement;
 
     FunctionTypeImpl gType =
@@ -1952,7 +1941,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 +1982,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]);
diff --git a/pkg/analyzer/test/generated/resolver_test_case.dart b/pkg/analyzer/test/generated/resolver_test_case.dart
index 9f11907..611479c 100644
--- a/pkg/analyzer/test/generated/resolver_test_case.dart
+++ b/pkg/analyzer/test/generated/resolver_test_case.dart
@@ -795,6 +795,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..02039f4 100644
--- a/pkg/analyzer/test/generated/scanner_test.dart
+++ b/pkg/analyzer/test/generated/scanner_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/token.dart';
 import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
@@ -77,6 +78,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 +129,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;
@@ -164,11 +168,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/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index aebb310..8382b04 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';
@@ -1533,6 +1534,7 @@
     _typeProvider = context.typeProvider;
     _visitor = new ResolverVisitor(
         inheritance, definingLibrary, source, _typeProvider, _listener,
+        featureSet: FeatureSet.forTesting(),
         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..4d44cbd 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 {
@@ -2702,8 +2698,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', '((T) → T, (T, T) → int, (T) → T) → void');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -2729,8 +2729,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', '(List<T>, (T, T) → int, List<T>) → void');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -2756,8 +2760,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', '(T, (T, T) → int, T) → void');
+      } else {
+        expect(fType.typeArguments[0].toString(), 'T');
+      }
     }
   }
 
@@ -3898,76 +3906,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() {
@@ -4049,15 +3999,13 @@
   }
 
   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>(T) → T');
     FunctionType ft = type.instantiate([typeProvider.stringType]);
     expect(ft.toString(), '(String) → String');
   }
@@ -4222,26 +4170,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 +4219,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 +4262,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");
   }
 
@@ -4381,12 +4339,14 @@
   }
 
   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");
   }
 
@@ -4497,6 +4457,7 @@
     expectIdentifierType('f;', '<S₀>(S₀) → S');
   }
 
+  @FailingTest(issue: 'https://github.com/dart-lang/sdk/issues/30236')
   test_genericMethod_nestedCaptureBounds() async {
     await resolveTestUnit(r'''
 class C<T> {
@@ -4706,6 +4667,7 @@
     expectIdentifierType('paramTearOff', "<T>(T) → T");
   }
 
+  @failingTest
   test_genericMethod_tearoff_instantiated() async {
     await resolveTestUnit(r'''
 class C<E> {
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/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..83168dd 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>();
 
 /**
@@ -1205,7 +1204,11 @@
     FunctionExpressionInvocation invocation = field.initializer;
     FunctionExpression closure = invocation.function.unParenthesized;
     FunctionElementImpl closureElement = closure.declaredElement;
-    expect(closureElement.enclosingElement, same(fieldInitializer));
+    if (AnalysisDriver.useSummary2) {
+      expect(closureElement.enclosingElement, same(field.declaredElement));
+    } else {
+      expect(closureElement.enclosingElement, same(fieldInitializer));
+    }
   }
 
   test_closure_inTopLevelVariable() async {
@@ -1223,7 +1226,11 @@
     FunctionExpressionInvocation invocation = variable.initializer;
     FunctionExpression closure = invocation.function.unParenthesized;
     FunctionElementImpl closureElement = closure.declaredElement;
-    expect(closureElement.enclosingElement, same(variableInitializer));
+    if (AnalysisDriver.useSummary2) {
+      expect(closureElement.enclosingElement, same(variable.declaredElement));
+    } else {
+      expect(closureElement.enclosingElement, same(variableInitializer));
+    }
   }
 
   test_conditionalExpression() async {
@@ -1837,12 +1844,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 {
@@ -5441,8 +5448,13 @@
       assertMember(invocation.methodName, 'C<int>', mElement);
       assertType(invocation.methodName, '<U>(int, U) → Map<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]);
+      }
     }
   }
 
@@ -5562,8 +5574,13 @@
     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 {
@@ -7219,7 +7236,7 @@
 
     SimpleIdentifier dName = enumNode.name;
     expect(dName.staticElement, same(enumElement));
-    expect(dName.staticType, typeProvider.typeType);
+    expect(dName.staticType, isNull);
 
     {
       var aElement = enumElement.getField('A');
@@ -8095,7 +8112,6 @@
     assertType(identifier, 'Type');
   }
 
-  @failingTest
   test_unresolved_instanceCreation_name_11() async {
     addTestFile(r'''
 int arg1, arg2;
@@ -8226,12 +8242,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 +8289,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 +8766,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..964254e 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -39,6 +39,9 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(AnalysisDriverSchedulerTest);
     defineReflectiveTests(AnalysisDriverTest);
+    if (!AnalysisDriver.useSummary2) {
+      defineReflectiveTests(AnalysisDriverSummary1Test);
+    }
     defineReflectiveTests(CacheAllAnalysisDriverTest);
   });
 }
@@ -344,6 +347,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 +1472,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 +1735,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);
   }
 
@@ -2465,41 +2514,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);
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/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/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/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/element/function_type_test.dart b/pkg/analyzer/test/src/dart/element/function_type_test.dart
index 975952b..a0c2fd3 100644
--- a/pkg/analyzer/test/src/dart/element/function_type_test.dart
+++ b/pkg/analyzer/test/src/dart/element/function_type_test.dart
@@ -497,7 +497,7 @@
         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));
   }
@@ -1226,7 +1226,9 @@
   ClassElement get enclosingElement => super.enclosingElement;
 }
 
-class MockParameterElement implements ParameterElementImpl {
+class MockParameterElement
+    with ParameterElementMixin
+    implements ParameterElementImpl {
   @override
   Element enclosingElement;
 
@@ -1245,15 +1247,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/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/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..7bfebe1
--- /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, '(int) → bool');
+    assertTypeArgumentTypes(invocation, ['int']);
+  }
+}
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..0f402b5 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -629,7 +629,10 @@
       StaticTypeWarningCode.UNDEFINED_METHOD,
     ]);
 
-    _assertUnresolvedMethodInvocation('foo<int>();');
+    _assertUnresolvedMethodInvocation(
+      'foo<int>();',
+      expectedTypeArguments: ['int'],
+    );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
 
@@ -1018,6 +1021,7 @@
       findNode.methodInvocation('foo<int>()'),
       findElement.topFunction('foo'),
       '() → Map<num, dynamic>',
+      expectedTypeArguments: ['num', 'dynamic'],
     );
     assertTypeName(findNode.typeName('int>'), intElement, 'int');
   }
@@ -1132,6 +1136,7 @@
       invocation,
       import.topFunction('foo'),
       '(int, int) → int',
+      expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1159,6 +1164,7 @@
       import.topGetter('foo'),
       '(int, int) → int',
       expectedMethodNameType: '() → <T>(T, T) → T',
+      expectedTypeArguments: ['int'],
     );
     assertImportPrefix(invocation.target, import.prefix);
   }
@@ -1231,6 +1237,7 @@
       '(int) → void',
       expectedMethodNameType: '(int) → void',
     );
+    assertTypeArgumentTypes(invocation, []);
   }
 
   test_hasReceiver_instance_method_generic() async {
@@ -1254,7 +1261,9 @@
       findElement.method('foo'),
       '(int) → int',
       expectedMethodNameType: '(int) → int',
+      expectedTypeArguments: ['int'],
     );
+    assertTypeArgumentTypes(invocation, ['int']);
   }
 
   test_hasReceiver_instance_method_issue30552() async {
@@ -1721,9 +1730,77 @@
     );
   }
 
+  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..a88f8a3 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>');
   }
 
   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,8 +1773,6 @@
 
 class X extends A with M {}
 ''');
-    await resolveTestFile();
-    assertNoTestErrors();
 
     var invocation = findNode.methodInvocation('foo(42)');
     assertElement(invocation, findElement.method('foo'));
@@ -1929,7 +1781,7 @@
   }
 
   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/non_nullable_test.dart b/pkg/analyzer/test/src/dart/resolution/non_nullable_test.dart
index 820678a..0011f32 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() {
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..813eec5 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,6 +110,7 @@
       creation,
       libraryA.getType('A'),
       'A',
+      expectedPrefix: _importOfA()?.prefix,
     );
   }
 
@@ -118,6 +123,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 +168,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..fadcc32 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.
@@ -281,11 +279,15 @@
     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);
@@ -373,6 +377,14 @@
         expected);
   }
 
+  void assertTypeArgumentTypes(
+    InvocationExpression node,
+    List<String> expected,
+  ) {
+    var actual = node.typeArgumentTypes.map((t) => '$t').toList();
+    expect(actual, expected);
+  }
+
   void assertTypeDynamic(Expression expression) {
     DartType actual = expression.staticType;
     expect(actual, isDynamicType);
@@ -395,7 +407,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);
     }
   }
 
diff --git a/pkg/analyzer/test/src/dart/resolution/test_all.dart b/pkg/analyzer/test/src/dart/resolution/test_all.dart
index ccbc919..ebd712a 100644
--- a/pkg/analyzer/test/src/dart/resolution/test_all.dart
+++ b/pkg/analyzer/test/src/dart/resolution/test_all.dart
@@ -9,11 +9,14 @@
 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 '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_type_alias_test.dart' as generic_type_alias;
 import 'import_prefix_test.dart' as import_prefix;
 import 'instance_creation_test.dart' as instance_creation;
@@ -36,11 +39,13 @@
     class_resolution.main();
     comment.main();
     constant.main();
+    constructor.main();
     definite_assignment.main();
     enum_resolution.main();
     flow_analysis.main();
     for_element.main();
     for_in.main();
+    function_expression_invocation.main();
     generic_type_alias.main();
     import_prefix.main();
     instance_creation.main();
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/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/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/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..78754f2 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,13 +29,6 @@
 
 @reflectiveTest
 class AmbiguousSetOrMapLiteralEitherTest extends DriverResolutionTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections
-    ];
-
   test_setAndMap() async {
     assertErrorsInCode('''
 var map;
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..8c5c365 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,90 @@
     : 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_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),
+              ]);
   }
 }
 
@@ -151,90 +215,3 @@
 ''');
   }
 }
-
-@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..1769170
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/default_list_constructor_mismatch_test.dart
@@ -0,0 +1,70 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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);
+''');
+  }
+
+  @failingTest
+  test_inferredType() async {
+    // This test is failing because summary support is incomplete, which results
+    // in the constructor having a type of 'List<C*>*'.
+    await assertErrorsInCode('''
+class C {}
+List<C> v = List(5);
+''', [
+      error(CompileTimeErrorCode.DEFAULT_LIST_CONSTRUCTOR_MISMATCH, 23, 4),
+    ]);
+  }
+
+  test_starType() async {
+    // TODO(brianwilkerson) This test is currently taking advantage of the fact
+    //  that the SDK is not opted in, which makes the use of `int` below a
+    //  reference to 'int*'. When it's possible to opt-out in a test this needs
+    //  to be updated to use an explicitly opted out type.
+    await assertNoErrorsInCode('''
+List<int> v = List(5);
+''');
+  }
+
+  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/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/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..cee830f 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,44 +10,11 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapEntryNotInMapTest);
-    defineReflectiveTests(MapEntryNotInMapWithUiAsCodeTest);
   });
 }
 
 @reflectiveTest
 class MapEntryNotInMapTest extends DriverResolutionTest {
-  bool get isUiAsCode => analysisOptions.experimentStatus.spread_collections;
-
-  test_set() async {
-    await assertErrorCodesInCode('''
-var c = <int>{1:2};
-''', [
-      isUiAsCode
-          ? CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP
-          : ParserErrorCode.UNEXPECTED_TOKEN
-    ]);
-  }
-
-  test_set_const() async {
-    await assertErrorCodesInCode('''
-var c = const <int>{1:2};
-''', [
-      isUiAsCode
-          ? CompileTimeErrorCode.MAP_ENTRY_NOT_IN_MAP
-          : ParserErrorCode.UNEXPECTED_TOKEN
-    ]);
-  }
-}
-
-@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};
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..9fea9f5 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,76 +12,12 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapKeyTypeNotAssignableTest);
-    defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(MapKeyTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(MapKeyTypeNotAssignableWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class MapKeyTypeNotAssignableTest extends DriverResolutionTest {
-  test_const_intInt_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 0;
-var v = const <int, bool>{a : true};
-''');
-  }
-
-  test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
-const dynamic a = 'a';
-var v = const <int, bool>{a : true};
-''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_const_intString_value() async {
-    await assertErrorCodesInCode('''
-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(
         '''
@@ -163,6 +99,26 @@
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
 
+  test_const_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <int, bool>{a : true};
+''');
+  }
+
+  test_const_intString_dynamic() async {
+    await assertErrorCodesInCode('''
+const dynamic a = 'a';
+var v = const <int, bool>{a : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_intString_value() async {
+    await assertErrorCodesInCode('''
+var v = const <int, bool>{'a' : true};
+''', [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+  }
+
   test_const_spread_intInt() async {
     await assertErrorCodesInCode(
         '''
@@ -223,6 +179,26 @@
 ''');
   }
 
+  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]);
+  }
+
   test_nonConst_spread_intInt() async {
     await assertNoErrorsInCode('''
 var v = <int, String>{...{1: 'a'}};
@@ -248,3 +224,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..30e7865 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
@@ -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,76 +10,11 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(MapValueTypeNotAssignableTest);
-    defineReflectiveTests(
-        MapValueTypeNotAssignableWithUIAsCodeAndConstantsTest);
-    defineReflectiveTests(MapValueTypeNotAssignableWithUIAsCodeTest);
   });
 }
 
 @reflectiveTest
 class MapValueTypeNotAssignableTest extends DriverResolutionTest {
-  test_const_intInt_dynamic() async {
-    await assertNoErrorsInCode('''
-const dynamic a = 0;
-var v = const <bool, int>{true: a};
-''');
-  }
-
-  test_const_intString_dynamic() async {
-    await assertErrorCodesInCode('''
-const dynamic a = 'a';
-var v = const <bool, int>{true: a};
-''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_const_intString_value() async {
-    await assertErrorCodesInCode('''
-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(
         '''
@@ -163,6 +96,26 @@
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
 
+  test_const_intInt_dynamic() async {
+    await assertNoErrorsInCode('''
+const dynamic a = 0;
+var v = const <bool, int>{true: a};
+''');
+  }
+
+  test_const_intString_dynamic() async {
+    await assertErrorCodesInCode('''
+const dynamic a = 'a';
+var v = const <bool, int>{true: a};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_const_intString_value() async {
+    await assertErrorCodesInCode('''
+var v = const <bool, int>{true: 'a'};
+''', [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+  }
+
   test_const_spread_intInt() async {
     await assertErrorCodesInCode(
         '''
@@ -223,6 +176,26 @@
 ''');
   }
 
+  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]);
+  }
+
   test_nonConst_spread_intInt() async {
     await assertNoErrorsInCode('''
 var v = <bool, int>{...{true: 1}};
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..dd0e60d 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() => null;
+g() {
+  f()();
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 53, 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}) => null;
+}
+''', [
+      error(CompileTimeErrorCode.MISSING_REQUIRED_ARGUMENT, 20, 7),
+    ]);
+  }
+}
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..1479299
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/mixin_super_class_constraint_non_interface_test.dart
@@ -0,0 +1,39 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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]);
+
+  @failingTest
+  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_call_super_test.dart b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
index 588df81..7230ed0 100644
--- a/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/must_call_super_test.dart
@@ -52,6 +52,20 @@
 ''', [HintCode.MUST_CALL_SUPER]);
   }
 
+  test_fromExtendingClass_abstractImplementation() 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 {
     await assertNoErrorsInCode(r'''
 import 'package:meta/meta.dart';
@@ -66,6 +80,20 @@
 ''');
   }
 
+  test_fromMixin() async {
+    await assertErrorCodesInCode(r'''
+import 'package:meta/meta.dart';
+class Mixin {
+  @mustCallSuper
+  void a() {}
+}
+class C with Mixin {
+  @override
+  void a() {}
+}
+''', [HintCode.MUST_CALL_SUPER]);
+  }
+
   test_indirectlyInherited() async {
     await assertErrorCodesInCode(r'''
 import 'package:meta/meta.dart';
@@ -86,6 +114,35 @@
 ''', [HintCode.MUST_CALL_SUPER]);
   }
 
+  test_indirectlyInheritedFromMixin() async {
+    await assertErrorCodesInCode(r'''
+import 'package:meta/meta.dart';
+class Mixin {
+  @mustCallSuper
+  void b() {}
+}
+class C extends Object with Mixin {}
+class D extends C {
+  @override
+  void b() {}
+}
+''', [HintCode.MUST_CALL_SUPER]);
+  }
+
+  test_indirectlyInheritedFromMixinConstraint() async {
+    await assertErrorCodesInCode(r'''
+import 'package:meta/meta.dart';
+class A {
+  @mustCallSuper
+  void a() {}
+}
+mixin C on A {
+  @override
+  void a() {}
+}
+''', [HintCode.MUST_CALL_SUPER]);
+  }
+
   test_overriddenWithFuture() async {
     // https://github.com/flutter/flutter/issues/11646
     await assertNoErrorsInCode(r'''
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..511316a 100644
--- a/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/non_bool_condition_test.dart
@@ -11,36 +11,13 @@
 
 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(
         '''
@@ -54,3 +31,10 @@
               ]);
   }
 }
+
+@reflectiveTest
+class NonBoolConditionWithConstantsTest extends NonBoolConditionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
+}
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..4ae32aa 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,19 +12,14 @@
 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;''');
@@ -154,9 +149,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..de4f61f 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,56 +13,13 @@
   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)
@@ -91,4 +48,30 @@
               ]
             : [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
   }
+
+  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 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..585bf90 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,57 +12,12 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantListElementTest);
-    defineReflectiveTests(NonConstantListElementWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantListElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantListElementWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantListElementTest extends DriverResolutionTest {
-  test_const_topVar() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const [a];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_const_topVar_nested() async {
-    await assertErrorCodesInCode(r'''
-final dynamic a = 0;
-var v = const [a + 1];
-''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
-  }
-
-  test_nonConst_topVar() async {
-    await assertNoErrorsInCode('''
-final dynamic a = 0;
-var v = [a];
-''');
-  }
-}
-
-@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
-    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 = {};
@@ -133,4 +88,33 @@
 var v = const [if (1 > 0) a];
 ''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
   }
+
+  test_const_topVar() async {
+    await assertErrorCodesInCode('''
+final dynamic a = 0;
+var v = const [a];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_const_topVar_nested() async {
+    await assertErrorCodesInCode(r'''
+final dynamic a = 0;
+var v = const [a + 1];
+''', [CompileTimeErrorCode.NON_CONSTANT_LIST_ELEMENT]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = [a];
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantListElementWithConstantsTest
+    extends NonConstantListElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..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..c6c69bd 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,36 +11,15 @@
 
 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('''
 void main() {
@@ -135,31 +114,14 @@
 }
 
 @reflectiveTest
-class NonConstantMapKeyTest extends DriverResolutionTest {
-  test_const_topVar() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int, int>{a: 0};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
-  }
-
-  test_nonConst_topVar() async {
-    await assertNoErrorsInCode('''
-final dynamic a = 0;
-var v = <int, int>{a: 0};
-''');
-  }
+class NonConstantMapElementWithConstantTest extends NonConstantMapElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 }
 
 @reflectiveTest
-class NonConstantMapKeyWithUiAsCodeTest extends NonConstantMapKeyTest {
-  @override
-  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
-    ..enabledExperiments = [
-      EnableString.control_flow_collections,
-      EnableString.spread_collections,
-    ];
-
+class NonConstantMapKeyTest extends DriverResolutionTest {
   test_const_ifElement_thenElseFalse_finalElse() async {
     await assertErrorCodesInCode(
         '''
@@ -247,34 +209,24 @@
             ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
-}
 
-@reflectiveTest
-class NonConstantMapValueTest extends DriverResolutionTest {
   test_const_topVar() async {
     await assertErrorCodesInCode('''
 final dynamic a = 0;
-var v = const <int, int>{0: a};
-''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+var v = const <int, int>{a: 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
   }
 
   test_nonConst_topVar() async {
     await assertNoErrorsInCode('''
 final dynamic a = 0;
-var v = <int, int>{0: a};
+var v = <int, int>{a: 0};
 ''');
   }
 }
 
 @reflectiveTest
-class NonConstantMapValueWithUiAsCodeTest extends NonConstantMapValueTest {
-  @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(
         '''
@@ -362,4 +314,18 @@
             ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
+
+  test_const_topVar() async {
+    await assertErrorCodesInCode('''
+final dynamic a = 0;
+var v = const <int, int>{0: a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int, int>{0: a};
+''');
+  }
 }
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..3b3be9c 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,54 +13,12 @@
   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
@@ -86,4 +44,30 @@
             ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY_FROM_DEFERRED_LIBRARY]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
+
+  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 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..5d865e5 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,42 +12,12 @@
 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(
         r'''
@@ -71,4 +41,18 @@
             ? [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
+
+  test_const_topLevel() async {
+    await assertErrorCodesInCode(r'''
+final dynamic a = 0;
+var v = const {a : 0};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_KEY]);
+  }
+}
+
+@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..5e1e315 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,55 +13,12 @@
   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
@@ -90,4 +47,30 @@
               ]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
+
+  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 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..eb75842 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,42 +12,12 @@
 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(
         r'''
@@ -74,4 +44,18 @@
             ? [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]
             : [CompileTimeErrorCode.NON_CONSTANT_MAP_ELEMENT]);
   }
+
+  test_const_topLevel() async {
+    await assertErrorCodesInCode(r'''
+final dynamic a = 0;
+var v = const {'a' : a};
+''', [CompileTimeErrorCode.NON_CONSTANT_MAP_VALUE]);
+  }
+}
+
+@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..f4d6ff7 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,56 +13,13 @@
   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
@@ -91,4 +48,30 @@
               ]
             : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
   }
+
+  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 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..cb461c7 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,56 +12,12 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(NonConstantSetElementTest);
-    defineReflectiveTests(NonConstantSetElementWithUiAsCodeAndConstantsTest);
-    defineReflectiveTests(NonConstantSetElementWithUiAsCodeTest);
+    defineReflectiveTests(NonConstantSetElementWithConstantsTest);
   });
 }
 
 @reflectiveTest
 class NonConstantSetElementTest extends DriverResolutionTest {
-  test_const_parameter() async {
-    await assertErrorCodesInCode(r'''
-f(a) {
-  return const {a};
-}''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_const_topVar() async {
-    await assertErrorCodesInCode('''
-final dynamic a = 0;
-var v = const <int>{a};
-''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
-  }
-
-  test_nonConst_topVar() async {
-    await assertNoErrorsInCode('''
-final dynamic a = 0;
-var v = <int>{a};
-''');
-  }
-}
-
-@reflectiveTest
-class NonConstantSetElementWithUiAsCodeAndConstantsTest
-    extends NonConstantSetElementWithUiAsCodeTest {
-  @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;
@@ -126,10 +82,38 @@
 ''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
   }
 
+  test_const_parameter() async {
+    await assertErrorCodesInCode(r'''
+f(a) {
+  return const {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]);
   }
+
+  test_const_topVar() async {
+    await assertErrorCodesInCode('''
+final dynamic a = 0;
+var v = const <int>{a};
+''', [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
+  }
+
+  test_nonConst_topVar() async {
+    await assertNoErrorsInCode('''
+final dynamic a = 0;
+var v = <int>{a};
+''');
+  }
+}
+
+@reflectiveTest
+class NonConstantSetElementWithConstantsTest extends NonConstantSetElementTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..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..ac6d136 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,13 +20,6 @@
 @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 = [];''');
@@ -156,9 +149,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..129bb73 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];
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..d5142c1 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};
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..56bcd2c 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,13 +15,6 @@
 
 @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('''
 var v = [...null];
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/sdk_version_ui_as_code_test.dart b/pkg/analyzer/test/src/diagnostics/sdk_version_ui_as_code_test.dart
index d14a9a2..53017da 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];
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..641a352 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,63 +12,12 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(SetElementTypeNotAssignableTest);
-    defineReflectiveTests(
-        SetElementTypeNotAssignableWithUiAsCodeAndConstantTest);
-    defineReflectiveTests(SetElementTypeNotAssignableWithUIAsCodeTest);
+    defineReflectiveTests(SetElementTypeNotAssignableWithConstantTest);
   });
 }
 
 @reflectiveTest
 class SetElementTypeNotAssignableTest extends DriverResolutionTest {
-  test_explicitTypeArgs_const() async {
-    await assertErrorCodesInCode('''
-var v = const <String>{42};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_explicitTypeArgs_const_actualTypeMatch() async {
-    await assertNoErrorsInCode('''
-const dynamic x = null;
-var v = const <String>{x};
-''');
-  }
-
-  test_explicitTypeArgs_const_actualTypeMismatch() async {
-    await assertErrorCodesInCode('''
-const dynamic x = 42;
-var v = const <String>{x};
-''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
-  }
-
-  test_explicitTypeArgs_notConst() async {
-    await assertErrorCodesInCode('''
-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(
         '''
@@ -149,6 +98,32 @@
             : [CompileTimeErrorCode.NON_CONSTANT_SET_ELEMENT]);
   }
 
+  test_explicitTypeArgs_const() async {
+    await assertErrorCodesInCode('''
+var v = const <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_const_actualTypeMatch() async {
+    await assertNoErrorsInCode('''
+const dynamic x = null;
+var v = const <String>{x};
+''');
+  }
+
+  test_explicitTypeArgs_const_actualTypeMismatch() async {
+    await assertErrorCodesInCode('''
+const dynamic x = 42;
+var v = const <String>{x};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
+  test_explicitTypeArgs_notConst() async {
+    await assertErrorCodesInCode('''
+var v = <String>{42};
+''', [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+  }
+
   test_nonConst_ifElement_thenElseFalse_intDynamic() async {
     await assertNoErrorsInCode('''
 const dynamic a = 'a';
@@ -191,3 +166,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..5a11626 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -22,12 +22,19 @@
     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 'final_not_initialized_test.dart' as final_not_initialized;
+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 +43,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 +65,13 @@
 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_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 +92,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;
@@ -162,12 +176,16 @@
     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();
+    final_not_initialized.main();
+    implicit_this_reference_in_initializer.main();
     import_deferred_library_with_load_function.main();
     invalid_assignment.main();
     invalid_cast_new_expr.main();
@@ -175,6 +193,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 +206,11 @@
     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_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 +225,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();
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..2a28469 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 {
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..5ee8a4e 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
@@ -177,10 +177,7 @@
 ''');
   }
 
-  @failingTest
   test_invoke_nullable() async {
-    // test is failing because nullable function invocations aren't being
-    // resolved correctly
     await assertErrorCodesInCode(r'''
 m() {
   Function()? x;
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
index e2ace47b..3713aef 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,50 +10,11 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(UndefinedGetterTest);
-    defineReflectiveTests(UndefinedGetterWithControlFlowCollectionsTest);
   });
 }
 
 @reflectiveTest
 class UndefinedGetterTest extends DriverResolutionTest {
-  test_ifStatement_notPromoted() async {
-    await assertErrorCodesInCode('''
-f(int x) {
-  if (x is String) {
-    x.length;
-  }
-}
-''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
-  test_ifStatement_promoted() async {
-    await assertNoErrorsInCode('''
-f(Object x) {
-  if (x is String) {
-    x.length;
-  }
-}
-''');
-  }
-
-  test_promotedTypeParameter_regress35305() async {
-    await assertErrorCodesInCode(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) {
@@ -103,4 +62,34 @@
 }
 ''');
   }
+
+  test_ifStatement_notPromoted() async {
+    await assertErrorCodesInCode('''
+f(int x) {
+  if (x is String) {
+    x.length;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+  }
+
+  test_ifStatement_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  if (x is String) {
+    x.length;
+  }
+}
+''');
+  }
+
+  test_promotedTypeParameter_regress35305() async {
+    await assertErrorCodesInCode(r'''
+void f<X extends num, Y extends X>(Y y) {
+  if (y is int) {
+    y.isEven;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER]);
+  }
 }
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_identifier_test.dart
index 7b44210..3a8e91f 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,27 @@
 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 assertErrorCodesInCode('''
+f() {
+  return [for (int x in []) null, x];
+}
+''', [StaticWarningCode.UNDEFINED_IDENTIFIER]);
+  }
+
   test_forStatement_inBody() async {
     await assertNoErrorsInCode('''
 f() {
@@ -37,27 +50,3 @@
 ''', [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]);
-  }
-}
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/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/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/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/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index dbf23a4..6834f37 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -855,6 +855,86 @@
     ]);
   }
 
+  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_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');
 
@@ -2816,6 +2932,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..731f012 100644
--- a/pkg/analyzer/test/src/summary/element_text.dart
+++ b/pkg/analyzer/test/src/summary/element_text.dart
@@ -311,6 +311,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 +354,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);
@@ -705,7 +727,7 @@
     String defaultValueSeparator;
     Expression defaultValue;
     String closeString;
-    if (e.isNotOptional) {
+    if (e.isRequiredPositional) {
       closeString = '';
     } else if (e.isOptionalPositional) {
       buffer.write('[');
@@ -726,12 +748,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 +758,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 +892,7 @@
       writeMetadata(e, '', '\n');
     }
 
+    writeIf(e.isLate, 'late ');
     writeIf(e.isFinal, 'final ');
     writeIf(e.isConst, 'const ');
     writeType2(type);
@@ -904,6 +923,27 @@
       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);
     }
@@ -915,12 +955,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 +988,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 +1056,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/resynthesize_ast2_test.dart b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
index 7ec7d23..12b725e 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_ast2_test.dart
@@ -41,7 +41,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);
@@ -112,18 +112,6 @@
 
   @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 +124,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 +137,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 +163,7 @@
     }
 
     var text = _readSafely(source.fullName);
-    var unit = parseText(text, experimentStatus: experimentStatus);
+    var unit = parseText(text, featureSet);
 
     var units = <LinkInputUnit>[];
     _addLibraryUnits(source, unit, units);
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..fa7d3c1 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -5,11 +5,11 @@
 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/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/generated/source.dart';
 import 'package:analyzer/src/summary/idl.dart';
@@ -204,6 +204,9 @@
 /// applied to a class implementing [ResynthesizeTestStrategy], along with the
 /// mixin [ResynthesizeTestHelpers].
 mixin ResynthesizeTestCases implements ResynthesizeTestHelpers {
+  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 +605,7 @@
     checkElementText(library, r'''
 class C {
   dynamic x;
-  C((double) → dynamic this.x);
+  C(dynamic Function(double) this.x/*(double b)*/);
 }
 ''');
   }
@@ -617,7 +620,7 @@
     checkElementText(library, r'''
 class C {
   dynamic x;
-  C((double) → int this.x);
+  C(int Function(double) this.x/*(double b)*/);
 }
 ''');
   }
@@ -1000,6 +1003,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 +1023,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 +1042,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 +1062,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'''
@@ -1248,7 +1293,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 +1315,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 +1378,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 +1388,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 +1398,7 @@
 class C<T extends void Function()> {}
 ''');
     checkElementText(library, r'''
-class C<T extends () → void> {
+class C<T extends void Function()> {
 }
 ''');
   }
@@ -1360,16 +1414,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(...))> {
 }
 ''');
     }
@@ -1547,6 +1601,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 +1686,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 +1702,7 @@
 --------------------
 unit: a.dart
 
-final (int) → double f;
+final double Function(int) f;
 ''');
   }
 
@@ -2027,6 +2094,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 +2380,26 @@
         withConstElements: false);
   }
 
+  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> {
@@ -2888,14 +3077,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 +3097,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 +3132,6 @@
   }
 
   test_const_list_spread() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>[...<int>[1]];
 ''');
@@ -2968,7 +3154,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 +3176,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 +3190,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 +3227,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 +3253,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 +3414,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 +3432,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 +3450,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 +3463,7 @@
 const V = foo;
 ''');
     checkElementText(library, r'''
-const () → dynamic V =
+const dynamic Function() V =
         foo/*location: test.dart;foo*/;
 dynamic foo() {}
 ''');
@@ -3294,7 +3475,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 +3491,7 @@
 ''');
     checkElementText(library, r'''
 import 'a.dart';
-const () → dynamic V =
+const dynamic Function() V =
         foo/*location: a.dart;foo*/;
 ''');
   }
@@ -3325,7 +3506,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 +3610,7 @@
     checkElementText(library, r'''
 typedef F = dynamic Function();
 class C {
-  final List<() → dynamic> f;
+  final List<dynamic Function()> f;
 }
 ''');
   }
@@ -3538,7 +3719,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 +3732,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 +3767,6 @@
   }
 
   test_const_set_spread() async {
-    experimentStatus = ExperimentStatus(spread_collections: true);
     var library = await checkLibrary('''
 const Object x = const <int>{...<int>{1}};
 ''');
@@ -3611,7 +3789,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 +4056,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 +4064,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 +4213,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 +4221,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 +4965,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 +5335,7 @@
 ''');
     checkElementText(library, r'''
 typedef F = dynamic Function(int p);
-dynamic main((int) → dynamic f) {}
+dynamic main(dynamic Function(int) f) {}
 ''');
   }
 
@@ -5793,21 +5970,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 +6033,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)*/) {}
 ''');
   }
 
@@ -5946,7 +6123,7 @@
 int Function(int a, String b) f() => null;
 ''');
     checkElementText(library, r'''
-(int, String) → int f() {}
+int Function(int, String) f() {}
 ''');
   }
 
@@ -5955,7 +6132,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 +6141,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 +6153,7 @@
 ''');
     checkElementText(library, r'''
 class C {
-  (int, String) → int m() {}
+  int Function(int, String) m() {}
 }
 ''');
   }
@@ -5986,7 +6163,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 +6172,7 @@
 int Function(int a, String b) v;
 ''');
     checkElementText(library, r'''
-(int, String) → int v;
+int Function(int, String) v;
 ''');
   }
 
@@ -6292,7 +6469,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 +6493,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 +6703,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,10 +6718,10 @@
     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;
 }
 ''');
   }
@@ -6584,9 +6752,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 +6768,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 +6795,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 +6805,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 +6820,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 +6831,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 +6840,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 +6925,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 +6965,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 +6984,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 +6995,7 @@
 ''');
     checkElementText(library, r'''
 import 'dart:async';
-(Future<int>) → Future<int> v;
+Future<int> Function(Future<int>) v;
 ''');
   }
 
@@ -6838,7 +7006,7 @@
 ''');
     checkElementText(library, r'''
 import 'dart:async';
-(Future<dynamic>) → Future<dynamic> v;
+Future<dynamic> Function(Future<dynamic>) v;
 ''');
   }
 
@@ -6850,7 +7018,7 @@
 ''');
     checkElementText(library, r'''
 class C {
-  () → int v;
+  int Function() v;
 }
 ''');
   }
@@ -6928,7 +7096,7 @@
     checkElementText(library, r'''
 import 'b.dart';
 class C {
-  (O) → O f() {}
+  O Function(O) f() {}
 }
 ''');
   }
@@ -6940,7 +7108,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 +7926,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 +7935,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 +8036,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 +8077,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 +8176,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 +8191,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 +8208,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;
 ''');
   }
@@ -8053,7 +8300,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 +8358,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 {}
@@ -8271,7 +8530,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 +8557,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();
 ''');
   }
 
@@ -8442,7 +8701,7 @@
     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 +8710,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 +8719,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 +8728,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 +8969,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final (<bottom>) → int v;
+final int Function(<bottom>) v;
 bool f() {}
 ''');
   }
@@ -8735,7 +8994,7 @@
 ''');
     checkElementText(library, r'''
 class C<T, U> {
-  (T, U) → int v;
+  int Function(T, U) v;
 }
 bool f() {}
 ''');
@@ -8758,7 +9017,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final () → int v;
+final int Function() v;
 bool f() {}
 ''');
   }
@@ -8769,7 +9028,7 @@
 bool f() => true;
 ''');
     checkElementText(library, r'''
-final (int, String) → int v;
+final int Function(int, String) v;
 bool f() {}
 ''');
   }
@@ -8824,7 +9083,7 @@
 ''');
     checkElementText(library, '''
 import 'a.dart' deferred as a;
-() → Future<dynamic> x;
+Future<dynamic> Function() x;
 ''');
   }
 
@@ -8833,7 +9092,7 @@
 var x = (int f(String x)) => 0;
 ''');
     checkElementText(library, '''
-((String) → int) → int x;
+int Function(int Function(String)) x;
 ''');
   }
 
@@ -8842,7 +9101,7 @@
 var x = (int Function(String) f) => 0;
 ''');
     checkElementText(library, '''
-((String) → int) → int x;
+int Function(int Function(String)) x;
 ''');
   }
 
@@ -8879,7 +9138,7 @@
 var x = (t) => (u) => t + u;
 ''');
     checkElementText(library, '''
-(dynamic) → (dynamic) → dynamic x;
+dynamic Function(dynamic) Function(dynamic) x;
 ''');
   }
 
@@ -8888,7 +9147,7 @@
 var x = (int t) => (int u) => t + u;
 ''');
     checkElementText(library, '''
-(int) → (int) → int x;
+int Function(int) Function(int) x;
 ''');
   }
 
@@ -8897,7 +9156,7 @@
 var x = ([y: 0]) => y;
 ''');
     checkElementText(library, '''
-([dynamic]) → dynamic x;
+dynamic Function([dynamic]) x;
 ''');
   }
 
@@ -8972,7 +9231,7 @@
 }
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -8985,7 +9244,7 @@
 part 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 --------------------
 unit: a.dart
 
@@ -9022,7 +9281,7 @@
 
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9052,7 +9311,7 @@
 
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9077,7 +9336,7 @@
 }
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9128,7 +9387,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9140,7 +9399,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9153,7 +9412,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9166,7 +9425,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9178,7 +9437,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9190,7 +9449,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9214,7 +9473,7 @@
 import 'b.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9225,7 +9484,7 @@
 import 'a.dart';
 C c;
 E e;
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9233,7 +9492,7 @@
     var library = await checkLibrary('typedef F(); F f;');
     checkElementText(library, r'''
 typedef F = dynamic Function();
-() → dynamic f;
+dynamic Function() f;
 ''');
   }
 
@@ -9242,7 +9501,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 +9509,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 +9548,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 +9562,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 +9585,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 +9599,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 +9613,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 +9627,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 +9641,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 +9746,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 +10010,7 @@
   void f() {}
 }
 C<int> c;
-() → void v;
+void Function() v;
 ''');
   }
 
@@ -9810,6 +10034,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 +10064,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 +10175,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..14ddf55 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;
@@ -1751,6 +1675,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 +1929,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 +2761,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 +2777,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 +2795,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 +2807,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 +3011,6 @@
   }
 
   test_constExpr_makeTypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const <int>{11, 22, 33};');
     assertUnlinkedConst(
@@ -3047,7 +3031,6 @@
   }
 
   test_constExpr_makeTypedSet_dynamic() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const <dynamic>{11, 22, 33};');
     assertUnlinkedConst(
@@ -3065,7 +3048,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 +3076,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 +3167,6 @@
   }
 
   test_constExpr_makeUntypedSet() {
-    experimentStatus = ExperimentStatus(set_literals: true);
     UnlinkedVariable variable =
         serializeVariableText('const v = const {11, 22, 33};');
     assertUnlinkedConst(
@@ -3203,8 +3183,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 +3209,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 +3240,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 +3266,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 +4010,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 +4030,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 +4053,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 +4074,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 +4094,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 +4616,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 +4649,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 +4659,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 +4680,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 +4691,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 +4704,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 +4725,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 +6265,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 +6289,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 +6297,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 +6308,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 +6316,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 +6327,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 +7755,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 +7795,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 +7820,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 +7842,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 +7867,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 +7893,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 +7927,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 +7962,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 +8006,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 +8048,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 +8087,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 +8132,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 +8170,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 +8235,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 +8283,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 +8296,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 +8345,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 +8465,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 +8735,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 +8776,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 +8806,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 +8866,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) {} }');
@@ -10830,6 +10965,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 +11656,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 +11675,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 +11696,7 @@
   test_variable_non_static() {
     UnlinkedVariable variable =
         serializeClassText('class C { int i; }').fields[0];
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isFalse);
   }
 
@@ -11536,6 +11704,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 +11716,7 @@
   test_variable_static() {
     UnlinkedVariable variable =
         serializeClassText('class C { static int i; }').fields[0];
+    expect(variable.isLate, isFalse);
     expect(variable.isStatic, isTrue);
   }
 
@@ -11556,10 +11726,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 +11774,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 +11812,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 +11824,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..9c286c5 100644
--- a/pkg/analyzer/test/src/summary/test_strategies.dart
+++ b/pkg/analyzer/test/src/summary/test_strategies.dart
@@ -3,11 +3,11 @@
 // 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/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -35,21 +35,18 @@
 }
 
 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();
   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: featureSet);
   CompilationUnit unit = parser.parseCompilationUnit(token);
   unit.lineInfo = new LineInfo(scanner.lineStarts);
   return unit;
@@ -96,8 +93,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 +127,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,8 +176,7 @@
         .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);
@@ -229,8 +225,7 @@
         contents = '';
       }
 
-      CompilationUnit unit =
-          parseText(contents, experimentStatus: experimentStatus);
+      CompilationUnit unit = parseText(contents, featureSet);
 
       UnlinkedUnitBuilder unlinkedUnit = serializeAstUnlinked(unit);
       bundleAssembler.addUnlinkedUnit(source, unlinkedUnit);
@@ -311,8 +306,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 +526,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 +542,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 +567,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
index e79a3a7..1fc7fae 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_integration_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_integration_test.dart
@@ -16,7 +16,6 @@
 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';
 
@@ -60,22 +59,16 @@
     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 writer = AstBinaryWriter(linkingBundleContext);
     var unitLinkedNode = writer.writeNode(originalUnit);
 
     linkedNodeUnit = LinkedNodeUnitBuilder(
       node: unitLinkedNode,
-      tokens: tokensResult.tokens,
+      tokens: writer.tokensBuilder,
     );
   }
 
@@ -91,6 +84,8 @@
     null,
     0,
     null,
+    null,
+    false,
     linkedNodeUnit,
   );
 
@@ -118,11 +113,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_binary_writer_test.dart b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
index e23f4c1..b195dca 100644
--- a/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
+++ b/pkg/analyzer/test/src/summary2/ast_binary_writer_test.dart
@@ -12,7 +12,6 @@
 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';
 
@@ -30,9 +29,7 @@
   @override
   AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
     ..enabledExperiments = [
-      EnableString.control_flow_collections,
       EnableString.non_nullable,
-      EnableString.spread_collections,
     ];
 
   test_classTypeAlias() async {
@@ -128,17 +125,11 @@
     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 writer = AstBinaryWriter(linkingBundleContext);
     var builder = writer.writeNode(originalUnit);
 
     var bundleContext = LinkedBundleContext(
@@ -152,9 +143,11 @@
       null,
       0,
       null,
+      null,
+      false,
       LinkedNodeUnitBuilder(
         node: builder,
-        tokens: tokensResult.tokens,
+        tokens: writer.tokensBuilder,
       ),
     );
 
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/task/options_test.dart b/pkg/analyzer/test/src/task/options_test.dart
index 11182d9..d881108 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,9 @@
         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');
       }
 
       // 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/inferred_type_test.dart b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
index 4a036db..d3502e5 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';
 
@@ -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');
+    } else {
+      expect(v.initializer.type.toString(), '() → Null');
+    }
   }
 
   test_bottom_inClosure() 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 {
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..223ca20 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -12,6 +12,8 @@
 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,85 @@
 }
 
 @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 =
+        path.separator + path.join('workspace', 'project', 'lib', 'file2.dart');
+    expect(package.contains(TestSource(file2Path)), isTrue);
+    var binPath =
+        path.separator + path.join('workspace', 'project', 'bin', 'bin.dart');
+    expect(package.contains(TestSource(binPath)), isTrue);
+    var testPath =
+        path.separator + path.join('workspace', 'project', 'test', 'test.dart');
+    expect(package.contains(TestSource(testPath)), isTrue);
+  }
+
+  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_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 +564,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/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/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/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..ab4e74f 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 {
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..d9e764c 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
@@ -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 &&
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/optype.dart
index 93c1024..6e035ce 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';
@@ -622,6 +621,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) {
@@ -688,22 +703,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 +735,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^)
@@ -970,6 +982,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/completion/optype_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/optype_test.dart
index f4c2eb8..caf7f39 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);
   }
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/compiler/lib/src/backend_strategy.dart b/pkg/compiler/lib/src/backend_strategy.dart
index c5cfe60..cb3b545 100644
--- a/pkg/compiler/lib/src/backend_strategy.dart
+++ b/pkg/compiler/lib/src/backend_strategy.dart
@@ -40,10 +40,10 @@
 
   /// Creates the [WorkItemBuilder] used by the codegen enqueuer.
   WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults);
+      GlobalTypeInferenceResults globalInferenceResults, CodegenInputs codegen);
 
   /// Creates the [SsaBuilder] used for the element model.
-  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
+  SsaBuilder createSsaBuilder(CompilerTask task, CodegenInputs codegen,
       SourceInformationStrategy sourceInformationStrategy);
 
   /// Returns the [SourceInformationStrategy] use for the element model.
diff --git a/pkg/compiler/lib/src/common/codegen.dart b/pkg/compiler/lib/src/common/codegen.dart
index ec92751..b2dedea 100644
--- a/pkg/compiler/lib/src/common/codegen.dart
+++ b/pkg/compiler/lib/src/common/codegen.dart
@@ -7,6 +7,7 @@
 import '../common_elements.dart';
 import '../elements/entities.dart';
 import '../elements/types.dart' show DartType, InterfaceType;
+import '../native/behavior.dart';
 import '../universe/feature.dart';
 import '../universe/use.dart' show ConstantUse, DynamicUse, StaticUse, TypeUse;
 import '../universe/world_impact.dart'
@@ -34,6 +35,10 @@
 
   Iterable<GenericInstantiation> get genericInstantiations =>
       const <GenericInstantiation>[];
+
+  Iterable<NativeBehavior> get nativeBehaviors => const [];
+
+  Iterable<FunctionEntity> get nativeMethods => const [];
 }
 
 class _CodegenImpact extends WorldImpactBuilderImpl implements CodegenImpact {
@@ -43,6 +48,8 @@
   bool _usesInterceptor = false;
   EnumSet<AsyncMarker> _asyncMarkers;
   Set<GenericInstantiation> _genericInstantiations;
+  List<NativeBehavior> _nativeBehaviors;
+  Set<FunctionEntity> _nativeMethods;
 
   _CodegenImpact();
 
@@ -117,6 +124,26 @@
   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 [];
+  }
 }
 
 // TODO(johnniwinther): Split this class into interface and implementation.
@@ -187,6 +214,14 @@
   void registerGenericInstantiation(GenericInstantiation instantiation) {
     worldImpact.registerGenericInstantiation(instantiation);
   }
+
+  void registerNativeBehavior(NativeBehavior nativeBehavior) {
+    worldImpact.registerNativeBehavior(nativeBehavior);
+  }
+
+  void registerNativeMethod(FunctionEntity function) {
+    worldImpact.registerNativeMethod(function);
+  }
 }
 
 /// [WorkItem] used exclusively by the [CodegenEnqueuer].
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..a2c1f14 100644
--- a/pkg/compiler/lib/src/compiler.dart
+++ b/pkg/compiler/lib/src/compiler.dart
@@ -15,7 +15,6 @@
 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 +31,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 +85,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 +103,6 @@
 
   GenericTask selfTask;
 
-  /// The constant environment for the frontend interpretation of compile-time
-  /// constants.
-  ConstantEnvironment constants;
-
   EnqueueTask enqueuer;
   DeferredLoadTask deferredLoadTask;
   DumpInfoTask dumpInfoTask;
@@ -176,7 +165,6 @@
           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.
@@ -210,6 +198,8 @@
     return _codegenWorldBuilder;
   }
 
+  CodegenWorld codegenWorldForTesting;
+
   bool get disableTypeInference =>
       options.disableTypeInference || compilationFailed;
 
@@ -248,7 +238,7 @@
       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;
@@ -342,13 +332,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);
@@ -379,21 +363,27 @@
     if (options.showInternalProgress) reporter.log('Compiling...');
     phase = PHASE_COMPILING;
 
-    Enqueuer codegenEnqueuer =
-        startCodegen(closedWorld, globalInferenceResults);
+    CodegenInputs codegen = backend.onCodegenStart(closedWorld);
+    Enqueuer codegenEnqueuer = enqueuer.createCodegenEnqueuer(
+        closedWorld, globalInferenceResults, codegen);
+    _codegenWorldBuilder = codegenEnqueuer.worldBuilder;
+
     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;
+    }
+    int programSize = backend.assembleProgram(closedWorld,
+        globalInferenceResults.inferredData, codegen, codegenWorld);
 
     if (options.dumpInfo) {
       dumpInfoTask.reportSize(programSize);
       dumpInfoTask.dumpInfo(closedWorld, globalInferenceResults);
     }
 
-    backend.onCodegenEnd();
+    backend.onCodegenEnd(codegen);
 
     checkQueue(codegenEnqueuer);
   }
@@ -431,16 +421,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 +519,6 @@
     if (markCompilationAsFailed(message, kind)) {
       compilationFailed = true;
     }
-    registerCompileTimeError(currentElement, message);
   }
 
   /// Helper for determining whether the current element is declared within
@@ -604,27 +583,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 +596,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 +711,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/dart2js.dart b/pkg/compiler/lib/src/dart2js.dart
index c829eaa..ebdc6a0 100644
--- a/pkg/compiler/lib/src/dart2js.dart
+++ b/pkg/compiler/lib/src/dart2js.dart
@@ -414,7 +414,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),
diff --git a/pkg/compiler/lib/src/deferred_load.dart b/pkg/compiler/lib/src/deferred_load.dart
index a412c65..dd23b37 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
diff --git a/pkg/compiler/lib/src/dump_info.dart b/pkg/compiler/lib/src/dump_info.dart
index 35be4dd..eec68ab 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);
diff --git a/pkg/compiler/lib/src/enqueue.dart b/pkg/compiler/lib/src/enqueue.dart
index ef66b6e..5439e6e 100644
--- a/pkg/compiler/lib/src/enqueue.dart
+++ b/pkg/compiler/lib/src/enqueue.dart
@@ -16,6 +16,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 +65,12 @@
           ..onEmptyForTesting = compiler.onResolutionQueueEmptyForTesting;
   }
 
-  Enqueuer createCodegenEnqueuer(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+  Enqueuer createCodegenEnqueuer(
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen) {
     Enqueuer enqueuer = compiler.backend.createCodegenEnqueuer(
-        this, compiler, closedWorld, globalInferenceResults)
+        this, compiler, closedWorld, globalInferenceResults, codegen)
       ..onEmptyForTesting = compiler.onCodegenQueueEmptyForTesting;
     if (retainDataForTesting) {
       codegenEnqueuerForTesting = enqueuer;
@@ -207,7 +210,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 +286,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 +310,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 +346,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 +364,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/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/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/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 7aee79e..63eefbc 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;
   }
@@ -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,6 +1092,9 @@
 
   @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>();
@@ -1079,6 +1103,7 @@
     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,7 +1339,8 @@
   @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>();
     visitSignature(node.function);
@@ -1349,8 +1401,11 @@
   @override
   Null visitField(ir.Field node) {
     thisType = new ThisInterfaceType.from(node.enclosingClass?.thisType);
+    _currentVariables = new Set<ir.VariableDeclaration>();
     visitNode(node.initializer);
     handleField(node);
+    _invalidatedVariables.removeAll(_currentVariables);
+    _currentVariables = null;
     thisType = null;
   }
 
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_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index 6f44b97..dc1a2b4 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -6,37 +6,29 @@
 
 import '../common.dart';
 import '../common/backend_api.dart' show ImpactTransformer;
-import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
+import '../common/codegen.dart' show CodegenWorkItem;
 import '../common/names.dart' show Uris;
 import '../common/tasks.dart' show CompilerTask;
-import '../common_elements.dart'
-    show CommonElements, ElementEnvironment, JElementEnvironment;
+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 '../js_emitter/js_emitter.dart' show CodeEmitterTask, Emitter;
 import '../kernel/dart2js_target.dart';
 import '../native/enqueue.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;
@@ -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,10 +52,13 @@
 import 'runtime_types.dart';
 
 abstract class FunctionCompiler {
-  void onCodegenStart();
+  void onCodegenStart(CodegenInputs codegen);
 
   /// Generates JavaScript code for `work.element`.
-  jsAst.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
+  jsAst.Fun compile(
+      CodegenWorkItem work,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults);
 
   Iterable get tasks;
@@ -310,7 +304,7 @@
 
   FunctionCompiler functionCompiler;
 
-  CodeEmitterTask emitter;
+  CodeEmitterTask emitterTask;
 
   /// The generated code as a js AST for compiled methods.
   final Map<MemberEntity, jsAst.Expression> generatedCode =
@@ -329,14 +323,12 @@
 
   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.
@@ -355,10 +347,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 +357,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 +408,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,14 +422,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,
@@ -463,21 +430,12 @@
     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) {
+  Namer determineNamer(JClosedWorld closedWorld) {
     return compiler.options.enableMinification
         ? compiler.options.useFrequencyNamer
-            ? new FrequencyBasedNamer(closedWorld, codegenWorldBuilder)
-            : new MinifyNamer(closedWorld, codegenWorldBuilder)
-        : new Namer(closedWorld, codegenWorldBuilder);
+            ? new FrequencyBasedNamer(closedWorld)
+            : new MinifyNamer(closedWorld)
+        : new Namer(closedWorld);
   }
 
   void validateInterceptorImplementsAllObjectMethods(
@@ -608,20 +566,13 @@
       CompilerTask task,
       Compiler compiler,
       JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen) {
     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,
@@ -629,8 +580,8 @@
             closedWorld.nativeData,
             closedWorld,
             compiler.abstractValueStrategy.createSelectorStrategy()),
-        compiler.backendStrategy
-            .createCodegenWorkItemBuilder(closedWorld, globalInferenceResults),
+        compiler.backendStrategy.createCodegenWorkItemBuilder(
+            closedWorld, globalInferenceResults, codegen),
         new CodegenEnqueuerListener(
             elementEnvironment,
             commonElements,
@@ -643,30 +594,20 @@
 
   Map<MemberEntity, WorldImpact> codegenImpactsForTesting;
 
-  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+  WorldImpact generateCode(
+      CodegenWorkItem work,
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen) {
     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();
-    }
     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);
+    jsAst.Fun function = functionCompiler.compile(
+        work, codegen, closedWorld, globalInferenceResults);
     if (function != null) {
       if (function.sourceInformation == null) {
         function = function.withSourceInformation(
@@ -698,30 +639,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 codegen, CodegenWorld codegenWorld) {
+    int programSize = emitterTask.assembleProgram(
+        namer, closedWorld, inferredData, codegen, 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,37 +658,44 @@
     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(
+  CodegenInputs onCodegenStart(JClosedWorld closedWorld) {
+    _namer = determineNamer(closedWorld);
+    OneShotInterceptorData oneShotInterceptorData = new OneShotInterceptorData(
         closedWorld.interceptorData, closedWorld.commonElements);
-    _namer = determineNamer(closedWorld, codegenWorldBuilder);
-    tracer = new Tracer(closedWorld, namer, compiler.outputProvider);
+    Tracer tracer = new Tracer(closedWorld, namer, compiler.outputProvider);
     _rtiEncoder = _namer.rtiEncoder = new RuntimeTypesEncoderImpl(
         namer,
         closedWorld.nativeData,
         closedWorld.elementEnvironment,
         closedWorld.commonElements,
         closedWorld.rtiNeed);
-    emitter.createEmitter(namer, closedWorld, codegenWorldBuilder, sorter);
+    _nativeCodegenEnqueuer = new NativeCodegenEnqueuer(
+        compiler.options,
+        closedWorld.elementEnvironment,
+        closedWorld.commonElements,
+        closedWorld.dartTypes,
+        emitterTask,
+        closedWorld.liveNativeClasses,
+        closedWorld.nativeData);
+    emitterTask.createEmitter(namer, closedWorld);
     // 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;
     }
 
     _codegenImpactTransformer = new CodegenImpactTransformer(
@@ -777,129 +709,20 @@
         nativeCodegenEnqueuer,
         namer,
         oneShotInterceptorData,
-        rtiChecksBuilder);
-    return const WorldImpact();
+        rtiChecksBuilder,
+        emitterTask.nativeEmitter);
+
+    CodegenInputs codegen = new CodegenImpl(emitterTask.emitter,
+        oneShotInterceptorData, rtiSubstitutions, rtiEncoder, namer, tracer);
+
+    functionCompiler.onCodegenStart(codegen);
+    return codegen;
   }
 
   /// 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.
@@ -976,3 +799,45 @@
     return _aliasedSuperMembers.contains(member);
   }
 }
+
+/// Interface for resources only used during code generation.
+abstract class CodegenInputs {
+  Emitter get emitter;
+  CheckedModeHelpers get checkedModeHelpers;
+  OneShotInterceptorData get oneShotInterceptorData;
+  RuntimeTypesSubstitutions get rtiSubstitutions;
+  RuntimeTypesEncoder get rtiEncoder;
+  // TODO(johnniwinther): Should be the modular part of the namer.
+  Namer get namer;
+  SuperMemberData get superMemberData;
+  Tracer get tracer;
+}
+
+class CodegenImpl implements CodegenInputs {
+  @override
+  final Emitter emitter;
+
+  @override
+  final CheckedModeHelpers checkedModeHelpers = new CheckedModeHelpers();
+
+  @override
+  final OneShotInterceptorData oneShotInterceptorData;
+
+  @override
+  final RuntimeTypesSubstitutions rtiSubstitutions;
+
+  @override
+  final RuntimeTypesEncoder rtiEncoder;
+
+  @override
+  final Namer namer;
+
+  @override
+  final SuperMemberData superMemberData = new SuperMemberData();
+
+  @override
+  final Tracer tracer;
+
+  CodegenImpl(this.emitter, this.oneShotInterceptorData, this.rtiSubstitutions,
+      this.rtiEncoder, this.namer, this.tracer);
+}
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/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..b596d65 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -11,9 +11,9 @@
 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';
@@ -24,7 +24,7 @@
 
 /// Generates the JavaScript expressions for constants.
 ///
-/// It uses a given [constantReferenceGenerator] to reference nested 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> {
@@ -35,29 +35,27 @@
 
   final CompilerOptions _options;
   final JCommonElements _commonElements;
-  final CodegenWorldBuilder _worldBuilder;
+  final JElementEnvironment _elementEnvironment;
   final RuntimeTypesNeed _rtiNeed;
   final RuntimeTypesEncoder _rtiEncoder;
   final JFieldAnalysis _fieldAnalysis;
-  final CodeEmitterTask _task;
-  final _ConstantReferenceGenerator constantReferenceGenerator;
-  final _ConstantListGenerator makeConstantList;
+  final Emitter _emitter;
+  final _ConstantReferenceGenerator _constantReferenceGenerator;
+  final _ConstantListGenerator _makeConstantList;
 
-  /// The given [constantReferenceGenerator] function must, when invoked with a
+  /// 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._elementEnvironment,
       this._rtiNeed,
       this._rtiEncoder,
       this._fieldAnalysis,
-      this._task,
-      this.constantReferenceGenerator,
-      this.makeConstantList);
-
-  Emitter get _emitter => _task.emitter;
+      this._emitter,
+      this._constantReferenceGenerator,
+      this._makeConstantList);
 
   /// Constructs a literal expression that evaluates to the constant. Uses a
   /// canonical name unless the constant can be emitted multiple times (as for
@@ -176,10 +174,10 @@
   @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 +193,7 @@
     }
 
     List<jsAst.Expression> arguments = <jsAst.Expression>[
-      constantReferenceGenerator(constant.entries),
+      _constantReferenceGenerator(constant.entries),
     ];
 
     if (_rtiNeed.classNeedsTypeArguments(classElement)) {
@@ -221,7 +219,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 +229,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 +246,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 +257,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,7 +318,7 @@
   @override
   jsAst.Expression visitInterceptor(InterceptorConstantValue constant, [_]) {
     ClassEntity interceptorClass = constant.cls;
-    return _task.interceptorPrototypeAccess(interceptorClass);
+    return _emitter.interceptorPrototypeAccess(interceptorClass);
   }
 
   @override
@@ -349,11 +347,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 +366,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 +410,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..7bb0830 100644
--- a/pkg/compiler/lib/src/js_backend/frequency_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/frequency_namer.dart
@@ -47,9 +47,7 @@
   jsAst.Name get staticsPropertyName =>
       _staticsPropertyName ??= getFreshName(instanceScope, 'static');
 
-  FrequencyBasedNamer(
-      JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
-      : super(closedWorld, codegenWorldBuilder) {
+  FrequencyBasedNamer(JClosedWorld closedWorld) : super(closedWorld) {
     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..d4276ff 100644
--- a/pkg/compiler/lib/src/js_backend/impact_transformer.dart
+++ b/pkg/compiler/lib/src/js_backend/impact_transformer.dart
@@ -15,6 +15,7 @@
 import '../constants/expressions.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';
@@ -88,12 +89,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;
@@ -357,6 +352,7 @@
   final Namer _namer;
   final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesChecksBuilder _rtiChecksBuilder;
+  final NativeEmitter _nativeEmitter;
 
   CodegenImpactTransformer(
       this._options,
@@ -369,7 +365,8 @@
       this._nativeCodegenEnqueuer,
       this._namer,
       this._oneShotInterceptorData,
-      this._rtiChecksBuilder);
+      this._rtiChecksBuilder,
+      this._nativeEmitter);
 
   void onIsCheckForCodegen(DartType type, TransformedWorldImpact transformed) {
     if (type.isDynamic) return;
@@ -449,6 +446,15 @@
       _rtiChecksBuilder.registerGenericInstantiation(instantiation);
     }
 
+    for (NativeBehavior behavior in impact.nativeBehaviors) {
+      _nativeCodegenEnqueuer.registerNativeBehavior(
+          transformed, behavior, impact);
+    }
+
+    for (FunctionEntity function in impact.nativeMethods) {
+      _nativeEmitter.nativeMethods.add(function);
+    }
+
     // TODO(johnniwinther): Remove eager registration.
     return transformed;
   }
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..7ae3818 100644
--- a/pkg/compiler/lib/src/js_backend/minify_namer.dart
+++ b/pkg/compiler/lib/src/js_backend/minify_namer.dart
@@ -10,8 +10,7 @@
         _MinifiedFieldNamer,
         _MinifyConstructorBodyNamer,
         _MinifiedOneShotInterceptorNamer {
-  MinifyNamer(JClosedWorld closedWorld, CodegenWorldBuilder codegenWorldBuilder)
-      : super(closedWorld, codegenWorldBuilder) {
+  MinifyNamer(JClosedWorld closedWorld) : super(closedWorld) {
     reserveBackendNames();
     fieldRegistry = new _FieldNamingRegistry(this);
   }
@@ -392,7 +391,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));
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 0648b9c..c69a928 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -14,6 +14,7 @@
 import '../closure.dart';
 import '../common.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,10 +25,10 @@
 import '../elements/names.dart';
 import '../elements/types.dart';
 import '../js/js.dart' as jsAst;
+import '../js_backend/field_analysis.dart';
 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;
@@ -490,7 +491,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 {
@@ -596,13 +596,14 @@
   /// key into maps.
   final Map<LibraryEntity, String> _libraryKeys = HashMap();
 
-  Namer(this._closedWorld, this._codegenWorldBuilder) {
+  Namer(this._closedWorld) {
     _literalAsyncPrefix = new StringBackedName(asyncPrefix);
     _literalGetterPrefix = new StringBackedName(getterPrefix);
     _literalSetterPrefix = new StringBackedName(setterPrefix);
   }
 
-  ElementEnvironment get elementEnvironment => _closedWorld.elementEnvironment;
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
 
   CommonElements get _commonElements => _closedWorld.commonElements;
 
@@ -731,11 +732,10 @@
   String constantLongName(ConstantValue constant) {
     String longName = _constantLongNames[constant];
     if (longName == null) {
-      _constantHasher ??=
-          new ConstantCanonicalHasher(rtiEncoder, _codegenWorldBuilder);
-      longName = new ConstantNamingVisitor(
-              rtiEncoder, _codegenWorldBuilder, _constantHasher)
-          .getName(constant);
+      _constantHasher ??= new ConstantCanonicalHasher(rtiEncoder, _closedWorld);
+      longName =
+          new ConstantNamingVisitor(rtiEncoder, _closedWorld, _constantHasher)
+              .getName(constant);
       _constantLongNames[constant] = longName;
     }
     return longName;
@@ -1020,10 +1020,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 +1033,7 @@
           }
         }
       }
-      lookupClass = elementEnvironment.getSuperClass(lookupClass);
+      lookupClass = _elementEnvironment.getSuperClass(lookupClass);
     }
     return false;
   }
@@ -1843,16 +1843,20 @@
   static const MAX_EXTRA_LENGTH = 30;
   static const DEFAULT_TAG_LENGTH = 3;
 
-  final RuntimeTypesEncoder rtiEncoder;
-  final CodegenWorldBuilder codegenWorldBuilder;
-  final ConstantCanonicalHasher hasher;
+  final RuntimeTypesEncoder _rtiEncoder;
+  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._rtiEncoder, this._closedWorld, this._hasher);
+
+  JElementEnvironment get _elementEnvironment =>
+      _closedWorld.elementEnvironment;
+  JFieldAnalysis get _fieldAnalysis => _closedWorld.fieldAnalysis;
 
   String getName(ConstantValue constant) {
     _visit(constant);
@@ -1863,7 +1867,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 +2025,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 +2047,7 @@
     }
     if (name == null) {
       // e.g. DartType 'dynamic' has no element.
-      name = rtiEncoder.getTypeRepresentationForTypeConstant(type);
+      name = _rtiEncoder.getTypeRepresentationForTypeConstant(type);
     }
     addIdentifier(name);
     add(getHashTag(constant, 3));
@@ -2090,19 +2094,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 RuntimeTypesEncoder _rtiEncoder;
+  final JClosedWorld _closedWorld;
+  final Map<ConstantValue, int> _hashes = {};
 
-  ConstantCanonicalHasher(this.rtiEncoder, this.codegenWorldBuilder);
+  ConstantCanonicalHasher(this._rtiEncoder, 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 +2174,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 +2186,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 = _rtiEncoder.getTypeRepresentationForTypeConstant(type);
     return _hashString(4, name);
   }
 
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..87c984e 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -24,10 +24,8 @@
 import '../universe/class_hierarchy.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 +166,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 +186,7 @@
 
   @override
   RuntimeTypesNeed computeRuntimeTypesNeed(
-      ResolutionWorldBuilder resolutionWorldBuilder,
-      KClosedWorld closedWorld,
-      CompilerOptions options) {
+      KClosedWorld closedWorld, CompilerOptions options) {
     return const TrivialRuntimeTypesNeed();
   }
 }
@@ -237,7 +231,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 +255,7 @@
 
   @override
   RuntimeTypesChecks computeRequiredChecks(
-      CodegenWorldBuilder codegenWorldBuilder, CompilerOptions options) {
+      CodegenWorld codegenWorld, CompilerOptions options) {
     rtiChecksBuilderClosed = true;
 
     Map<ClassEntity, ClassUse> classUseMap = <ClassEntity, ClassUse>{};
@@ -855,18 +849,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 +971,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 +979,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 +1003,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 +1020,8 @@
         if (typeDeclaration is ClassEntity) {
           node.addDependency(_getClassNode(typeDeclaration));
         } else {
-          node.addDependency(_getMethodNode(
-              elementEnvironment, worldBuilder, typeDeclaration));
+          node.addDependency(
+              _getMethodNode(elementEnvironment, world, typeDeclaration));
         }
       });
     }
@@ -1085,34 +1079,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 +1111,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 +1136,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 +1170,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 +1229,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 +1495,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>();
@@ -1564,9 +1545,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 +1638,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 +1660,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 +1785,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 +1800,7 @@
         localFunctionsNeedingSignature.addAll(localFunctions);
       }
       for (FunctionEntity function
-          in resolutionWorldBuilder.closurizedMembersWithFreeTypeVariables) {
+          in closedWorld.closurizedMembersWithFreeTypeVariables) {
         methodsNeedingSignature.add(function);
         potentiallyNeedTypeArguments(function.enclosingClass);
       }
@@ -1980,12 +1961,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 +2049,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 +2088,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 +2105,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 +2154,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 +2165,7 @@
                 bound, TypeVisitorState.covariantTypeArgument);
           }
         }
-      }
+      });
     }
 
     cachedRequiredChecks = _computeChecks(classUseMap);
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..9e49e92 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;
@@ -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..74afc24 100644
--- a/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
+++ b/pkg/compiler/lib/src/js_emitter/code_emitter_task.dart
@@ -13,7 +13,8 @@
 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/js_backend.dart'
+    show CodegenInputs, JavaScriptBackend, Namer;
 import '../js_backend/inferred_data.dart';
 import '../universe/codegen_world_builder.dart';
 import '../world.dart' show JClosedWorld;
@@ -24,7 +25,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 +34,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 +47,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 +67,79 @@
   @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, 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,
+          _backend.rtiEncoder,
+          _backend.sourceInformationStrategy,
+          this,
+          _generateSourceMap);
+      metadataCollector = new MetadataCollector(
+          _compiler.options,
+          _compiler.reporter,
+          _emitter,
+          _backend.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 codegen,
+      CodegenWorld codegenWorld) {
     return measure(() {
-      _finalizeRti();
+      _finalizeRti(codegen, 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,
+          codegen.superMemberData,
           typeTestRegistry.rtiChecks,
-          backend.rtiEncoder,
-          backend.oneShotInterceptorData,
-          backend.customElementsCodegenAnalysis,
-          backend.generatedCode,
+          codegen.rtiEncoder,
+          codegen.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, codegen, codegenWorld);
       // TODO(floitsch): we shouldn't need the `neededClasses` anymore.
       neededClasses = programBuilder.collector.neededClasses;
       return size;
@@ -204,21 +147,13 @@
   }
 }
 
-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);
+  int emitProgram(ProgramBuilder programBuilder, CodegenInputs codegen,
+      CodegenWorld codegenWorld);
 
   /// Returns the JS function that must be invoked to get the value of the
   /// lazily initialized static.
@@ -243,8 +178,10 @@
   jsAst.Expression constructorAccess(ClassEntity e);
 
   /// Returns the JS prototype of the given class [e].
-  jsAst.Expression prototypeAccess(
-      covariant ClassEntity e, bool hasBeenInstantiated);
+  jsAst.Expression prototypeAccess(ClassEntity e, {bool hasBeenInstantiated});
+
+  /// 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);
@@ -267,55 +204,3 @@
   /// 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/headers.dart b/pkg/compiler/lib/src/js_emitter/headers.dart
index 9af8ea1..adc0060 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, '
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..5905955 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.
   ///
@@ -138,9 +135,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 +145,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..eeecd6ff 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,37 @@
 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(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 +197,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)
@@ -422,8 +419,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..57ff772 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;
 
@@ -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..b2c2743 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;
@@ -127,8 +125,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 +154,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 +266,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 +290,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..cd297c8 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
@@ -22,8 +22,6 @@
     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,10 +62,9 @@
   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;
@@ -108,10 +105,9 @@
       this._elementEnvironment,
       this._commonElements,
       this._outputUnitData,
-      this._worldBuilder,
+      this._codegenWorld,
       this._nativeCodegenEnqueuer,
       this._backendUsage,
-      this._constantHandler,
       this._nativeData,
       this._rtiNeed,
       this._interceptorData,
@@ -135,10 +131,9 @@
             _commonElements,
             _elementEnvironment,
             _outputUnitData,
-            _worldBuilder,
+            _codegenWorld,
             _namer,
             _task.emitter,
-            _constantHandler,
             _nativeData,
             _interceptorData,
             _oneShotInterceptorData,
@@ -347,12 +342,12 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
         _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
     return stubGenerator.generateTypeToInterceptorMap();
   }
@@ -435,11 +430,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 +475,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 +490,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 +517,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 +551,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 +639,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 +658,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 +764,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 +787,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 +852,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 +862,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);
@@ -901,9 +900,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);
       }
     }
@@ -971,12 +969,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 +984,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);
   }
 
@@ -1022,12 +1016,12 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
         _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
 
     String holderName =
@@ -1107,7 +1101,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 +1112,12 @@
     InterceptorStubGenerator stubGenerator = new InterceptorStubGenerator(
         _options,
         _commonElements,
-        _task,
+        _task.emitter,
         _nativeCodegenEnqueuer,
         _namer,
         _oneShotInterceptorData,
         _customElementsCodegenAnalysis,
-        _worldBuilder,
+        _codegenWorld,
         _closedWorld);
 
     String holderName =
@@ -1148,8 +1142,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/startup_emitter/emitter.dart b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
index 75acab7..f595f07 100644
--- a/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
+++ b/pkg/compiler/lib/src/js_emitter/startup_emitter/emitter.dart
@@ -7,66 +7,114 @@
 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 '../../common/tasks.dart';
 import '../../constants/values.dart' show ConstantValue;
 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/js_backend.dart' show CodegenInputs, Namer;
+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;
 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;
-
-  EmitterFactory({this.generateSourceMap});
-
-  @override
-  bool get supportsReflection => false;
-
-  @override
-  Emitter createEmitter(CodeEmitterTask task, Namer namer,
-      JClosedWorld closedWorld, Sorter sorter) {
-    return new Emitter(task.compiler, namer, task.nativeEmitter, closedWorld,
-        sorter, task, generateSourceMap);
-  }
-}
-
-class Emitter extends emitterTask.EmitterBase {
-  final Compiler _compiler;
+class EmitterImpl implements Emitter {
+  final DiagnosticReporter _reporter;
   final JClosedWorld _closedWorld;
-  @override
+  final RuntimeTypesEncoder _rtiEncoder;
   final Namer namer;
-  final ModelEmitter _emitter;
-
-  JavaScriptBackend get _backend => _compiler.backend;
-
-  Emitter(
-      this._compiler,
-      this.namer,
-      NativeEmitter nativeEmitter,
-      this._closedWorld,
-      Sorter sorter,
-      CodeEmitterTask task,
-      bool shouldGenerateSourceMap)
-      : _emitter = new ModelEmitter(_compiler, namer, nativeEmitter,
-            _closedWorld, sorter, task, shouldGenerateSourceMap);
-
-  DiagnosticReporter get reporter => _compiler.reporter;
+  ModelEmitter _emitter;
 
   @override
-  int emitProgram(ProgramBuilder programBuilder) {
+  Program programForTesting;
+
+  EmitterImpl(
+      CompilerOptions options,
+      this._reporter,
+      CompilerOutput outputProvider,
+      DumpInfoTask dumpInfoTask,
+      this.namer,
+      this._closedWorld,
+      this._rtiEncoder,
+      SourceInformationStrategy sourceInformationStrategy,
+      CompilerTask task,
+      bool shouldGenerateSourceMap) {
+    _emitter = new ModelEmitter(
+        options,
+        _reporter,
+        outputProvider,
+        dumpInfoTask,
+        namer,
+        _closedWorld,
+        task,
+        this,
+        sourceInformationStrategy,
+        _rtiEncoder,
+        shouldGenerateSourceMap);
+  }
+
+  @override
+  int emitProgram(ProgramBuilder programBuilder, CodegenInputs codegen,
+      CodegenWorld codegenWorld) {
     Program program = programBuilder.buildProgram();
     if (retainDataForTesting) {
       programForTesting = program;
     }
-    return _emitter.emitProgram(program);
+    return _emitter.emitProgram(program, codegen, codegenWorld);
+  }
+
+  js.PropertyAccess globalPropertyAccessForMember(MemberEntity element) {
+    js.Name name = namer.globalPropertyNameForMember(element);
+    js.PropertyAccess pa = new js.PropertyAccess(
+        new js.VariableUse(namer.globalObjectForMember(element)), name);
+    return pa;
+  }
+
+  js.PropertyAccess globalPropertyAccessForClass(ClassEntity element) {
+    js.Name name = namer.globalPropertyNameForClass(element);
+    js.PropertyAccess pa = new js.PropertyAccess(
+        new js.VariableUse(namer.globalObjectForClass(element)), name);
+    return pa;
+  }
+
+  js.PropertyAccess globalPropertyAccessForType(Entity element) {
+    js.Name name = namer.globalPropertyNameForType(element);
+    js.PropertyAccess pa = new js.PropertyAccess(
+        new js.VariableUse(namer.globalObjectForType(element)), name);
+    return pa;
+  }
+
+  @override
+  js.PropertyAccess staticFieldAccess(FieldEntity element) {
+    return globalPropertyAccessForMember(element);
+  }
+
+  @override
+  js.PropertyAccess staticFunctionAccess(FunctionEntity element) {
+    return globalPropertyAccessForMember(element);
+  }
+
+  @override
+  js.PropertyAccess constructorAccess(ClassEntity element) {
+    return globalPropertyAccessForClass(element);
+  }
+
+  @override
+  js.Expression interceptorClassAccess(ClassEntity element) {
+    return globalPropertyAccessForClass(element);
+  }
+
+  @override
+  js.Expression typeAccess(Entity element) {
+    return globalPropertyAccessForType(element);
   }
 
   @override
@@ -109,14 +157,19 @@
   }
 
   @override
-  js.PropertyAccess prototypeAccess(
-      ClassEntity element, bool hasBeenInstantiated) {
+  js.PropertyAccess prototypeAccess(ClassEntity element,
+      {bool hasBeenInstantiated}) {
     js.Expression constructor =
         hasBeenInstantiated ? constructorAccess(element) : typeAccess(element);
     return js.js('#.prototype', constructor);
   }
 
   @override
+  js.Expression interceptorPrototypeAccess(ClassEntity e) {
+    return js.js('#.prototype', interceptorClassAccess(e));
+  }
+
+  @override
   js.Template templateForBuiltin(JsBuiltin builtin) {
     switch (builtin) {
       case JsBuiltin.dartObjectConstructor:
@@ -128,19 +181,19 @@
         return js.js.expressionTemplateFor('#.substring($isPrefixLength)');
 
       case JsBuiltin.isFunctionType:
-        return _backend.rtiEncoder.templateForIsFunctionType;
+        return _rtiEncoder.templateForIsFunctionType;
 
       case JsBuiltin.isFutureOrType:
-        return _backend.rtiEncoder.templateForIsFutureOrType;
+        return _rtiEncoder.templateForIsFutureOrType;
 
       case JsBuiltin.isVoidType:
-        return _backend.rtiEncoder.templateForIsVoidType;
+        return _rtiEncoder.templateForIsVoidType;
 
       case JsBuiltin.isDynamicType:
-        return _backend.rtiEncoder.templateForIsDynamicType;
+        return _rtiEncoder.templateForIsDynamicType;
 
       case JsBuiltin.isJsInteropTypeArgument:
-        return _backend.rtiEncoder.templateForIsJsInteropTypeArgument;
+        return _rtiEncoder.templateForIsJsInteropTypeArgument;
 
       case JsBuiltin.rawRtiToJsConstructorName:
         return js.js.expressionTemplateFor("#.name");
@@ -167,7 +220,7 @@
         return js.js.expressionTemplateFor("$typesAccess[#]");
 
       default:
-        reporter.internalError(
+        _reporter.internalError(
             NO_LOCATION_SPANNABLE, "Unhandled Builtin: $builtin");
         return null;
     }
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..7781d54 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 ConstantEmitter _constantEmitter;
+  final ModelEmitter _modelEmitter;
   final JClosedWorld _closedWorld;
+  final CodegenInputs _codegen;
+  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._constantEmitter,
+      this._modelEmitter,
+      this._closedWorld,
+      this._codegen,
+      this._codegenWorld);
 
   js.Expression generateEmbeddedGlobalAccess(String global) =>
-      modelEmitter.generateEmbeddedGlobalAccess(global);
+      _modelEmitter.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': _codegen.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.operatorIsPrefix),
+      'tearOffCode': new js.Block(buildTearOffCode(
+          _options, _codegen.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.callNameField),
+      'stubName': js.string(_namer.stubNameField),
+      'argumentCount': js.string(_namer.requiredParameterField),
+      'defaultArgumentValues': js.string(_namer.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;
@@ -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) {
@@ -1064,13 +1073,13 @@
 
       // Closures taking exactly one argument are common.
       properties.add(js.Property(
-          js.string(namer.callCatchAllName), js.quoteName(call1Name)));
+          js.string(_namer.callCatchAllName), js.quoteName(call1Name)));
       properties.add(
-          js.Property(js.string(namer.requiredParameterField), js.number(1)));
+          js.Property(js.string(_namer.requiredParameterField), js.number(1)));
 
       // Most closures have no optional arguments.
       properties.add(js.Property(
-          js.string(namer.defaultValuesField), new js.LiteralNull()));
+          js.string(_namer.defaultValuesField), new js.LiteralNull()));
     }
 
     return new js.ObjectInitializer(properties);
@@ -1083,11 +1092,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 +1115,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 +1140,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 +1189,12 @@
           js.Name applyName = method.applyIndex == 0
               ? method.name
               : method.parameterStubs[method.applyIndex - 1].name;
-          properties[js.string(namer.callCatchAllName)] =
+          properties[js.string(_namer.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.requiredParameterField)] =
               js.number(method.requiredParameterCount);
         }
 
@@ -1193,7 +1203,7 @@
         // 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.defaultValuesField)] = defaultValues;
         }
       }
     }
@@ -1578,9 +1588,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 +1633,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 +1809,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..f02e6a1 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,51 @@
 
 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 CodegenInputs, 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;
+  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,23 +85,31 @@
 
   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,
+      Emitter 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]);
@@ -135,7 +147,7 @@
 
     // 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.
@@ -144,8 +156,8 @@
 
   js.Expression generateStaticClosureAccess(FunctionEntity element) {
     return js.js('#.#()', [
-      namer.globalObjectForMember(element),
-      namer.staticClosureName(element)
+      _namer.globalObjectForMember(element),
+      _namer.staticClosureName(element)
     ]);
   }
 
@@ -158,19 +170,27 @@
     // 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, CodegenInputs codegen, 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,
+        _constantEmitter,
+        this,
+        _closedWorld,
+        codegen,
+        codegenWorld);
 
     var deferredLoadingState = new DeferredLoadingState();
     js.Statement mainCode =
@@ -211,14 +231,14 @@
     writeMainFragment(mainFragment, mainCode,
         isSplit: program.deferredFragments.isNotEmpty ||
             program.hasSoftDeferredClasses ||
-            compiler.options.experimentalTrackAllocations);
+            _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 +252,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 +292,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;
 
@@ -292,29 +312,29 @@
     ]);
 
     mainOutput.addBuffer(js.createCodeBuffer(
-        program, compiler.options, backend.sourceInformationStrategy,
-        monitor: compiler.dumpInfoTask));
+        program, _options, _sourceInformationStrategy,
+        monitor: _dumpInfoTask));
 
-    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 +350,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 +360,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;
@@ -362,8 +382,8 @@
     ]);
 
     output.addBuffer(js.createCodeBuffer(
-        program, compiler.options, backend.sourceInformationStrategy,
-        monitor: compiler.dumpInfoTask));
+        program, _options, _sourceInformationStrategy,
+        monitor: _dumpInfoTask));
 
     // 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 +394,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 +406,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 +438,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)
+    _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..bb595f5 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';
@@ -939,8 +940,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 +972,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 +1066,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..1c7f8f8 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -141,8 +141,7 @@
   LibraryEntity getLibrary(ir.Library node);
 
   /// Returns the [js.Template] for the `JsBuiltin` [constant] value.
-  js.Template getJsBuiltinTemplate(
-      ConstantValue constant, CodeEmitterTask emitter);
+  js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter);
 
   /// Returns a [Spannable] for a message pointing to the IR [node] in the
   /// context of [member].
@@ -209,9 +208,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..30418af 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -33,6 +33,7 @@
 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;
@@ -58,17 +59,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,8 +123,9 @@
   /// 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 = {};
 
@@ -159,7 +151,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 +169,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 +183,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 +195,7 @@
                   getDartType(data.node.type))));
       assert(newTypedef.typedefIndex == oldTypedef.typedefIndex);
     }
+
     for (int memberIndex = 0;
         memberIndex < _elementMap.members.length;
         memberIndex++) {
@@ -216,8 +211,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,
@@ -690,7 +736,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 +1144,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 +1169,7 @@
       case MemberKind.closureField:
       case MemberKind.signature:
       case MemberKind.generatorBody:
-        cachedStaticTypes = const {};
+        cachedStaticTypes = const StaticTypeCache();
         break;
     }
 
@@ -1464,40 +1510,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 +1525,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));
@@ -1759,7 +1673,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}) {
@@ -2196,12 +2111,11 @@
   }
 
   @override
-  js.Template getJsBuiltinTemplate(
-      ConstantValue constant, CodeEmitterTask emitter) {
+  js.Template getJsBuiltinTemplate(ConstantValue constant, Emitter emitter) {
     int index = extractEnumIndexFromConstantValue(
         constant, commonElements.jsBuiltinEnum);
     if (index == null) return null;
-    return emitter.builtinTemplateFor(JsBuiltin.values[index]);
+    return emitter.templateForBuiltin(JsBuiltin.values[index]);
   }
 }
 
@@ -2474,6 +2388,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.
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..ecda819 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -12,6 +12,7 @@
 import '../common/tasks.dart';
 import '../compiler.dart';
 import '../deferred_load.dart';
+import '../dump_info.dart';
 import '../elements/entities.dart';
 import '../enqueue.dart';
 import '../io/kernel_source_information.dart'
@@ -23,13 +24,17 @@
 import '../js/js_source_mapping.dart';
 import '../js_backend/backend.dart';
 import '../js_backend/inferred_data.dart';
+import '../js_backend/namer.dart';
 import '../js_backend/native_data.dart';
+import '../js_emitter/code_emitter_task.dart';
 import '../kernel/kernel_strategy.dart';
 import '../native/behavior.dart';
+import '../options.dart';
 import '../ssa/builder_kernel.dart';
 import '../ssa/nodes.dart';
 import '../ssa/ssa.dart';
 import '../ssa/types.dart';
+import '../tracer.dart';
 import '../universe/codegen_world_builder.dart';
 import '../universe/selector.dart';
 import '../universe/world_builder.dart';
@@ -92,29 +97,37 @@
   }
 
   @override
-  SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
+  SsaBuilder createSsaBuilder(CompilerTask task, CodegenInputs codegen,
       SourceInformationStrategy sourceInformationStrategy) {
     return new KernelSsaBuilder(
         task,
-        backend.compiler,
+        _compiler.options,
+        _compiler.reporter,
+        _compiler.dumpInfoTask,
         // ignore:deprecated_member_use_from_same_package
-        elementMap);
+        elementMap,
+        codegen.namer,
+        codegen.emitter,
+        codegen.tracer,
+        sourceInformationStrategy);
   }
 
   @override
-  WorkItemBuilder createCodegenWorkItemBuilder(JClosedWorld closedWorld,
-      GlobalTypeInferenceResults globalInferenceResults) {
+  WorkItemBuilder createCodegenWorkItemBuilder(
+      JClosedWorld closedWorld,
+      GlobalTypeInferenceResults globalInferenceResults,
+      CodegenInputs codegen) {
     return new KernelCodegenWorkItemBuilder(
-        _compiler.backend, closedWorld, globalInferenceResults);
+        _compiler.backend, closedWorld, globalInferenceResults, codegen);
   }
 
   @override
   CodegenWorldBuilder createCodegenWorldBuilder(
       NativeBasicData nativeBasicData,
-      covariant JsClosedWorld closedWorld,
+      JClosedWorld closedWorld,
       SelectorConstraintsStrategy selectorConstraintsStrategy) {
     return new CodegenWorldBuilderImpl(
-        closedWorld.elementMap, closedWorld, selectorConstraintsStrategy);
+        closedWorld, selectorConstraintsStrategy);
   }
 
   @override
@@ -133,15 +146,16 @@
   final JavaScriptBackend _backend;
   final JClosedWorld _closedWorld;
   final GlobalTypeInferenceResults _globalInferenceResults;
+  final CodegenInputs _codegen;
 
-  KernelCodegenWorkItemBuilder(
-      this._backend, this._closedWorld, this._globalInferenceResults);
+  KernelCodegenWorkItemBuilder(this._backend, this._closedWorld,
+      this._globalInferenceResults, this._codegen);
 
   @override
   CodegenWorkItem createWorkItem(MemberEntity entity) {
     if (entity.isAbstract) return null;
     return new KernelCodegenWorkItem(
-        _backend, _closedWorld, _globalInferenceResults, entity);
+        _backend, _closedWorld, _globalInferenceResults, _codegen, entity);
   }
 }
 
@@ -153,43 +167,66 @@
   @override
   final CodegenRegistry registry;
   final GlobalTypeInferenceResults _globalInferenceResults;
+  final CodegenInputs _codegen;
 
   KernelCodegenWorkItem(this._backend, this._closedWorld,
-      this._globalInferenceResults, this.element)
+      this._globalInferenceResults, this._codegen, this.element)
       : registry =
             new CodegenRegistry(_closedWorld.elementEnvironment, element);
 
   @override
   WorldImpact run() {
-    return _backend.codegen(this, _closedWorld, _globalInferenceResults);
+    return _backend.generateCode(
+        this, _closedWorld, _globalInferenceResults, _codegen);
   }
 }
 
 /// 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;
+  final Namer _namer;
+  final Emitter _emitter;
+  final Tracer _tracer;
+  final SourceInformationStrategy _sourceInformationStrategy;
+
+  // TODO(johnniwinther,sra): Inlining decisions should not be based on the
+  // order in which ssa graphs are built.
   FunctionInlineCache _inlineCache;
 
-  KernelSsaBuilder(this.task, this._compiler, this._elementMap);
+  KernelSsaBuilder(
+      this._task,
+      this._options,
+      this._reporter,
+      this._dumpInfoTask,
+      this._elementMap,
+      this._namer,
+      this._emitter,
+      this._tracer,
+      this._sourceInformationStrategy);
 
   @override
   HGraph build(CodegenWorkItem work, JClosedWorld closedWorld,
       GlobalTypeInferenceResults results) {
     _inlineCache ??= new FunctionInlineCache(closedWorld.annotationsData);
-    return task.measure(() {
+    return _task.measure(() {
       KernelSsaGraphBuilder builder = new KernelSsaGraphBuilder(
+          _options,
+          _reporter,
           work.element,
           _elementMap.getMemberThisType(work.element),
-          _compiler,
+          _dumpInfoTask,
           _elementMap,
           results,
           closedWorld,
-          _compiler.codegenWorldBuilder,
           work.registry,
-          _compiler.backend.emitter.nativeEmitter,
-          _compiler.backend.sourceInformationStrategy,
+          _namer,
+          _emitter,
+          _tracer,
+          _sourceInformationStrategy,
           _inlineCache);
       return builder.build();
     });
@@ -268,7 +305,7 @@
 
   @override
   AbstractValue inferredIndexType(ir.ForInStatement node) {
-    return AbstractValueFactory.inferredTypeForSelector(
+    return AbstractValueFactory.inferredResultTypeForSelector(
         new Selector.index(), typeOfIterator(node), _globalInferenceResults);
   }
 
@@ -285,8 +322,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..6ed9e82 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);
@@ -167,6 +171,9 @@
     OutputUnitData outputUnitData =
         new OutputUnitData.readFromDataSource(source);
 
+    Map<MemberEntity, MemberAccess> memberAccess =
+        source.readMemberMap(() => new MemberAccess.readFromDataSource(source));
+
     source.end(tag);
 
     return new JsClosedWorld(
@@ -189,7 +196,8 @@
         annotationsData,
         globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        memberAccess);
   }
 
   /// Serializes this [JsClosedWorld] to [sink].
@@ -217,6 +225,8 @@
     annotationsData.writeToDataSink(sink);
     closureDataLookup.writeToDataSink(sink);
     outputUnitData.writeToDataSink(sink);
+    sink.writeMemberMap(
+        memberAccess, (MemberAccess access) => access.writeToDataSink(sink));
     sink.end(tag);
   }
 
@@ -539,6 +549,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..1a9544f 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);
 
@@ -202,6 +203,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 +232,8 @@
         annotationsData,
         _globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        memberAccess);
   }
 
   BackendUsage _convertBackendUsage(
@@ -260,7 +267,8 @@
         runtimeTypeUses: runtimeTypeUses,
         isFunctionApplyUsed: backendUsage.isFunctionApplyUsed,
         isMirrorsUsed: backendUsage.isMirrorsUsed,
-        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed);
+        isNoSuchMethodUsed: backendUsage.isNoSuchMethodUsed,
+        isHtmlLoaded: backendUsage.isHtmlLoaded);
   }
 
   NativeBasicData _convertNativeBasicData(
@@ -487,7 +495,7 @@
         map.toBackendLibrary,
         convertClassMap,
         convertMemberMap,
-        (m) => convertMap<ConstantValue, OutputUnit>(
+        (m) => convertMap<ConstantValue, OutputUnit, OutputUnit>(
             m, map.toBackendConstant, (v) => v));
   }
 }
@@ -633,20 +641,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;
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 7a2b12a..bb8f069 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';
@@ -1389,14 +1390,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..6041116 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -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 ConstrainedDynamicUse(
+        Selectors.iterator, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        Selectors.current, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        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 ConstrainedDynamicUse(
+        Selectors.cancel, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        Selectors.current, receiverConstraint, const []));
+    impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
+        Selectors.moveNext, receiverConstraint, const []));
   }
 
   @override
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/options.dart b/pkg/compiler/lib/src/options.dart
index f91b15b..2e4ac4b 100644
--- a/pkg/compiler/lib/src/options.dart
+++ b/pkg/compiler/lib/src/options.dart
@@ -215,9 +215,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;
 
@@ -385,8 +382,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 =
@@ -464,9 +459,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;
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 7070b01..2f3ace7a 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -9,7 +9,6 @@
 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
@@ -25,13 +24,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';
+import '../js_backend/native_data.dart';
+import '../js_backend/runtime_types.dart';
+import '../js_emitter/code_emitter_task.dart';
 import '../js_model/locals.dart' show JumpVisitor;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../js_model/element_map.dart';
@@ -39,21 +44,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 +85,42 @@
       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 Emitter _emitter;
+  final Namer _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;
 
   /// A stack of [InterfaceType]s that have been seen during inlining of
   /// factory constructors.  These types are preserved in [HInvokeStatic]s and
@@ -100,29 +128,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 +153,44 @@
 
   StackFrame _currentFrame;
 
-  final FunctionInlineCache inlineCache;
+  final FunctionInlineCache _inlineCache;
 
   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._sourceInformationStrategy,
-      this.inlineCache)
-      : this.targetElement = _effectiveTargetElementFor(initialTargetElement),
-        _infoReporter = compiler.dumpInfoTask,
-        this.closureDataLookup = closedWorld.closureDataLookup {
+      this._inlineCache)
+      : 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 +199,203 @@
   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;
+      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 +429,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 +441,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.worldImpact.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.worldImpact.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 +488,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 +513,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 +533,8 @@
             name += " (body)";
           }
         }
-        backend.tracer.traceCompilation(name);
-        backend.tracer.traceGraph('builder', graph);
+        _tracer.traceCompilation(name);
+        _tracer.traceGraph('builder', graph);
       }
 
       return graph;
@@ -343,7 +562,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 +574,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) {
@@ -406,13 +625,12 @@
   /// Pops the most recent instruction from the stack and 'boolifies' it.
   ///
   /// Boolification is checking if the value is '=== true'.
-  @override
   HInstruction popBoolified() {
     HInstruction value = pop();
-    if (typeBuilder.checkOrTrustTypes) {
-      return typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
+    if (_typeBuilder.checkOrTrustTypes) {
+      return _typeBuilder.potentiallyCheckOrTrustTypeOfCondition(value);
     }
-    HInstruction result = new HBoolify(value, abstractValueDomain.boolType);
+    HInstruction result = new HBoolify(value, _abstractValueDomain.boolType);
     add(result);
     return result;
   }
@@ -426,17 +644,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 +675,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 +729,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 +749,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 +786,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 +800,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 +811,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 +845,7 @@
 
       ConstructorEntity inlinedConstructor = _elementMap.getConstructor(body);
 
-      inlinedFrom(
+      _inlinedFrom(
           inlinedConstructor, _sourceInformationBuilder.buildCall(body, body),
           () {
         ConstructorBodyEntity constructorBody =
@@ -636,7 +854,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 +868,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 +877,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 +899,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 +918,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 +937,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 +953,7 @@
         TypeVariableType typeVariable = variables.current;
         localsHandler.updateLocal(
             localsHandler.getTypeVariableAsLocal(typeVariable),
-            typeBuilder.analyzeTypeArgument(argument, sourceElement));
+            _typeBuilder.analyzeTypeArgument(argument, sourceElement));
       });
     }
   }
@@ -745,8 +962,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 +977,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 +995,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 +1005,7 @@
     });
   }
 
-  static bool isRedirectingConstructor(ir.Constructor constructor) =>
+  static bool _isRedirectingConstructor(ir.Constructor constructor) =>
       constructor.initializers
           .any((initializer) => initializer is ir.RedirectingInitializer);
 
@@ -797,14 +1013,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 +1050,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 +1171,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 +1193,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 +1205,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 +1215,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 +1256,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 +1265,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 +1283,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 +1304,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 +1314,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 +1337,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,7 +1360,7 @@
         graph.needsAsyncRewrite = true;
         graph.asyncElementType = elementType;
         functionNode.body.accept(this);
-        closeFunction();
+        _closeFunction();
         return;
       }
     }
@@ -1154,20 +1370,20 @@
     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 +1393,7 @@
       graph.asyncElementType = function.elementType;
     }
     functionNode.body.accept(this);
-    closeFunction();
+    _closeFunction();
   }
 
   bool _generatedEntryIsEmpty() {
@@ -1199,7 +1415,7 @@
     // check.
 
     if (targetChecks.checkTypeParameters) {
-      checkTypeVariableBounds(targetElement);
+      _checkTypeVariableBounds(targetElement);
     }
 
     MemberDefinition definition =
@@ -1207,9 +1423,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 +1440,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 +1453,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 +1477,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 +1507,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 +1516,7 @@
           _pushStaticInvocation(
               _commonElements.closureConverter,
               [argument, graph.addConstantInt(arity, closedWorld)],
-              abstractValueDomain.dynamicType,
+              _abstractValueDomain.dynamicType,
               const <DartType>[],
               sourceInformation: null);
           argument = pop();
@@ -1328,7 +1544,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 +1562,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 +1597,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 +1618,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 +1644,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 +1655,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 +1684,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 +1694,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 +1720,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();
@@ -1540,26 +1753,6 @@
     }
   }
 
-  /// 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 +1776,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 +1794,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 +1824,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 +1841,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 +1861,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 +1871,7 @@
 
     HInstruction buildGetLength(SourceInformation sourceInformation) {
       HGetLength result = new HGetLength(
-          array, abstractValueDomain.positiveIntType,
+          array, _abstractValueDomain.positiveIntType,
           isAssignable: !isFixed)
         ..sourceInformation = sourceInformation;
       add(result);
@@ -1696,7 +1889,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 +1907,7 @@
 
       node.iterable.accept(this);
       array = pop();
-      isFixed = abstractValueDomain
+      isFixed = _abstractValueDomain
           .isFixedLengthJsIndexable(array.instructionType)
           .isDefinitelyTrue;
       localsHandler.updateLocal(
@@ -1730,7 +1923,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 +1950,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 +1975,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 +1993,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 +2003,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 +2021,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 +2037,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 +2054,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 +2076,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 +2097,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 +2134,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 +2147,7 @@
     void finalizerFunction() {
       _pushDynamicInvocation(
           node,
+          staticInstanceType,
           null,
           Selectors.cancel,
           [streamIterator],
@@ -1949,7 +2155,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 +2164,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 +2189,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 +2207,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 +2240,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 +2285,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 +2302,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 +2329,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 +2342,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 +2352,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 +2376,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,13 +2395,13 @@
     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
@@ -2210,7 +2417,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 +2425,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 +2481,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 +2498,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 +2507,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 +2537,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 +2592,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 +2624,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 +2719,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 +2799,9 @@
     }
 
     void buildLoop() {
-      loopHandler.handleLoop(
+      _loopHandler.handleLoop(
           switchStatement,
-          closureDataLookup.getCapturedLoopScope(switchStatement),
+          _closureDataLookup.getCapturedLoopScope(switchStatement),
           switchTarget,
           () {},
           buildCondition,
@@ -2611,12 +2819,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 +2855,7 @@
     }
 
     HSwitch switchInstruction =
-        new HSwitch(abstractValueDomain, <HInstruction>[expression]);
+        new HSwitch(_abstractValueDomain, <HInstruction>[expression]);
     HBasicBlock expressionEnd = close(switchInstruction);
     LocalsHandler savedLocals = localsHandler;
 
@@ -2707,7 +2915,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 +2925,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 +3041,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 +3066,7 @@
         element.accept(this);
         elements.add(pop());
       }
-      listInstruction = buildLiteralList(elements);
+      listInstruction = _buildLiteralList(elements);
       add(listInstruction);
       SourceInformation sourceInformation =
           _sourceInformationBuilder.buildListLiteral(node);
@@ -2869,8 +3077,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 +3106,7 @@
       constructor = _commonElements.setLiteralConstructorEmpty;
     } else {
       constructor = _commonElements.setLiteralConstructor;
-      HLiteralList argList = buildLiteralList(elements);
+      HLiteralList argList = _buildLiteralList(elements);
       add(argList);
       inputs.add(argList);
     }
@@ -2910,17 +3118,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 +3149,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 +3187,7 @@
       constructor = _commonElements.mapLiteralConstructorEmpty;
     } else {
       constructor = _commonElements.mapLiteralConstructor;
-      HLiteralList argList = buildLiteralList(constructorArgs);
+      HLiteralList argList = _buildLiteralList(constructorArgs);
       add(argList);
       inputs.add(argList);
     }
@@ -2992,17 +3200,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 +3231,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 +3275,7 @@
 
     DartType dartType = _elementMap.getDartType(type);
     dartType = localsHandler.substInContext(dartType);
-    HInstruction value = typeBuilder.analyzeTypeArgument(
+    HInstruction value = _typeBuilder.analyzeTypeArgument(
         dartType, sourceElement,
         sourceInformation: sourceInformation);
     _pushStaticInvocation(
@@ -3143,9 +3351,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 +3367,7 @@
 
     _pushDynamicInvocation(
         node,
+        _getStaticType(node.receiver),
         _typeInferenceMap.receiverTypeOfGet(node),
         new Selector.getter(_elementMap.getName(node.name)),
         <HInstruction>[receiver],
@@ -3169,13 +3378,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 +3398,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 +3418,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 +3471,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 +3494,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 +3504,7 @@
     stack.add(value);
     localsHandler.updateLocal(
         local,
-        typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+        _typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
             value, _getDartTypeIfValid(variable.type)),
         sourceInformation: sourceInformation);
   }
@@ -3304,7 +3515,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 +3612,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 +3632,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 +3640,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 +3702,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 +3721,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 +3751,7 @@
     }
 
     if (function is ConstructorEntity && function.isFactoryConstructor) {
-      handleInvokeFactoryConstructor(
+      _handleInvokeFactoryConstructor(
           node, function, typeMask, arguments, sourceInformation);
       return;
     }
@@ -3550,7 +3761,7 @@
         sourceInformation: sourceInformation);
   }
 
-  void handleInvokeFactoryConstructor(
+  void _handleInvokeFactoryConstructor(
       ir.StaticInvocation invocation,
       ConstructorEntity function,
       AbstractValue typeMask,
@@ -3563,7 +3774,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 +3787,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 +3801,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 +3817,11 @@
               "Unexpected arguments. "
               "Expected 1-2 argument, actual: $arguments."));
       HInstruction lengthInput = arguments.first;
-      if (lengthInput.isNumber(abstractValueDomain).isPotentiallyFalse) {
+      if (lengthInput.isNumber(_abstractValueDomain).isPotentiallyFalse) {
         HTypeConversion conversion = new HTypeConversion(
-            commonElements.numType,
+            _commonElements.numType,
             HTypeConversion.ARGUMENT_TYPE_CHECK,
-            abstractValueDomain.numType,
+            _abstractValueDomain.numType,
             lengthInput,
             sourceInformation);
         add(conversion);
@@ -3629,14 +3840,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 +3863,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 +3901,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 +3916,7 @@
       graph.allocatedFixedLists.add(newInstance);
     }
 
-    if (rtiNeed.classNeedsTypeArguments(commonElements.listClass) &&
+    if (_rtiNeed.classNeedsTypeArguments(_commonElements.listClass) &&
         (isFixedListConstructorCall ||
             isGrowableListConstructorCall ||
             isJSArrayTypedConstructor)) {
@@ -3718,7 +3929,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 +3958,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 +3974,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 +3984,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 +4121,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 +4131,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 +4152,7 @@
           argumentNamesInstruction,
           typeArgumentCount,
         ],
-        abstractValueDomain.dynamicType,
+        _abstractValueDomain.dynamicType,
         const <DartType>[],
         sourceInformation: sourceInformation);
   }
@@ -4017,14 +4232,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 +4258,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 +4295,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 +4305,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 +4321,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.
@@ -4125,7 +4340,7 @@
 
     if (instruction is HConstant) {
       js.Name name =
-          _elementMap.getNameForJsGetName(instruction.constant, namer);
+          _elementMap.getNameForJsGetName(instruction.constant, _namer);
       stack.add(graph.addConstantStringFromName(name, closedWorld));
       return;
     }
@@ -4138,7 +4353,7 @@
     stack.add(graph.addConstantNull(closedWorld));
   }
 
-  void handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
+  void _handleForeignJsEmbeddedGlobal(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 2, maxPositional: 2)) {
       // Result expected on stack.
@@ -4148,7 +4363,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 +4378,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));
@@ -4179,7 +4394,7 @@
     js.Template template;
     if (instruction is HConstant) {
       template =
-          _elementMap.getJsBuiltinTemplate(instruction.constant, emitter);
+          _elementMap.getJsBuiltinTemplate(instruction.constant, _emitter);
     }
     if (template == null) {
       reporter.reportErrorMessage(
@@ -4210,7 +4425,7 @@
         nativeBehavior: nativeBehavior));
   }
 
-  void handleForeignJsGetFlag(ir.StaticInvocation invocation) {
+  void _handleForeignJsGetFlag(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 1, maxPositional: 1)) {
       stack.add(
@@ -4219,7 +4434,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 +4445,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 +4476,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 +4495,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 +4547,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 +4574,7 @@
     }
   }
 
-  void handleJsStringConcat(ir.StaticInvocation invocation) {
+  void _handleJsStringConcat(ir.StaticInvocation invocation) {
     if (_unexpectedForeignArguments(invocation,
         minPositional: 2, maxPositional: 2)) {
       // Result expected on stack.
@@ -4368,7 +4583,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 +4602,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 +4637,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 +4649,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 +4689,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 +4712,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 +4741,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 +4751,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 +4778,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 +4788,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 +4815,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 +4844,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());
   }
 
@@ -4636,7 +4862,7 @@
     node.expression.accept(this);
     arguments.add(pop());
     // TODO(johnniwinther): Use the static type of the expression.
-    bool typeArgumentsNeeded = rtiNeed.instantiationNeedsTypeArguments(
+    bool typeArgumentsNeeded = _rtiNeed.instantiationNeedsTypeArguments(
         null, node.typeArguments.length);
     List<DartType> typeArguments = node.typeArguments
         .map((type) => typeArgumentsNeeded
@@ -4648,7 +4874,7 @@
     // 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 +4890,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 +4910,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 +4922,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 +4950,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 +4961,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 +4977,7 @@
           argumentNamesInstruction,
           graph.addConstantInt(typeArguments.length, closedWorld),
         ],
-        abstractValueDomain.dynamicType,
+        _abstractValueDomain.dynamicType,
         typeArguments,
         sourceInformation: sourceInformation);
 
@@ -4781,7 +5008,7 @@
     if (target is FunctionEntity) {
       typeMask = _typeInferenceMap.getReturnTypeOf(target);
     } else {
-      typeMask = abstractValueDomain.dynamicType;
+      typeMask = _abstractValueDomain.dynamicType;
     }
     HInstruction instruction = new HInvokeSuper(
         target,
@@ -4794,7 +5021,7 @@
         sourceInformation,
         isSetter: selector.isSetter || selector.isIndexSet);
     instruction.sideEffects =
-        inferredData.getSideEffectsOfSelector(selector, null);
+        _inferredData.getSideEffectsOfSelector(selector, null);
     push(instruction);
     return instruction;
   }
@@ -4868,14 +5095,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 +5129,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 +5151,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 +5179,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 +5195,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 +5260,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 +5278,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 +5321,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 +5344,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 +5353,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 +5385,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 +5456,18 @@
       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).
     bool cachedCanBeInlined =
-        inlineCache.canInline(function, insideLoop: insideLoop);
+        _inlineCache.canInline(function, insideLoop: insideLoop);
     if (cachedCanBeInlined == false) return false;
 
     bool meetsHardConstraints() {
@@ -5240,20 +5483,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 +5506,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 +5518,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;
         }
       }
@@ -5314,7 +5557,7 @@
       // 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);
 
       if (!hasOnlyNonDeferredImportPaths) {
         return doesNotContainCode();
@@ -5349,7 +5592,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
@@ -5368,20 +5611,20 @@
           enableUserAssertions: options.enableUserAssertions);
       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);
+          _inlineCache.markAsNonInlinable(function, insideLoop: insideLoop);
         }
       }
       return canInline;
@@ -5404,16 +5647,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 +5740,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 +5777,7 @@
         }
       }
     });
-    if (rtiNeed.methodNeedsTypeArguments(function)) {
+    if (_rtiNeed.methodNeedsTypeArguments(function)) {
       if (callStructure.typeArgumentCount ==
           parameterStructure.typeParameters) {
         /// Offset of type arguments in [providedArguments].
@@ -5549,8 +5792,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 +5804,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 +5826,7 @@
         _returnType,
         stack,
         localsHandler,
-        inTryStatement,
+        _inTryStatement,
         _isCalledOnce(function));
     _inliningStack.add(state);
 
@@ -5597,7 +5840,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 +5851,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 +5901,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 +5910,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 +5928,7 @@
     }
     assert(
         argumentIndex == compiledArguments.length ||
-            !rtiNeed.methodNeedsTypeArguments(function) &&
+            !_rtiNeed.methodNeedsTypeArguments(function) &&
                 compiledArguments.length - argumentIndex ==
                     function.parameterStructure.typeParameters,
         failedAt(
@@ -5695,8 +5937,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 +5953,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 +5972,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 +5990,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,7 +6024,7 @@
 
   /// Generates type tests for the parameters of the inlined function.
   void _potentiallyCheckInlinedParameterTypes(FunctionEntity function) {
-    if (!typeBuilder.checkOrTrustTypes) return;
+    if (!_typeBuilder.checkOrTrustTypes) return;
 
     // TODO(sra): Incorporate properties of call site to help determine which
     // type parameters and value parameters need to be checked.
@@ -5798,7 +6039,7 @@
     }
 
     if (!trusted) {
-      checkTypeVariableBounds(function);
+      _checkTypeVariableBounds(function);
     }
 
     KernelToLocalsMap localsMap =
@@ -5810,10 +6051,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 +6086,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 +6094,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>[]));
   }
 }
@@ -6438,12 +6679,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 +6751,7 @@
     buildFinalizer();
     if (!kernelBuilder.isAborted()) {
       endFinallyBlock =
-          kernelBuilder.close(new HGoto(kernelBuilder.abstractValueDomain));
+          kernelBuilder.close(new HGoto(kernelBuilder._abstractValueDomain));
     }
     tryInstruction.finallyBlock = startFinallyBlock;
     finallyGraph =
@@ -6523,7 +6764,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 +6776,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 +6795,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 +6804,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 +6821,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 +6831,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 +6850,7 @@
     }
 
     ir.Catch firstBlock = tryCatch.catches[catchesIndex];
-    kernelBuilder.handleIf(
+    kernelBuilder._handleIf(
         visitCondition: () {
           pushCondition(firstBlock);
         },
@@ -6619,10 +6860,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 +6883,7 @@
             kernelBuilder.wrapStatementGraph(catchGraph),
             kernelBuilder.wrapStatementGraph(finallyGraph)),
         exitBlock);
-    kernelBuilder.inTryStatement = previouslyInTryStatement;
+    kernelBuilder._inTryStatement = previouslyInTryStatement;
   }
 }
 
@@ -6693,7 +6934,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 +6955,24 @@
     }
   }
 }
+
+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)';
+}
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index 6c5852a..6bfaa83 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -10,7 +10,7 @@
 import '../common.dart';
 import '../common/names.dart';
 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
-import '../common/tasks.dart' show CompilerTask;
+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;
@@ -29,7 +29,6 @@
 import '../js_emitter/code_emitter_task.dart';
 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;
@@ -47,12 +46,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 +60,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));
     }
@@ -79,67 +78,65 @@
     }
   }
 
-  js.Expression generateCode(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+  js.Expression generateCode(CodegenWorkItem work, HGraph graph,
+      CodegenInputs codegen, JClosedWorld closedWorld) {
     if (work.element.isField) {
-      return generateLazyInitializer(work, graph, closedWorld);
+      return generateLazyInitializer(work, graph, codegen, closedWorld);
     } else {
-      return generateMethod(work, graph, closedWorld);
+      return generateMethod(work, graph, codegen, closedWorld);
     }
   }
 
-  js.Expression generateLazyInitializer(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+  js.Expression generateLazyInitializer(CodegenWorkItem work, HGraph graph,
+      CodegenInputs codegen, JClosedWorld closedWorld) {
     return measure(() {
-      backend.tracer.traceGraph("codegen", graph);
-      SourceInformation sourceInformation = sourceInformationFactory
+      codegen.tracer.traceGraph("codegen", graph);
+      SourceInformation sourceInformation = sourceInformationStrategy
           .createBuilderForContext(work.element)
           .buildDeclaration(work.element);
-      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,
+          codegen.emitter,
+          codegen.checkedModeHelpers,
+          codegen.oneShotInterceptorData,
+          codegen.rtiSubstitutions,
+          codegen.rtiEncoder,
+          codegen.namer,
+          codegen.superMemberData,
+          codegen.tracer,
           closedWorld,
           work);
-      codegen.visitGraph(graph);
-      return new js.Fun(codegen.parameters, codegen.body)
+      codeGenerator.visitGraph(graph);
+      return new js.Fun(codeGenerator.parameters, codeGenerator.body)
           .withSourceInformation(sourceInformation);
     });
   }
 
-  js.Expression generateMethod(
-      CodegenWorkItem work, HGraph graph, JClosedWorld closedWorld) {
+  js.Expression generateMethod(CodegenWorkItem work, HGraph graph,
+      CodegenInputs codegen, JClosedWorld closedWorld) {
     return measure(() {
       FunctionEntity element = work.element;
       if (element.asyncMarker != AsyncMarker.SYNC) {
         work.registry.registerAsyncMarker(element.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,
+          codegen.emitter,
+          codegen.checkedModeHelpers,
+          codegen.oneShotInterceptorData,
+          codegen.rtiSubstitutions,
+          codegen.rtiEncoder,
+          codegen.namer,
+          codegen.superMemberData,
+          codegen.tracer,
           closedWorld,
           work);
-      codegen.visitGraph(graph);
-      backend.tracer.traceGraph("codegen", graph);
+      codeGenerator.visitGraph(graph);
+      codegen.tracer.traceGraph("codegen", graph);
       return buildJavaScriptFunction(graph.needsAsyncRewrite, work.element,
-          codegen.parameters, codegen.body);
+          codeGenerator.parameters, codeGenerator.body);
     });
   }
 }
@@ -165,8 +162,7 @@
 
   final CompilerTask _codegenTask;
   final CompilerOptions _options;
-  final CodeEmitterTask _emitter;
-  final NativeCodegenEnqueuer _nativeEnqueuer;
+  final Emitter _emitter;
   final CheckedModeHelpers _checkedModeHelpers;
   final OneShotInterceptorData _oneShotInterceptorData;
   final RuntimeTypesSubstitutions _rtiSubstitutions;
@@ -223,7 +219,6 @@
       this._codegenTask,
       this._options,
       this._emitter,
-      this._nativeEnqueuer,
       this._checkedModeHelpers,
       this._oneShotInterceptorData,
       this._rtiSubstitutions,
@@ -1979,10 +1974,13 @@
       // 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));
     }
@@ -1997,7 +1995,8 @@
       _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));
     }
@@ -2014,7 +2013,8 @@
       _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));
     }
@@ -2092,12 +2092,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 +2119,47 @@
   visitInvokeSuper(HInvokeSuper node) {
     MemberEntity superElement = node.element;
     ClassEntity superClass = superElement.enclosingClass;
+    Selector selector = node.selector;
+    bool useAliasedSuper = _superMemberData.maybeRegisterAliasedSuperMember(
+        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 (_superMemberData.maybeRegisterAliasedSuperMember(
+          superElement, selector)) {
+        _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 +2171,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 +2183,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 +2269,7 @@
   void registerForeignTypes(HForeign node) {
     NativeBehavior nativeBehavior = node.nativeBehavior;
     if (nativeBehavior == null) return;
-    _nativeEnqueuer.registerNativeBehavior(
-        _registry.worldImpact, nativeBehavior, node);
+    _registry.registerNativeBehavior(nativeBehavior);
   }
 
   @override
@@ -3246,9 +3273,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}: "
diff --git a/pkg/compiler/lib/src/ssa/codegen_helpers.dart b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
index 4ad0571..c1ee6cb 100644
--- a/pkg/compiler/lib/src/ssa/codegen_helpers.dart
+++ b/pkg/compiler/lib/src/ssa/codegen_helpers.dart
@@ -136,7 +136,7 @@
   @override
   HInstruction visitInvokeDynamic(HInvokeDynamic node) {
     if (node.isInterceptedCall) {
-      tryReplaceInterceptorWithDummy(node, node.selector, node.mask);
+      tryReplaceInterceptorWithDummy(node, node.selector, node.receiverType);
     }
     return node;
   }
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/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..9e87a54 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -1713,15 +1713,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 +1736,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 +1781,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 +1799,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 +1816,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 +1837,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 +1879,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 +1890,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 +1911,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 +3205,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 +3219,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);
 }
@@ -3730,8 +3760,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();
   }
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index e584210..88f9b6c 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -5,8 +5,7 @@
 import '../common.dart';
 import '../common/codegen.dart' show CodegenRegistry, CodegenWorkItem;
 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;
@@ -40,28 +39,26 @@
 }
 
 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,
+  void optimize(
+      CodegenWorkItem work,
+      HGraph graph,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults) {
     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}');
     }
 
@@ -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);
@@ -143,7 +140,7 @@
           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 SsaDeadCodeEliminator(closedWorld, this),
@@ -155,7 +152,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);
@@ -563,7 +560,7 @@
     }
 
     Selector selector = node.selector;
-    AbstractValue mask = node.mask;
+    AbstractValue mask = node.receiverType;
     HInstruction input = node.inputs[1];
 
     bool applies(MemberEntity element) {
@@ -616,7 +613,7 @@
         // optimization.
         HInvokeDynamicMethod result = new HInvokeDynamicMethod(
             node.selector,
-            node.mask,
+            node.receiverType,
             node.inputs.sublist(1), // Drop interceptor.
             node.instructionType,
             node.typeArguments,
@@ -653,7 +650,7 @@
 
     HInvokeDynamicMethod splitInstruction = new HInvokeDynamicMethod(
         node.selector,
-        node.mask,
+        node.receiverType,
         node.inputs.sublist(1), // Drop interceptor.
         resultMask,
         const <DartType>[],
@@ -780,8 +777,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 +852,7 @@
         AbstractValueFactory.fromNativeBehavior(nativeBehavior, _closedWorld);
     HInvokeDynamicMethod result = new HInvokeDynamicMethod(
         node.selector,
-        node.mask,
+        node.receiverType,
         inputs.sublist(1), // Drop interceptor.
         returnType,
         node.typeArguments,
@@ -1601,8 +1604,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 +1621,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>[],
@@ -2939,8 +2943,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 +2952,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 +2981,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 +3024,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 +3058,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 +3071,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..c6e963e 100644
--- a/pkg/compiler/lib/src/ssa/ssa.dart
+++ b/pkg/compiler/lib/src/ssa/ssa.dart
@@ -4,16 +4,22 @@
 
 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 CodegenRegistry, CodegenWorkItem;
 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_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,37 +27,49 @@
 import 'optimize.dart';
 
 class SsaFunctionCompiler implements FunctionCompiler {
+  final DiagnosticReporter _reporter;
   final SsaCodeGeneratorTask generator;
   final SsaBuilderTask _builder;
   final SsaOptimizerTask optimizer;
-  final JavaScriptBackend backend;
+  final SourceInformationStrategy sourceInformationStrategy;
 
-  SsaFunctionCompiler(JavaScriptBackend backend, Measurer measurer,
-      SourceInformationStrategy sourceInformationFactory)
-      : generator = new SsaCodeGeneratorTask(backend, sourceInformationFactory),
-        _builder = new SsaBuilderTask(backend, sourceInformationFactory),
-        optimizer = new SsaOptimizerTask(backend),
-        backend = backend;
+  SsaFunctionCompiler(
+      CompilerOptions 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() {
-    _builder.onCodegenStart();
+  void onCodegenStart(CodegenInputs codegen) {
+    _builder.onCodegenStart(codegen);
   }
 
   /// Generates JavaScript code for `work.element`.
   /// Using the ssa builder, optimizer and code generator.
   @override
-  js.Fun compile(CodegenWorkItem work, JClosedWorld closedWorld,
+  js.Fun compile(
+      CodegenWorkItem work,
+      CodegenInputs codegen,
+      JClosedWorld closedWorld,
       GlobalTypeInferenceResults globalInferenceResults) {
     HGraph graph = _builder.build(work, closedWorld, globalInferenceResults);
     if (graph == null) return null;
-    optimizer.optimize(work, graph, closedWorld, globalInferenceResults);
+    optimizer.optimize(
+        work, graph, codegen, closedWorld, globalInferenceResults);
     MemberEntity element = work.element;
-    js.Expression result = generator.generateCode(work, graph, closedWorld);
+    js.Expression result =
+        generator.generateCode(work, graph, codegen, closedWorld);
     if (graph.needsAsyncRewrite) {
       SourceInformationBuilder sourceInformationBuilder =
-          backend.sourceInformationStrategy.createBuilderForContext(element);
-      result = backend.rewriteAsync(
+          sourceInformationStrategy.createBuilderForContext(element);
+      result = _rewriteAsync(
+          codegen,
           closedWorld.commonElements,
           closedWorld.elementEnvironment,
           work.registry,
@@ -64,6 +82,132 @@
     return result;
   }
 
+  js.Expression _rewriteAsync(
+      CodegenInputs codegen,
+      CommonElements commonElements,
+      JElementEnvironment elementEnvironment,
+      CodegenRegistry registry,
+      FunctionEntity element,
+      js.Expression code,
+      DartType asyncTypeParameter,
+      SourceInformation bodySourceInformation,
+      SourceInformation exitSourceInformation) {
+    if (element.asyncMarker == AsyncMarker.SYNC) return code;
+
+    AsyncRewriterBase rewriter = null;
+    js.Name name = codegen.namer.methodPropertyName(
+        element is JGeneratorBody ? element.function : element);
+
+    switch (element.asyncMarker) {
+      case AsyncMarker.ASYNC:
+        rewriter = _makeAsyncRewriter(
+            codegen,
+            commonElements,
+            elementEnvironment,
+            registry,
+            element,
+            code,
+            asyncTypeParameter,
+            name);
+        break;
+      case AsyncMarker.SYNC_STAR:
+        rewriter = new SyncStarRewriter(_reporter, element,
+            endOfIteration: codegen.emitter
+                .staticFunctionAccess(commonElements.endOfIteration),
+            iterableFactory: codegen.emitter
+                .staticFunctionAccess(commonElements.syncStarIterableFactory),
+            iterableFactoryTypeArguments:
+                _fetchItemType(codegen, asyncTypeParameter),
+            yieldStarExpression:
+                codegen.emitter.staticFunctionAccess(commonElements.yieldStar),
+            uncaughtErrorExpression: codegen.emitter
+                .staticFunctionAccess(commonElements.syncStarUncaughtError),
+            safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+            bodyName: codegen.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: codegen.emitter
+                .staticFunctionAccess(commonElements.asyncStarHelper),
+            streamOfController: codegen.emitter
+                .staticFunctionAccess(commonElements.streamOfController),
+            wrapBody:
+                codegen.emitter.staticFunctionAccess(commonElements.wrapBody),
+            newController: codegen.emitter.staticFunctionAccess(
+                commonElements.asyncStarStreamControllerFactory),
+            newControllerTypeArguments:
+                _fetchItemType(codegen, asyncTypeParameter),
+            safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+            yieldExpression: codegen.emitter
+                .staticFunctionAccess(commonElements.yieldSingle),
+            yieldStarExpression:
+                codegen.emitter.staticFunctionAccess(commonElements.yieldStar),
+            bodyName: codegen.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, DartType type) {
+    if (type == null) return null;
+    var ast =
+        codegen.rtiEncoder.getTypeRepresentation(codegen.emitter, type, null);
+    return <js.Expression>[ast];
+  }
+
+  AsyncRewriter _makeAsyncRewriter(
+      CodegenInputs codegen,
+      CommonElements commonElements,
+      JElementEnvironment elementEnvironment,
+      CodegenRegistry registry,
+      FunctionEntity element,
+      js.Expression code,
+      DartType elementType,
+      js.Name name) {
+    FunctionEntity startFunction = commonElements.asyncHelperStartSync;
+    FunctionEntity completerFactory = commonElements.asyncAwaitCompleterFactory;
+
+    List<js.Expression> itemTypeExpression =
+        _fetchItemType(codegen, elementType);
+
+    AsyncRewriter rewriter = new AsyncRewriter(_reporter, element,
+        asyncStart: codegen.emitter.staticFunctionAccess(startFunction),
+        asyncAwait: codegen.emitter
+            .staticFunctionAccess(commonElements.asyncHelperAwait),
+        asyncReturn: codegen.emitter
+            .staticFunctionAccess(commonElements.asyncHelperReturn),
+        asyncRethrow: codegen.emitter
+            .staticFunctionAccess(commonElements.asyncHelperRethrow),
+        wrapBody: codegen.emitter.staticFunctionAccess(commonElements.wrapBody),
+        completerFactory:
+            codegen.emitter.staticFunctionAccess(completerFactory),
+        completerFactoryTypeArguments: itemTypeExpression,
+        safeVariableName: codegen.namer.safeVariablePrefixForAsyncRewrite,
+        bodyName: codegen.namer.deriveAsyncBodyName(name));
+
+    registry.registerStaticUse(new StaticUse.staticInvoke(
+        completerFactory,
+        const CallStructure.unnamed(0, 1),
+        [elementEnvironment.getFunctionAsyncOrSyncStarElementType(element)]));
+
+    return rewriter;
+  }
+
   @override
   Iterable<CompilerTask> get tasks {
     return <CompilerTask>[_builder, optimizer, generator];
@@ -78,19 +222,20 @@
 }
 
 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);
+  void onCodegenStart(CodegenInputs codegen) {
+    _builder = _backendStrategy.createSsaBuilder(
+        this, codegen, _sourceInformationFactory);
   }
 
   /// Creates the [HGraph] for [work] or returns `null` if no code is needed
@@ -100,41 +245,3 @@
     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;
-  }
-}
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..b4fe2d7 100644
--- a/pkg/compiler/lib/src/ssa/ssa_tracer.dart
+++ b/pkg/compiler/lib/src/ssa/ssa_tracer.dart
@@ -372,7 +372,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
diff --git a/pkg/compiler/lib/src/ssa/type_builder.dart b/pkg/compiler/lib/src/ssa/type_builder.dart
index bb7e4ed..710338c 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.
@@ -123,7 +130,7 @@
   }
 
   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);
@@ -194,11 +201,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 +225,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 +238,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,7 +256,7 @@
         TypeInfoExpressionKind.COMPLETE,
         argument,
         inputs,
-        builder.abstractValueDomain.dynamicType)
+        _abstractValueDomain.dynamicType)
       ..sourceInformation = sourceInformation;
     builder.add(result);
     return result;
@@ -268,8 +275,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 +299,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..7079eec 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -332,11 +332,11 @@
       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;
@@ -436,7 +436,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/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index eb54121..b719421 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -4,17 +4,18 @@
 
 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/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 +26,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
+  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 +59,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 +85,13 @@
   /// [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 the types that are live as constant type arguments.
-  Iterable<DartType> get liveTypeArguments;
 }
 
 class CodegenWorldBuilderImpl extends WorldBuilderBase
     implements CodegenWorldBuilder {
-  final JClosedWorld _world;
+  final JClosedWorld _closedWorld;
 
   /// 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 +111,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 +123,43 @@
 
   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);
 
-  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 +169,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 +214,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 +269,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 +305,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 +388,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 +537,312 @@
   }
 
   /// 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);
+  }
+}
+
+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;
+
+  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})
+      : _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 +857,13 @@
       }
     }
 
-    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;
-  }
-
-  @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..f6386be 100644
--- a/pkg/compiler/lib/src/universe/feature.dart
+++ b/pkg/compiler/lib/src/universe/feature.dart
@@ -36,9 +36,6 @@
   /// A catch statement.
   CATCH_STATEMENT,
 
-  /// A compile time error.
-  COMPILE_TIME_ERROR,
-
   /// A fall through in a switch case.
   FALL_THROUGH_ERROR,
 
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/use.dart b/pkg/compiler/lib/src/universe/use.dart
index 01b0d07..453f812 100644
--- a/pkg/compiler/lib/src/universe/use.dart
+++ b/pkg/compiler/lib/src/universe/use.dart
@@ -147,19 +147,21 @@
   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,
 }
@@ -198,9 +200,10 @@
   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:
@@ -262,13 +265,15 @@
             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);
+    return new GenericStaticUse(element, StaticUseKind.STATIC_INVOKE,
+        callStructure, typeArguments, deferredImport);
   }
 
   /// Closurization of a static or top-level function [element].
@@ -280,6 +285,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 +299,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 +318,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);
   }
 
@@ -345,7 +352,7 @@
         failedAt(element,
             "Not CallStructure for super invocation of element $element."));
     return new GenericStaticUse(
-        element, StaticUseKind.INVOKE, callStructure, typeArguments);
+        element, StaticUseKind.SUPER_INVOKE, callStructure, typeArguments);
   }
 
   /// Read access of a super field or getter [element].
@@ -358,7 +365,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 +387,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 +415,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 +429,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);
   }
 
@@ -456,7 +463,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 +474,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 +490,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 +537,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 +563,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 +572,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].
@@ -602,7 +596,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);
   }
 
@@ -654,7 +648,7 @@
             element,
             "Type argument count mismatch. Call structure has "
             "${callStructure?.typeArgumentCount ?? 0} but "
-            "${typeArguments?.length ?? 0} were passed."));
+            "${typeArguments?.length ?? 0} were passed in $this."));
   }
 
   GenericStaticUse.methodInlining(FunctionEntity entity, this.typeArguments)
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/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/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/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/bin/dartdevc.dart b/pkg/dev_compiler/bin/dartdevc.dart
index 1075043..fbe7114 100755
--- a/pkg/dev_compiler/bin/dartdevc.dart
+++ b/pkg/dev_compiler/bin/dartdevc.dart
@@ -56,18 +56,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..1b5039a 100644
--- a/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/ast_builder.dart
@@ -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 "[]":
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index 39f7c88f..2c72273 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';
@@ -3961,23 +3962,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;
   }
 
@@ -5177,9 +5185,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 +5204,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].
diff --git a/pkg/dev_compiler/lib/src/analyzer/driver.dart b/pkg/dev_compiler/lib/src/analyzer/driver.dart
index 7c5d95b..c1e1efc 100644
--- a/pkg/dev_compiler/lib/src/analyzer/driver.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/driver.dart
@@ -340,6 +340,7 @@
         (uri) => _isLibraryUri('$uri'),
         resynthesizer.context,
         resynthesizer,
+        null,
         InheritanceManager2(resynthesizer.typeSystem),
         libraryFile,
         _resourceProvider);
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/flutter/track_widget_constructor_locations.dart b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
index 02d12f2..a667613 100644
--- a/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
+++ b/pkg/dev_compiler/lib/src/flutter/track_widget_constructor_locations.dart
@@ -10,7 +10,7 @@
 //
 // The following modifications were made:
 // - remove "package:vm" dependency (only used for one interface)
-// - pass in the class hierarchy that DDC already has available.
+// - optionally 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`
@@ -314,9 +314,9 @@
   /// [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;
+  ClassHierarchy hierarchy;
 
-  WidgetCreatorTracker(this.hierarchy);
+  WidgetCreatorTracker([this.hierarchy]);
 
   void _resolveFlutterClasses(Iterable<Library> libraries) {
     // If the Widget or Debug location classes have been updated we need to get
@@ -364,13 +364,15 @@
     // 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,
+    final Name fieldName = new Name(
+      _locationFieldName,
+      _hasCreationLocationClass.enclosingLibrary,
     );
+    final Field locationField = new Field(fieldName,
+        isFinal: true,
+        reference: clazz.reference.canonicalName
+            ?.getChildFromFieldWithName(fieldName)
+            ?.reference);
     clazz.addMember(locationField);
 
     final Set<Constructor> _handledConstructors =
@@ -436,6 +438,23 @@
     clazz.constructors.forEach(handleConstructor);
   }
 
+  Component _computeFullProgram(Component deltaProgram) {
+    final Set<Library> libraries = new Set<Library>();
+    final List<Library> workList = <Library>[];
+    for (Library library in deltaProgram.libraries) {
+      workList.add(library);
+    }
+    while (workList.isNotEmpty) {
+      final Library library = workList.removeLast();
+      for (LibraryDependency dependency in library.dependencies) {
+        if (libraries.add(dependency.targetLibrary)) {
+          workList.add(dependency.targetLibrary);
+        }
+      }
+    }
+    return new Component()..libraries.addAll(libraries);
+  }
+
   /// Transform the given [module].
   void transform(Component module) {
     final List<Library> libraries = module.libraries;
@@ -451,6 +470,14 @@
       return;
     }
 
+    // TODO(jacobr): once there is a working incremental ClassHierarchy
+    // constructor switch to using it instead of building a ClassHierarchy off
+    // the full program.
+    hierarchy ??= new ClassHierarchy(
+      _computeFullProgram(module),
+      onAmbiguousSupertypes: (Class cls, Supertype a, Supertype b) {},
+    );
+
     final Set<Class> transformedClasses = new Set<Class>.identity();
     final Set<Library> librariesToTransform = new Set<Library>.identity()
       ..addAll(module.libraries);
diff --git a/pkg/dev_compiler/lib/src/kernel/command.dart b/pkg/dev_compiler/lib/src/kernel/command.dart
index e9f2a3a..cf0f5bc 100644
--- a/pkg/dev_compiler/lib/src/kernel/command.dart
+++ b/pkg/dev_compiler/lib/src/kernel/command.dart
@@ -323,6 +323,7 @@
   // TODO(jmesserly): remove this hack once Flutter SDK has a `dartdevc` with
   // support for the widget inspector.
   if (argResults['track-widget-creation'] as bool) {
+    component.computeCanonicalNames();
     WidgetCreatorTracker(hierarchy).transform(component);
   }
 
diff --git a/pkg/dev_compiler/lib/src/kernel/compiler.dart b/pkg/dev_compiler/lib/src/kernel/compiler.dart
index b6c1925..3267966 100644
--- a/pkg/dev_compiler/lib/src/kernel/compiler.dart
+++ b/pkg/dev_compiler/lib/src/kernel/compiler.dart
@@ -166,6 +166,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;
@@ -3226,6 +3244,12 @@
 
   @override
   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 +3262,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}';
@@ -3407,43 +3431,102 @@
 
   @override
   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');
-      }
+    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')
@@ -5261,3 +5344,10 @@
   }
   return false;
 }
+
+class SwitchLabelState {
+  String label;
+  JS.Identifier variable;
+
+  SwitchLabelState(this.label, this.variable);
+}
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/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/ddb b/pkg/dev_compiler/tool/ddb
index b5cb2fa..c48fd81 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;
@@ -67,11 +66,8 @@
   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.
@@ -80,6 +76,19 @@
     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) {
+    stdout
+      ..write(result.stdout)
+      ..flush();
+    stderr
+      ..write(result.stderr)
+      ..flush();
+    if (result.exitCode != 0) exit(result.exitCode);
+  }
+
   String mod;
   bool chrome = false;
   bool node = false;
@@ -105,7 +114,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');
@@ -140,12 +148,7 @@
       entry
     ]);
   }
-
-  print(result.stdout);
-  if (result.exitCode != 0) {
-    print(result.stderr);
-    exit(result.exitCode);
-  }
+  echoResult(result);
 
   if (chrome) {
     String chromeBinary;
@@ -220,9 +223,6 @@
     result = Process.runSync(
         nodeBinary, ['--inspect=localhost:$port', nodeFile],
         environment: {'NODE_PATH': nodePath});
-    stdout
-      ..write(result.stdout)
-      ..flush();
   } else if (d8) {
     var runjs = '''
     import { dart, _isolate_helper } from '$sdkJsPath/dart_sdk.js';
@@ -239,13 +239,7 @@
     var d8File = '$libRoot/$basename.d8.js';
     new File(d8File).writeAsStringSync(runjs);
     var d8Binary = binary ?? 'd8';
-    result = Process.runSync(binary, ['--module', d8File]);
-    stdout
-      ..write(result.stdout)
-      ..flush();
+    result = Process.runSync(d8Binary, ['--module', d8File]);
   }
-  if (result.exitCode != 0) {
-    print(result.stderr);
-    exit(result.exitCode);
-  }
+  echoResult(result);
 }
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
index 192b5f6..da07a3c 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/core_patch.dart
@@ -547,9 +547,15 @@
 class RegExp {
   @patch
   factory RegExp(String source,
-          {bool multiLine = false, bool caseSensitive = true}) =>
+          {bool multiLine = false,
+          bool caseSensitive = true,
+          bool unicode = false,
+          bool dotAll = false}) =>
       JSSyntaxRegExp(source,
-          multiLine: multiLine, caseSensitive: caseSensitive);
+          multiLine: multiLine,
+          caseSensitive: caseSensitive,
+          unicode: unicode,
+          dotAll: dotAll);
 
   @patch
   static String escape(String text) => quoteStringForRegExp(text);
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
index e943f3e..3ec16c9 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/runtime.dart
@@ -90,8 +90,10 @@
       }
     }
     if (typeof $window.SourceBufferList == "undefined") {
-      $window.SourceBufferList =
-        new $window.MediaSource().sourceBuffers.constructor;
+      if ('MediaSource' in $window) {
+        $window.SourceBufferList =
+          new $window.MediaSource().sourceBuffers.constructor; 
+      }
     }
     if (typeof $window.SpeechRecognition == "undefined") {
       $window.SpeechRecognition = $window.webkitSpeechRecognition;
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
index a5d6dd0..41c3de7 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/ddc_runtime/types.dart
@@ -201,7 +201,9 @@
   toString() => 'bottom';
 }
 
-final bottom = BottomType();
+// 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';
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
index 3a6f4e9..69016fd 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
@@ -6,6 +6,7 @@
 
 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';
@@ -33,6 +34,7 @@
   static const keyToString = JsonMLConfig("keyToString");
   static const asClass = JsonMLConfig("asClass");
   static const asObject = JsonMLConfig("asObject");
+  static const asMap = JsonMLConfig("asMap");
   toString() => "JsonMLConfig($name)";
 }
 
@@ -458,6 +460,7 @@
       TypeFormatter(),
       NamedConstructorFormatter(),
       MapFormatter(),
+      MapOverviewFormatter(),
       IterableFormatter(),
       IterableSpanFormatter(),
       MapEntryFormatter(),
@@ -677,8 +680,13 @@
       ];
 }
 
-/// Formatter for Dart Map objects.
-class MapFormatter implements Formatter {
+/// 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;
@@ -686,6 +694,35 @@
   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);
@@ -703,20 +740,9 @@
       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.
diff --git a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
index 9206685..744effc 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/regexp_helper.dart
@@ -47,18 +47,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 {
@@ -68,17 +72,21 @@
     // 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(@nullCheck String source, bool multiLine,
-      bool caseSensitive, bool global) {
+      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
@@ -87,7 +95,7 @@
         '',
         '(function() {'
         'try {'
-        'return new RegExp(#, # + # + #);'
+        'return new RegExp(#, # + # + # + # + #);'
         '} catch (e) {'
         'return e;'
         '}'
@@ -95,6 +103,8 @@
         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
@@ -103,7 +113,7 @@
     throw FormatException("Illegal RegExp pattern: $source, $errorMessage");
   }
 
-  Match firstMatch(@nullCheck String string) {
+  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));
@@ -120,7 +130,7 @@
     return null;
   }
 
-  Iterable<Match> allMatches(@nullCheck String string,
+  Iterable<RegExpMatch> allMatches(@nullCheck String string,
       [@nullCheck int start = 0]) {
     if (start < 0 || start > string.length) {
       throw RangeError.range(start, 0, string.length);
@@ -128,7 +138,7 @@
     return _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);
@@ -136,7 +146,7 @@
     return _MatchImplementation(this, JSArray<String>.of(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);
@@ -148,7 +158,7 @@
     return _MatchImplementation(this, JSArray<String>.of(match));
   }
 
-  Match matchAsPrefix(String string, [int start = 0]) {
+  RegExpMatch matchAsPrefix(String string, [int start = 0]) {
     if (start < 0 || start > string.length) {
       throw RangeError.range(start, 0, string.length);
     }
@@ -157,6 +167,8 @@
 
   bool get isMultiLine => _isMultiLine;
   bool get isCaseSensitive => _isCaseSensitive;
+  bool get isUnicode => _isUnicode;
+  bool get isDotAll => _isDotAll;
 }
 
 class _MatchImplementation implements RegExpMatch {
@@ -207,25 +219,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 => _AllMatchesIterator(_re, _string, _start);
+  Iterator<RegExpMatch> get iterator =>
+      _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;
@@ -235,6 +256,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;
@@ -248,6 +278,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/pkg/front_end/lib/src/api_unstable/bazel_worker.dart b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
index 6f37ab2..1e74242 100644
--- a/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
+++ b/pkg/front_end/lib/src/api_unstable/bazel_worker.dart
@@ -23,9 +23,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;
@@ -114,8 +112,6 @@
     for (WorkerInputComponent cachedInput in workerInputCache.values) {
       cachedInput.component.adoptChildren();
     }
-    sdkComponent.unbindCanonicalNames();
-    sdkComponent.computeCanonicalNames();
 
     // Reuse the incremental compiler, but reset as needed.
     incrementalCompiler = oldState.incrementalCompiler;
@@ -125,9 +121,6 @@
   }
 
   // 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>();
@@ -144,8 +137,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.adoptChildren();
       component.computeCanonicalNames();
       inputSummaries.add(component);
@@ -158,7 +149,8 @@
     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);
   }
@@ -199,9 +191,9 @@
   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}) {
   summaryOnly ??= true;
   CompilerOptions options = compilerState.options;
   options..onDiagnostic = diagnosticMessageHandler;
@@ -210,11 +202,24 @@
   processedOpts.inputs.clear();
   processedOpts.inputs.addAll(inputs);
 
-  var result = await generateKernel(processedOpts,
+  return generateKernel(processedOpts,
       buildSummary: summaryOnly, buildComponent: !summaryOnly);
+}
+
+Future<List<int>> compileSummary(InitializedCompilerState compilerState,
+    List<Uri> inputs, DiagnosticMessageHandler diagnosticMessageHandler) async {
+  var result = await _compile(compilerState, inputs, diagnosticMessageHandler,
+      summaryOnly: true);
+  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 +231,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/ddc.dart b/pkg/front_end/lib/src/api_unstable/ddc.dart
index 4542aa3..ef61212 100644
--- a/pkg/front_end/lib/src/api_unstable/ddc.dart
+++ b/pkg/front_end/lib/src/api_unstable/ddc.dart
@@ -180,11 +180,10 @@
     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;
@@ -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/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 9cfba14..3746481 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -379,12 +379,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/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_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/fasta_codes_generated.dart b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
index 668da04..0c4177b 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -757,6 +757,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 +950,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 +959,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.
@@ -1945,17 +1955,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.
@@ -6366,7 +6365,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())""");
 
@@ -9360,7 +9359,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..52264f2 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -608,7 +608,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 +730,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 +791,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;
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..d780212 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -531,16 +531,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);
   }
 
@@ -591,7 +601,9 @@
       buildDartType(pop()); // Type.
     }
     List<Expression> annotations = pop();
-    if (annotations != null) {
+    // Fields with duplicate names are sorted out in the else branch of the
+    // `declaration.next == null` above.
+    if (annotations != null && fields.isNotEmpty) {
       inferAnnotations(annotations);
       Field field = fields.first.target;
       // The first (and often only field) will not get a clone.
@@ -1489,7 +1501,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 +1843,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 +2146,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);
@@ -2862,8 +2881,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));
   }
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..9173c09
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_collection_builders.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.
+
+part of 'constant_evaluator.dart';
+
+abstract class _ListOrSetConstantBuilder<L extends Expression,
+    C extends Constant> {
+  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);
+
+  C makeConstant(List<Constant> elements);
+
+  Message get messageForIteration;
+
+  _ListOrSetConstantBuilder<L, C> newTempBuilder();
+
+  /// Add an element (which is possibly a spread or an if element) to the
+  /// constant list being built by this builder.
+  void add(Expression element) {
+    if (element is SpreadElement) {
+      addSpread(element.expression, isNullAware: element.isNullAware);
+    } else if (element is IfElement) {
+      Constant condition = evaluator._evaluateSubexpression(element.condition);
+      if (evaluator.shouldBeUnevaluated) {
+        // Unevaluated if
+        evaluator.enterLazy();
+        Constant then = (newTempBuilder()..add(element.then)).build();
+        Constant otherwise;
+        if (element.otherwise != null) {
+          otherwise = (newTempBuilder()..add(element.otherwise)).build();
+        } else {
+          otherwise = makeConstant([]);
+        }
+        evaluator.leaveLazy();
+        parts.add(evaluator.unevaluated(
+            element.condition,
+            new ConditionalExpression(
+                evaluator.extract(condition),
+                evaluator.extract(then),
+                evaluator.extract(otherwise),
+                const DynamicType())));
+      } else {
+        // Fully evaluated if
+        if (condition == evaluator.trueConstant) {
+          add(element.then);
+        } else if (condition == evaluator.falseConstant) {
+          if (element.otherwise != null) {
+            add(element.otherwise);
+          }
+        } else if (condition == evaluator.nullConstant) {
+          evaluator.report(element.condition, messageConstEvalNullValue);
+        } else {
+          evaluator.report(
+              element.condition,
+              templateConstEvalInvalidType.withArguments(
+                  condition,
+                  evaluator.typeEnvironment.boolType,
+                  condition.getType(evaluator.typeEnvironment)));
+        }
+      }
+    } else if (element is ForElement || element is ForInElement) {
+      // For or for-in
+      evaluator.report(element, messageForIteration);
+    } else {
+      // Ordinary 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, {bool isNullAware}) {
+    Constant spread =
+        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+    if (evaluator.shouldBeUnevaluated) {
+      // Unevaluated spread
+      if (isNullAware) {
+        VariableDeclaration temp = new VariableDeclaration(null,
+            initializer: evaluator.extract(spread));
+        parts.add(evaluator.unevaluated(
+            spreadExpression,
+            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 == evaluator.nullConstant) {
+      // Null spread
+      if (!isNullAware) {
+        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, ListConstant> {
+  ListConstantBuilder(
+      Expression original, DartType elementType, ConstantEvaluator evaluator)
+      : super(original, elementType, evaluator);
+
+  @override
+  ListLiteral makeLiteral(List<Expression> elements) =>
+      new ListLiteral(elements, isConst: true);
+
+  @override
+  ListConstant makeConstant(List<Constant> elements) =>
+      new ListConstant(const DynamicType(), elements);
+
+  @override
+  Message get messageForIteration => messageConstEvalIterationInConstList;
+
+  @override
+  ListConstantBuilder newTempBuilder() =>
+      new ListConstantBuilder(original, const DynamicType(), evaluator);
+
+  @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, SetConstant> {
+  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
+  SetConstant makeConstant(List<Constant> elements) =>
+      new SetConstant(const DynamicType(), elements);
+
+  @override
+  Message get messageForIteration => messageConstEvalIterationInConstSet;
+
+  @override
+  SetConstantBuilder newTempBuilder() =>
+      new SetConstantBuilder(original, const DynamicType(), evaluator);
+
+  @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);
+
+  MapConstantBuilder newTempBuilder() => new MapConstantBuilder(
+      original, const DynamicType(), const DynamicType(), evaluator);
+
+  /// Add a map entry (which is possibly a spread or an if map entry) to the
+  /// constant map being built by this builder
+  void add(MapEntry element) {
+    if (element is SpreadMapEntry) {
+      addSpread(element.expression, isNullAware: element.isNullAware);
+    } else if (element is IfMapEntry) {
+      Constant condition = evaluator._evaluateSubexpression(element.condition);
+      if (evaluator.shouldBeUnevaluated) {
+        // Unevaluated if
+        evaluator.enterLazy();
+        Constant then = (newTempBuilder()..add(element.then)).build();
+        Constant otherwise;
+        if (element.otherwise != null) {
+          otherwise = (newTempBuilder()..add(element.otherwise)).build();
+        } else {
+          otherwise =
+              new MapConstant(const DynamicType(), const DynamicType(), []);
+        }
+        evaluator.leaveLazy();
+        parts.add(evaluator.unevaluated(
+            element.condition,
+            new ConditionalExpression(
+                evaluator.extract(condition),
+                evaluator.extract(then),
+                evaluator.extract(otherwise),
+                const DynamicType())));
+      } else {
+        // Fully evaluated if
+        if (condition == evaluator.trueConstant) {
+          add(element.then);
+        } else if (condition == evaluator.falseConstant) {
+          if (element.otherwise != null) {
+            add(element.otherwise);
+          }
+        } else if (condition == evaluator.nullConstant) {
+          evaluator.report(element.condition, messageConstEvalNullValue);
+        } else {
+          evaluator.report(
+              element.condition,
+              templateConstEvalInvalidType.withArguments(
+                  condition,
+                  evaluator.typeEnvironment.boolType,
+                  condition.getType(evaluator.typeEnvironment)));
+        }
+      }
+    } else if (element is ForMapEntry || element is ForInMapEntry) {
+      // For or for-in
+      evaluator.report(element, messageConstEvalIterationInConstMap);
+    } else {
+      // Ordinary map entry
+      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, {bool isNullAware}) {
+    Constant spread =
+        evaluator.unlower(evaluator._evaluateSubexpression(spreadExpression));
+    if (evaluator.shouldBeUnevaluated) {
+      // Unevaluated spread
+      if (isNullAware) {
+        VariableDeclaration temp = new VariableDeclaration(null,
+            initializer: evaluator.extract(spread));
+        parts.add(evaluator.unevaluated(
+            spreadExpression,
+            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 == evaluator.nullConstant) {
+      // Null spread
+      if (!isNullAware) {
+        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..d50ce8d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/constant_evaluator.dart
@@ -78,6 +78,8 @@
         IfMapEntry,
         SpreadMapEntry;
 
+part 'constant_collection_builders.dart';
+
 Component transformComponent(Component component, ConstantsBackend backend,
     Map<String, String> environmentDefines, ErrorReporter errorReporter,
     {bool keepFields: true,
@@ -765,220 +767,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, isNullAware: false);
     }
-    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 +794,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_, isNullAware: false);
     }
-    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 +816,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, isNullAware: false);
     }
-    return makeMapConstantFromParts(parts, node, node.keyType, node.valueType);
+    return builder.build();
   }
 
   visitFunctionExpression(FunctionExpression node) {
@@ -2092,7 +1751,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 +1795,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/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_library_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_library_builder.dart
index eac2a4a..c1d8ca8 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
@@ -1382,7 +1382,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);
             }
         }
       }
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..4dd4cca 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -651,10 +651,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 {
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/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..bb60229 100644
--- a/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/forwarding_listener.dart
@@ -172,10 +172,10 @@
   }
 
   @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
@@ -412,8 +412,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
@@ -567,10 +568,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
@@ -846,10 +847,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
@@ -1142,11 +1149,6 @@
   }
 
   @override
-  void handleLanguageVersion(Token commentToken, int major, int minor) {
-    listener?.handleLanguageVersion(commentToken, major, minor);
-  }
-
-  @override
   void handleLiteralBool(Token token) {
     listener?.handleLiteralBool(token);
   }
@@ -1471,6 +1473,11 @@
   }
 
   @override
+  void reportNonNullableModifierError(Token modifierToken) {
+    listener?.reportNonNullableModifierError(modifierToken);
+  }
+
+  @override
   set suppressParseErrors(bool value) {
     listener?.suppressParseErrors = value;
   }
diff --git a/pkg/front_end/lib/src/fasta/parser/listener.dart b/pkg/front_end/lib/src/fasta/parser/listener.dart
index 9cc581a..5239ab9 100644
--- a/pkg/front_end/lib/src/fasta/parser/listener.dart
+++ b/pkg/front_end/lib/src/fasta/parser/listener.dart
@@ -272,8 +272,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 +298,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 +901,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 +974,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 +1067,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");
@@ -1405,15 +1423,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..0c49fb1 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';
     }
@@ -274,7 +273,9 @@
       if (varToken != null) {
         parser.reportRecoverableError(next, fasta.messageCovariantAfterVar);
       } 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 {
@@ -307,6 +308,8 @@
         parser.reportRecoverableError(next, fasta.messageExternalAfterConst);
       } else if (staticToken != null) {
         parser.reportRecoverableError(next, fasta.messageExternalAfterStatic);
+      } 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));
@@ -353,6 +404,8 @@
         parser.reportRecoverableError(next, fasta.messageStaticAfterFinal);
       } else if (varToken != null) {
         parser.reportRecoverableError(next, fasta.messageStaticAfterVar);
+      } 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..51b32e6 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,
@@ -341,7 +338,6 @@
       directiveState?.checkScriptTag(this, token.next);
       token = parseScript(token);
     }
-    parseLanguageVersionOpt(token);
     while (!token.next.isEof) {
       final Token start = token.next;
       token = parseTopLevelDeclarationImpl(token, directiveState);
@@ -368,74 +364,6 @@
     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 +463,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.
@@ -1379,42 +1308,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;
@@ -2179,6 +2126,7 @@
     listener.beginTopLevelMember(next);
 
     Token externalToken;
+    Token lateToken;
     Token varFinalOrConst;
 
     if (isModifier(next)) {
@@ -2196,6 +2144,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 +2161,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;
           }
         }
@@ -2304,6 +2264,9 @@
           reportRecoverableErrorWithToken(
               varFinalOrConst, fasta.templateExtraneousModifier);
         }
+      } else if (lateToken != null) {
+        reportRecoverableErrorWithToken(
+            lateToken, fasta.templateExtraneousModifier);
       }
       return parseTopLevelMethod(beforeStart, externalToken, beforeType,
           typeInfo, getOrSet, token.next);
@@ -2313,8 +2276,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 +2285,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
@@ -2337,7 +2301,7 @@
       }
     }
     if (typeInfo == noType) {
-      if (varFinalOrConst == null) {
+      if (varFinalOrConst == null && lateToken == null) {
         reportRecoverableError(name, fasta.messageMissingConstFinalVarOrType);
       }
     } else {
@@ -2355,19 +2319,21 @@
     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);
+      listener.endTopLevelFields(staticToken, covariantToken, lateToken,
+          varFinalOrConst, fieldCount, beforeStart.next, token);
     } else {
-      listener.endFields(staticToken, covariantToken, varFinalOrConst,
-          fieldCount, beforeStart.next, token);
+      listener.endFields(staticToken, covariantToken, lateToken,
+          varFinalOrConst, fieldCount, beforeStart.next, token);
     }
     return token;
   }
@@ -2422,8 +2388,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 +2403,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
@@ -2882,6 +2850,7 @@
 
     Token covariantToken;
     Token externalToken;
+    Token lateToken;
     Token staticToken;
     Token varFinalOrConst;
 
@@ -2909,18 +2878,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 +2948,7 @@
               externalToken,
               staticToken,
               covariantToken,
+              lateToken,
               varFinalOrConst,
               beforeType,
               typeInfo,
@@ -2982,8 +2962,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 +2977,7 @@
               externalToken,
               staticToken,
               covariantToken,
+              lateToken,
               varFinalOrConst,
               beforeType,
               typeInfo,
@@ -3011,6 +2998,7 @@
             externalToken,
             staticToken,
             covariantToken,
+            lateToken,
             varFinalOrConst,
             beforeType,
             typeInfo,
@@ -3024,8 +3012,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 +3038,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -3059,6 +3054,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -3074,11 +3070,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 +3185,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) {
@@ -3622,7 +3626,8 @@
       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, '{')) {
@@ -3631,12 +3636,18 @@
       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)) {
@@ -5052,7 +5063,7 @@
         }
       }
       return parseExpressionStatementOrDeclarationAfterModifiers(
-          constToken, start, constToken, typeInfo);
+          constToken, start, null, constToken, typeInfo, false);
     }
     return parseExpressionStatementOrDeclaration(start);
   }
@@ -5078,50 +5089,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 +5242,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 +5258,7 @@
     }
     token = typeInfo.parseType(beforeType, this);
     next = token.next;
-    listener.beginVariablesDeclaration(next, varFinalOrConst);
+    listener.beginVariablesDeclaration(next, lateToken, varFinalOrConst);
     if (!onlyParseVariableDeclarationStart) {
       token = parseVariablesDeclarationRest(token, true);
     }
@@ -6118,6 +6150,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType) {
     TypeInfo typeInfo = computeType(beforeType, true, true);
@@ -6142,6 +6175,7 @@
         externalToken,
         staticToken,
         covariantToken,
+        lateToken,
         varFinalOrConst,
         beforeType,
         typeInfo,
@@ -6160,6 +6194,7 @@
       Token externalToken,
       Token staticToken,
       Token covariantToken,
+      Token lateToken,
       Token varFinalOrConst,
       Token beforeType,
       TypeInfo typeInfo,
@@ -6175,7 +6210,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 +6222,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
@@ -6206,6 +6242,7 @@
           externalToken,
           staticToken,
           covariantToken,
+          lateToken,
           varFinalOrConst,
           beforeType,
           typeInfo,
diff --git a/pkg/front_end/lib/src/fasta/scanner.dart b/pkg/front_end/lib/src/fasta/scanner.dart
index 8f8e495..db6a662 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;
 
+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();
 }
 
@@ -58,30 +70,32 @@
 /// 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,
+    Recover recover}) {
   if (bytes.last != 0) {
     throw new ArgumentError("[bytes]: the last byte must be null.");
   }
-  Scanner scanner =
-      new Utf8BytesScanner(bytes, includeComments: includeComments);
+  Scanner scanner = new Utf8BytesScanner(bytes,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
   return _tokenizeAndRecover(scanner, recover, 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,
+    LanguageVersionChanged languageVersionChanged,
     Recover recover}) {
-  // TODO(brianwilkerson): Remove the parameter `enableGtGtGt` after the feature
-  // has been anabled by default.
   assert(source != null, 'source must not be null');
-  StringScanner scanner =
-      new StringScanner(source, includeComments: includeComments);
-  scanner.enableGtGtGt = enableGtGtGt;
-  scanner.enableGtGtGtEq = enableGtGtGtEq;
+  StringScanner scanner = new StringScanner(source,
+      configuration: configuration,
+      includeComments: includeComments,
+      languageVersionChanged: languageVersionChanged);
   return _tokenizeAndRecover(scanner, recover, source: source);
 }
 
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..637bbc1 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,19 @@
 
   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 `>>>`.
   /// See https://github.com/dart-lang/language/issues/61
   /// and https://github.com/dart-lang/language/issues/60
-  bool enableGtGtGt = false;
+  bool _enableTripleShift = 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;
+  /// Experimental flag for enabling scanning of NNBD tokens
+  /// such as 'required' and 'late'.
+  bool _enableNonNullable = false;
 
   /**
    * The string offset for the next token that will be created.
@@ -90,9 +97,20 @@
 
   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) {
+      _enableNonNullable = config.enableNonNullable;
+      _enableTripleShift = config.enableTripleShift;
+    }
   }
 
   /**
@@ -249,6 +267,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 +286,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 +317,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 +708,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 +886,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 +1003,7 @@
         }
         return next;
       }
+      next = advance();
     }
   }
 
@@ -983,6 +1135,10 @@
     if (state == null || state.keyword == null) {
       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 +1526,25 @@
     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 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 enableTripleShift,
+    bool enableNonNullable,
+  })  : this.enableTripleShift = enableTripleShift ?? false,
+        this.enableNonNullable = enableNonNullable ?? 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/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..1125c14 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);
   }
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..24d3a08 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -1017,8 +1017,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));
   }
@@ -1287,9 +1289,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) {
     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) |
@@ -1304,9 +1314,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) |
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..e2a7840 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
@@ -202,9 +202,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);
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..ede5fec 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
@@ -618,7 +618,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 +649,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 +663,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(
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..6c48edf 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);
@@ -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/scanner/token.dart b/pkg/front_end/lib/src/scanner/token.dart
index 62718b0..0ffd35b 100644
--- a/pkg/front_end/lib/src/scanner/token.dart
+++ b/pkg/front_end/lib/src/scanner/token.dart
@@ -211,6 +211,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 +238,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");
@@ -313,6 +318,7 @@
     IN,
     INTERFACE,
     IS,
+    LATE,
     LIBRARY,
     MIXIN,
     NATIVE,
@@ -323,6 +329,7 @@
     OPERATOR,
     PART,
     PATCH,
+    REQUIRED,
     RETHROW,
     RETURN,
     SET,
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 844ba61..0229457 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -42,6 +42,7 @@
 CantUseSuperBoundedTypeForInstanceCreation/analyzerCode: Fail
 CantUseSuperBoundedTypeForInstanceCreation/example: Fail
 ColonInPlaceOfIn/example: Fail
+ConflictingModifiers/script1: Fail
 ConflictsWithConstructor/example: Fail
 ConflictsWithFactory/analyzerCode: Fail
 ConflictsWithFactory/example: Fail
@@ -50,10 +51,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,7 +101,6 @@
 ContinueWithoutLabelInCase/script1: Fail
 CouldNotParseUri/analyzerCode: Fail
 CouldNotParseUri/example: Fail
-CovariantAfterFinal/script1: Fail
 CovariantAfterVar/script1: Fail
 CovariantAndStatic/script1: Fail
 CovariantAndStatic/script2: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index bc98cf9..53c901f 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -574,15 +574,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 +585,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; }"
@@ -641,7 +632,7 @@
     - "class C { factory const C() = prefix.B.foo; }"
 
 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,14 +654,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'."
@@ -2576,7 +2559,7 @@
   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
 
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/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/type_info_test.dart b/pkg/front_end/test/fasta/parser/type_info_test.dart
index 5c37a69..b100668 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,12 @@
   });
 }
 
-/// 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);
-}
+        {bool includeComments: false, Recover recover}) =>
+    scanner.scanString(source,
+        configuration: const ScannerConfiguration(enableTripleShift: true),
+        includeComments: includeComments,
+        recover: recover);
 
 @reflectiveTest
 class NoTypeInfoTest {
@@ -2768,8 +2743,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/incremental_load_from_dill_test.dart b/pkg/front_end/test/incremental_load_from_dill_test.dart
index 16125c3..b5cffb2 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,8 +302,6 @@
       for (Component c in moduleComponents.values) {
         c.adoptChildren();
       }
-      sdk.unbindCanonicalNames();
-      sdk.computeCanonicalNames();
 
       modulesToUse = new List<Component>();
       for (String moduleName in world["modules"]) {
@@ -310,7 +316,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 +441,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 +467,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 +568,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 +601,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 +909,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 +922,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/scanner_fasta_test.dart b/pkg/front_end/test/scanner_fasta_test.dart
index 4345dd7..6af6e46 100644
--- a/pkg/front_end/test/scanner_fasta_test.dart
+++ b/pkg/front_end/test/scanner_fasta_test.dart
@@ -85,8 +85,7 @@
 @reflectiveTest
 class ScannerTest_Fasta extends ScannerTestBase {
   @override
-  Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false}) {
+  Token scanWithListener(String source, ErrorListener listener) {
     var result = scanString(source, includeComments: true);
     var token = result.tokens;
 
@@ -717,15 +716,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 +754,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 +935,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..25ad95f 100644
--- a/pkg/front_end/test/scanner_replacement_test.dart
+++ b/pkg/front_end/test/scanner_replacement_test.dart
@@ -32,15 +32,12 @@
 @reflectiveTest
 class ScannerTest_Replacement extends ScannerTestBase {
   @override
-  analyzer.Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false}) {
+  analyzer.Token scanWithListener(String source, ErrorListener listener) {
     // 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,
+    fasta.ScannerResult result = fasta.scanString(source, includeComments: true,
         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
@@ -200,10 +197,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;
   }
diff --git a/pkg/front_end/test/scanner_test.dart b/pkg/front_end/test/scanner_test.dart
index 3a0bf75..36b1477 100644
--- a/pkg/front_end/test/scanner_test.dart
+++ b/pkg/front_end/test/scanner_test.dart
@@ -79,8 +79,7 @@
 }
 
 abstract class ScannerTestBase {
-  Token scanWithListener(String source, ErrorListener listener,
-      {bool lazyAssignmentOperators: false});
+  Token scanWithListener(String source, ErrorListener listener);
 
   void test_ampersand() {
     _assertToken(TokenType.AMPERSAND, "&");
@@ -92,8 +91,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 +150,7 @@
 
   void test_bar_bar_eq() {
     if (AbstractScanner.LAZY_ASSIGNMENT_ENABLED) {
-      _assertToken(TokenType.BAR_BAR_EQ, "||=", lazyAssignmentOperators: true);
+      _assertToken(TokenType.BAR_BAR_EQ, "||=");
     }
   }
 
@@ -1326,11 +1324,9 @@
    * 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 +1338,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 +1347,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);
@@ -1407,11 +1399,9 @@
     expect(token.type, TokenType.EOF);
   }
 
-  Token _scan(String source,
-      {bool lazyAssignmentOperators: false, bool ignoreErrors: false}) {
+  Token _scan(String source, {bool ignoreErrors: false}) {
     ErrorListener listener = new ErrorListener();
-    Token token = scanWithListener(source, listener,
-        lazyAssignmentOperators: lazyAssignmentOperators);
+    Token token = scanWithListener(source, listener);
     if (!ignoreErrors) {
       listener.assertNoErrors();
     }
diff --git a/pkg/front_end/test/token_test.dart b/pkg/front_end/test/token_test.dart
index 686c789..fb9f1ae 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';
@@ -100,6 +101,7 @@
       Keyword.MIXIN,
       Keyword.OPERATOR,
       Keyword.PART,
+      Keyword.REQUIRED,
       Keyword.SET,
       Keyword.STATIC,
       Keyword.TYPEDEF,
@@ -117,12 +119,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) {
@@ -153,6 +159,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/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/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/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/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/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/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..9199ba0
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.expect
@@ -0,0 +1,72 @@
+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:11: Error: Expected a class or mixin body, but got 'xx'.
+// 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..9199ba0
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.legacy.transformed.expect
@@ -0,0 +1,72 @@
+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:11: Error: Expected a class or mixin body, but got 'xx'.
+// 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..0a38be0
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.outline.expect
@@ -0,0 +1,67 @@
+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:11: Error: Expected a class or mixin body, but got 'xx'.
+// 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..2e470e5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.expect
@@ -0,0 +1,72 @@
+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:11: Error: Expected a class or mixin body, but got 'xx'.
+// 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..2e470e5
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36647.dart.strong.transformed.expect
@@ -0,0 +1,72 @@
+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:11: Error: Expected a class or mixin body, but got 'xx'.
+// 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..4735cfe
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.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;
+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..4735cfe
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.legacy.transformed.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;
+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..659526a
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.outline.expect
@@ -0,0 +1,18 @@
+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;
+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..4735cfe
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.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;
+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..4735cfe
--- /dev/null
+++ b/pkg/front_end/testcases/regress/issue_36793.dart.strong.transformed.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;
+static field core::int x;
+static method main() → dynamic {
+  core::print(self::y);
+}
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..25584dc 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -752,7 +752,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 +792,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 +920,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_36793: TextSerializationFailure
+regress/issue_36669: 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 +1008,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/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/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..5d366a5 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -6022,8 +6022,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 +6050,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..31c621d 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -76,14 +76,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,
@@ -803,6 +808,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 +931,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 +979,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 +1054,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 +1096,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 +1145,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 +1207,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/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/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/io_pipeline.dart b/pkg/modular_test/lib/src/io_pipeline.dart
new file mode 100644
index 0000000..acc6144
--- /dev/null
+++ b/pkg/modular_test/lib/src/io_pipeline.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.
+
+/// 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);
+}
+
+class IOPipeline extends Pipeline<IOModularStep> {
+  /// A folder per step. The key is the data id produced by a specific step.
+  ///
+  /// This contains internal state used during the run of the pipeline, but is
+  /// expected to be null before and after the pipeline is executed.
+  Map<DataId, Uri> _tmpFolders;
+  Map<DataId, Uri> get tmpFoldersForTesting => _tmpFolders;
+  bool saveFoldersForTesting;
+
+  IOPipeline(List<ModularStep> steps, {this.saveFoldersForTesting: false})
+      : super(steps);
+
+  @override
+  Future<void> run(ModularTest test) async {
+    assert(_tmpFolders == null);
+    _tmpFolders = {};
+    await super.run(test);
+    if (!saveFoldersForTesting) {
+      for (var folder in _tmpFolders.values) {
+        await Directory.fromUri(folder).delete(recursive: true);
+      }
+      _tmpFolders = null;
+    }
+  }
+
+  @override
+  Future<void> runStep(IOModularStep step, Module module,
+      Map<Module, Set<DataId>> visibleData) async {
+    var folder =
+        await Directory.systemTemp.createTemp('modular_test_${step.resultId}-');
+    _tmpFolders[step.resultId] ??= (await Directory.systemTemp
+            .createTemp('modular_test_${step.resultId}_res-'))
+        .uri;
+    for (var module in visibleData.keys) {
+      for (var dataId in visibleData[module]) {
+        var filename = "${module.name}.${dataId.name}";
+        var assetUri = _tmpFolders[dataId].resolve(filename);
+        await File.fromUri(assetUri)
+            .copy(folder.uri.resolve(filename).toFilePath());
+      }
+    }
+    if (step.needsSources) {
+      for (var uri in module.sources) {
+        var originalUri = module.rootUri.resolveUri(uri);
+        await File.fromUri(originalUri)
+            .copy(folder.uri.resolveUri(uri).toFilePath());
+      }
+    }
+
+    await step.execute(module, folder.uri,
+        (Module m, DataId id) => Uri.parse("${m.name}.${id.name}"));
+
+    var outputFile = File.fromUri(
+        folder.uri.resolve("${module.name}.${step.resultId.name}"));
+    if (!await outputFile.exists()) {
+      throw StateError(
+          "Step '${step.runtimeType}' didn't produce an output file");
+    }
+    await outputFile.copy(_tmpFolders[step.resultId]
+        .resolve("${module.name}.${step.resultId.name}")
+        .toFilePath());
+    await folder.delete(recursive: true);
+  }
+}
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..4f1740a
--- /dev/null
+++ b/pkg/modular_test/lib/src/memory_pipeline.dart
@@ -0,0 +1,62 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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<Object> execute(Module module, SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider);
+}
+
+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;
+
+  MemoryPipeline(this._sources, List<ModularStep> steps) : super(steps);
+
+  @override
+  Future<void> run(ModularTest test) async {
+    assert(_results == null);
+    _results = {};
+    await super.run(test);
+    resultsForTesting = _results;
+    _results = null;
+  }
+
+  @override
+  Future<void> runStep(MemoryModularStep step, Module module,
+      Map<Module, Set<DataId>> visibleData) async {
+    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];
+      });
+    }
+    Object result = await step.execute(module, (Uri uri) => inputSources[uri],
+        (Module m, DataId id) => inputData[m][id]);
+    (_results[module] ??= {})[step.resultId] = result;
+  }
+}
diff --git a/pkg/modular_test/lib/src/pipeline.dart b/pkg/modular_test/lib/src/pipeline.dart
new file mode 100644
index 0000000..4bb3e89
--- /dev/null
+++ b/pkg/modular_test/lib/src/pipeline.dart
@@ -0,0 +1,153 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 [resultId], 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 [resultId] in this list.
+  final List<DataId> moduleDataNeeded;
+
+  /// Data that this step produces.
+  final DataId resultId;
+
+  ModularStep(
+      {this.needsSources: true,
+      this.dependencyDataNeeded: const [],
+      this.moduleDataNeeded: const [],
+      this.resultId});
+}
+
+/// 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> {
+  final List<S> steps;
+
+  Pipeline(this.steps) {
+    _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) {
+      var resultKind = step.resultId;
+      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, {});
+    }
+  }
+
+  Future<void> _recursiveRun(S step, Module module,
+      Map<Module, Set<DataId>> computedData, Set<Module> seen) async {
+    if (!seen.add(module)) return;
+    for (var dependency in module.dependencies) {
+      await _recursiveRun(step, dependency, computedData, seen);
+    }
+    // Include only requested data from transitive dependencies.
+    Map<Module, Set<DataId>> visibleData = {};
+
+    // TODO(sigmund): consider excluding parent modules here. In particular,
+    // [seen] not only contains transitive dependencies, but also this module
+    // and parent modules. Technically we haven't computed any data for those,
+    // so we shouldn't be including any entries for parent modules in
+    // [visibleData].
+    seen.forEach((dep) {
+      if (dep == module) return;
+      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);
+    (computedData[module] ??= {}).add(step.resultId);
+  }
+
+  Future<void> runStep(
+      S step, Module module, Map<Module, Set<DataId>> visibleData);
+}
+
+class InvalidPipelineError extends Error {
+  final String message;
+  InvalidPipelineError(this.message);
+  String toString() => "Invalid pipeline: $message";
+}
diff --git a/pkg/modular_test/lib/src/suite.dart b/pkg/modular_test/lib/src/suite.dart
new file mode 100644
index 0000000..bba158e
--- /dev/null
+++ b/pkg/modular_test/lib/src/suite.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.
+
+/// 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;
+
+  ModularTest(this.modules, this.mainModule)
+      : assert(mainModule != null && modules.length > 0);
+}
+
+/// 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;
+
+  Module(this.name, this.dependencies, this.rootUri, this.sources,
+      this.mainSource) {
+    if (!_validModuleName.hasMatch(name)) {
+      throw "invalid module name: $name";
+    }
+  }
+
+  @override
+  String toString() => '[module $name]';
+}
+
+final RegExp _validModuleName = new RegExp(r'^[a-zA-Z_][a-zA-Z0-9_]*$');
diff --git a/pkg/modular_test/pubspec.yaml b/pkg/modular_test/pubspec.yaml
new file mode 100644
index 0000000..94f26d8
--- /dev/null
+++ b/pkg/modular_test/pubspec.yaml
@@ -0,0 +1,14 @@
+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:
+  yaml: ^2.1.15
+
+dev_dependencies:
+  test: any
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..bc80082
--- /dev/null
+++ b/pkg/modular_test/test/io_pipeline_test.dart
@@ -0,0 +1,163 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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) 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, saveFoldersForTesting: true);
+  }
+
+  @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
+  String getResult(covariant IOPipeline pipeline, Module m, DataId dataId) {
+    var folderUri = pipeline.tmpFoldersForTesting[dataId];
+    return File.fromUri(folderUri.resolve("${m.name}.${dataId.name}"))
+        .readAsStringSync();
+  }
+
+  @override
+  Future<void> cleanup(Pipeline<IOModularStep> pipeline) async {
+    var folders = (pipeline as IOPipeline).tmpFoldersForTesting.values;
+    for (var folder in folders) {
+      await Directory.fromUri(folder).delete(recursive: true);
+    }
+    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 [];
+
+  SourceOnlyStep(this.action, this.resultId, this.needsSources);
+
+  @override
+  Future<void> execute(
+      Module module, Uri root, ModuleDataToRelativeUri toUri) 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));
+  }
+}
+
+class ModuleDataStep implements IOModularStep {
+  final String Function(String) action;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  final List<DataId> moduleDataNeeded;
+  final DataId resultId;
+  final DataId inputId;
+
+  ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
+      : moduleDataNeeded = requestInput ? [inputId] : [];
+
+  @override
+  Future<void> execute(
+      Module module, Uri root, ModuleDataToRelativeUri toUri) 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);
+  }
+}
+
+class LinkStep implements IOModularStep {
+  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;
+
+  LinkStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  @override
+  Future<void> execute(
+      Module module, Uri root, ModuleDataToRelativeUri toUri) 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));
+  }
+}
+
+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/memory_pipeline_test.dart b/pkg/modular_test/test/memory_pipeline_test.dart
new file mode 100644
index 0000000..2e35a940
--- /dev/null
+++ b/pkg/modular_test/test/memory_pipeline_test.dart
@@ -0,0 +1,120 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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) {
+    return new MemoryPipeline(sources, steps);
+  }
+
+  @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
+  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 [];
+
+  SourceOnlyStep(this.action, this.resultId, this.needsSources);
+
+  Future<Object> execute(Module module, SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider) {
+    Map<Uri, String> sources = {};
+    for (var uri in module.sources) {
+      sources[uri] = sourceProvider(module.rootUri.resolveUri(uri));
+    }
+    return Future.value(action(sources));
+  }
+}
+
+class ModuleDataStep implements MemoryModularStep {
+  final String Function(String) action;
+  bool get needsSources => false;
+  List<DataId> get dependencyDataNeeded => const [];
+  final List<DataId> moduleDataNeeded;
+  final DataId resultId;
+  final DataId inputId;
+
+  ModuleDataStep(this.action, this.inputId, this.resultId, bool requestInput)
+      : moduleDataNeeded = requestInput ? [inputId] : [];
+
+  Future<Object> execute(Module module, SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider) {
+    var inputData = dataProvider(module, inputId) as String;
+    if (inputData == null) return Future.value("data for $module was null");
+    return Future.value(action(inputData));
+  }
+}
+
+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;
+
+  LinkStep(this.action, this.inputId, this.depId, this.resultId,
+      bool requestDependencies)
+      : dependencyDataNeeded = requestDependencies ? [depId] : [];
+
+  Future<Object> execute(Module module, SourceProvider sourceProvider,
+      ModuleDataProvider dataProvider) {
+    List<String> depsData = module.dependencies
+        .map((d) => dataProvider(d, depId) as String)
+        .toList();
+    var inputData = dataProvider(module, inputId) as String;
+    return Future.value(action(inputData, depsData));
+  }
+}
diff --git a/pkg/modular_test/test/pipeline_common.dart b/pkg/modular_test/test/pipeline_common.dart
new file mode 100644
index 0000000..a01da5c
--- /dev/null
+++ b/pkg/modular_test/test/pipeline_common.dart
@@ -0,0 +1,254 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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);
+
+  /// 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});
+
+  /// 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',
+  };
+
+  var m1 = Module("a", const [], testStrategy.testRootUri,
+      [Uri.parse("a1.dart"), Uri.parse("a2.dart")], null);
+  var m2 = Module("b", [m1], testStrategy.testRootUri.resolve('b/'),
+      [Uri.parse("b1.dart"), Uri.parse("b2.dart")], null);
+
+  var singleModuleInput = ModularTest([m1], m1);
+  var multipleModulesInput = ModularTest([m1, m2], m2);
+
+  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, concatStep.resultId),
+        "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, concatStep.resultId),
+        "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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, concatStep.resultId),
+        "a1.dart: A1\na2.dart: A2\n");
+    expect(testStrategy.getResult(pipeline, m2, concatStep.resultId),
+        "b1.dart: B1\nb2.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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, lowercaseStep.resultId),
+        "a1.dart: a1\na2.dart: a2\n");
+    expect(testStrategy.getResult(pipeline, m2, lowercaseStep.resultId),
+        "b1.dart: b1\nb2.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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, lowercaseStep.resultId),
+        "data for [module a] was null");
+    expect(testStrategy.getResult(pipeline, m2, lowercaseStep.resultId),
+        "data for [module b] was null");
+    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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
+        "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+        "a1 a1\na2 a2\n\nb1 b1\nb2 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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
+        "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+        "null\nb1 b1\nb2 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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
+        "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+        "a1.dart: a1\na2.dart: a2\n\nb1 b1\nb2 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(multipleModulesInput);
+    expect(testStrategy.getResult(pipeline, m1, replaceJoinStep.resultId),
+        "a1 a1\na2 a2\n");
+    expect(testStrategy.getResult(pipeline, m2, replaceJoinStep.resultId),
+        "null\nb1 b1\nb2 b2\n");
+    await testStrategy.cleanup(pipeline);
+  });
+}
+
+DataId _concatId = const DataId("concat");
+DataId _lowercaseId = const DataId("lowercase");
+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 _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/validate_test.dart b/pkg/modular_test/test/validate_test.dart
new file mode 100644
index 0000000..152271a
--- /dev/null
+++ b/pkg/modular_test/test/validate_test.dart
@@ -0,0 +1,79 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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], resultId: id1),
+      ModularStep(moduleDataNeeded: [id1], resultId: id2),
+      ModularStep(
+          moduleDataNeeded: [id2],
+          dependencyDataNeeded: [id1, id3],
+          resultId: id3),
+    ]);
+  });
+
+  test('circular dependency is not allowed', () {
+    var id1 = DataId("data_a");
+    expect(
+        () => validateSteps([
+              ModularStep(moduleDataNeeded: [id1], resultId: id1),
+            ]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+
+  test('out of order dependencies are not allowed', () {
+    var id1 = DataId("data_a");
+    var id2 = DataId("data_b");
+    validateSteps([
+      ModularStep(resultId: id1), // id1 must be produced before it is consumed.
+      ModularStep(dependencyDataNeeded: [id1], resultId: id2),
+    ]);
+
+    expect(
+        () => validateSteps([
+              ModularStep(dependencyDataNeeded: [id1], resultId: id2),
+              ModularStep(resultId: id1),
+            ]),
+        throwsA(TypeMatcher<InvalidPipelineError>()));
+  });
+
+  test('same data cannot be produced by two steps', () {
+    var id1 = DataId("data_a");
+    expect(
+        () => validateSteps([
+              ModularStep(resultId: id1),
+              ModularStep(resultId: 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);
+
+  @override
+  Future<void> runStep(ModularStep step, Module module,
+          Map<Module, Set<DataId>> visibleData) =>
+      null;
+}
diff --git a/pkg/pkg.status b/pkg/pkg.status
index d26e5ee..5ad6e12 100644
--- a/pkg/pkg.status
+++ b/pkg/pkg.status
@@ -130,6 +130,7 @@
 [ $runtime != vm ]
 dev_compiler/test/options/*: SkipByDesign
 front_end/test/hot_reload_e2e_test: Skip
+modular_test/test/io_pipeline_test: SkipByDesign
 vm/test/*: SkipByDesign # Only meant to run on vm
 
 [ $system == linux ]
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/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index f8ae346..21721a6 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -57,10 +57,11 @@
   Map<String, String> environmentDefines: const <String, String>{},
   ErrorReporter errorReporter,
   List<Library> libraries,
+  ClassHierarchy hierarchy,
 }) {
   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);
diff --git a/pkg/vm/lib/frontend_server.dart b/pkg/vm/lib/frontend_server.dart
index 6685160..0d7c7af 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.'
@@ -351,7 +354,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..703cfa8 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -678,6 +678,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,6 +706,7 @@
             .toList();
         generateBytecode(component,
             libraries: libraries,
+            hierarchy: hierarchy,
             emitSourcePositions: emitBytecodeSourcePositions,
             emitAnnotations: emitBytecodeAnnotations,
             useFutureBytecodeFormat: useFutureBytecodeFormat,
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/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/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/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index fe17198..a71a37a 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -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);
@@ -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/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
index 1a25aa9..b122da6 100644
--- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -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/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 2a98dd2..b79b398 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -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=
@@ -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..bc4b45d 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -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::•()
       ;
@@ -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::•()
       ;
   }
@@ -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/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
index 4fcf451..3ff8087 100644
--- a/pkg/vm/testcases/bytecode/optional_params.dart.expect
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -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/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index adea1f5a..b7ca049 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -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..126eae9 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -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/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/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/bin/BUILD.gn b/runtime/bin/BUILD.gn
index a13c951..7c93362 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,17 +818,21 @@
 
 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" ]
@@ -829,17 +841,21 @@
 
 dart_executable("dart_precompiled_runtime_for_linking") {
   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" ]
@@ -850,15 +866,19 @@
 
 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 +937,6 @@
   if (dart_target_arch != "ia32") {
     configs += [ "..:dart_precompiler_config" ]
   }
-  if (is_fuchsia) {
-    configs -= [ "//build/config:symbol_visibility_hidden" ]
-  }
 
   deps = [
     ":crashpad",
@@ -927,7 +944,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 +960,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 +1114,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/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/dfe.cc b/runtime/bin/dfe.cc
index edf14c4..03ca32b 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;
   }
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..9f10a7e 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)
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..f9f25de 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"
 
@@ -1420,7 +1420,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.
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
index 1f07257..f1c418c 100644
--- a/runtime/bin/ffi_test_functions.cc
+++ b/runtime/bin/ffi_test_functions.cc
@@ -85,7 +85,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;
 }
@@ -467,7 +467,7 @@
 // truncated.
 DART_EXPORT void* LargePointer() {
   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.
@@ -504,7 +504,8 @@
 DART_EXPORT int RedirectStderr() {
   char filename[256];
   snprintf(filename, sizeof(filename), "/tmp/captured_stderr_%d", getpid());
-  freopen(filename, "w", stderr);
+  FILE* f = freopen(filename, "w", stderr);
+  ASSERT(f);
   printf("Got file %s\n", filename);
   return getpid();
 }
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..1f60fca 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);
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..af9741e 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)) {                                      \
@@ -152,7 +152,7 @@
 
 // clang-format off
 static void PrintUsage() {
-  Log::PrintErr(
+  Syslog::PrintErr(
 "Usage: gen_snapshot [<vm-flags>] [<options>] <dart-kernel-file>             \n"
 "                                                                            \n"
 "Common options:                                                             \n"
@@ -194,7 +194,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 +237,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 +251,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 +263,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 +277,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 +293,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 +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, "
@@ -317,7 +317,7 @@
     }
     case kAppAOTAssembly: {
       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;
@@ -326,7 +326,7 @@
     }
     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 +336,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 +354,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 +368,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 +378,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 +387,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);
@@ -479,7 +479,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 +491,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 +597,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);
@@ -629,10 +629,10 @@
     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);
@@ -732,7 +732,7 @@
   }
   if (isolate == NULL) {
     delete isolate_data;
-    Log::PrintErr("%s\n", error);
+    Syslog::PrintErr("%s\n", error);
     free(error);
     return kErrorExitCode;
   }
@@ -821,7 +821,7 @@
   DartUtils::SetEnvironment(environment);
 
   if (!Platform::Initialize()) {
-    Log::PrintErr("Initialization failed\n");
+    Syslog::PrintErr("Initialization failed\n");
     return kErrorExitCode;
   }
   Console::SaveConfig();
@@ -843,14 +843,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 +889,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 +901,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/loader.cc b/runtime/bin/loader.cc
index e335ca5..2993e91 100644
--- a/runtime/bin/loader.cc
+++ b/runtime/bin/loader.cc
@@ -292,7 +292,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/main.cc b/runtime/bin/main.cc
index 2d09c17..180cb3f 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" {
@@ -186,7 +186,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 +450,7 @@
   }
 
   if (isolate == NULL) {
-    Log::PrintErr("%s\n", *error);
+    Syslog::PrintErr("%s\n", *error);
     delete isolate_data;
     return NULL;
   }
@@ -698,7 +698,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 +812,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 +838,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 +978,7 @@
 
   // Perform platform specific initialization.
   if (!Platform::Initialize()) {
-    Log::PrintErr("Initialization failed\n");
+    Syslog::PrintErr("Initialization failed\n");
     Platform::Exit(kErrorExitCode);
   }
 
@@ -1018,7 +1019,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);
       }
@@ -1047,11 +1048,13 @@
 #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;
@@ -1076,9 +1079,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 +1092,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 +1145,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 +1157,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,7 +1165,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);
   }
   Process::ClearAllSignalHandlers();
diff --git a/runtime/bin/main_options.cc b/runtime/bin/main_options.cc
index 0826fa1..501b9c1 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;
@@ -444,7 +445,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 +454,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..da60ee0 100644
--- a/runtime/bin/namespace_fuchsia.cc
+++ b/runtime/bin/namespace_fuchsia.cc
@@ -45,7 +45,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));
     }
   }
 }
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 c26e462..1484749 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..88ebda7 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)) {
diff --git a/runtime/bin/process_linux.cc b/runtime/bin/process_linux.cc
index 93c7f6c..da0a75b 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_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_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..b2f6524 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)
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_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_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..f144ed4 100644
--- a/runtime/include/dart_api.h
+++ b/runtime/include/dart_api.h
@@ -976,6 +976,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.
  *
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/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..82a8262 100644
--- a/runtime/lib/ffi.cc
+++ b/runtime/lib/ffi.cc
@@ -42,9 +42,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);
@@ -594,7 +594,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();
 
   Class& native_function_class = Class::Handle(
       Isolate::Current()->class_table()->At(kFfiNativeFunctionCid));
diff --git a/runtime/lib/isolate.cc b/runtime/lib/isolate.cc
index 55c61f8..d666686 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?
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index 916649f..3bc2dc5 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);
   }
@@ -756,7 +756,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 +824,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 +1117,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 +1128,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 +1500,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 +1580,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 +1618,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/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/observatory/lib/src/elements/function_view.dart b/runtime/observatory/lib/src/elements/function_view.dart
index 6b73ba8..301d230 100644
--- a/runtime/observatory/lib/src/elements/function_view.dart
+++ b/runtime/observatory/lib/src/elements/function_view.dart
@@ -426,8 +426,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:
diff --git a/runtime/observatory/lib/src/elements/script_inset.dart b/runtime/observatory/lib/src/elements/script_inset.dart
index c386824..8d4bb5a 100644
--- a/runtime/observatory/lib/src/elements/script_inset.dart
+++ b/runtime/observatory/lib/src/elements/script_inset.dart
@@ -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);
diff --git a/runtime/observatory/lib/src/models/objects/function.dart b/runtime/observatory/lib/src/models/objects/function.dart
index 777f57d..68bd5ae 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,
diff --git a/runtime/observatory/lib/src/service/object.dart b/runtime/observatory/lib/src/service/object.dart
index 99e84be..a36dd23 100644
--- a/runtime/observatory/lib/src/service/object.dart
+++ b/runtime/observatory/lib/src/service/object.dart
@@ -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':
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/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/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/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/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/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/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/bin/log.h b/runtime/platform/syslog.h
similarity index 82%
rename from runtime/bin/log.h
rename to runtime/platform/syslog.h
index 022dd1b..d48c10b 100644
--- a/runtime/bin/log.h
+++ b/runtime/platform/syslog.h
@@ -2,17 +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.
 
-#ifndef RUNTIME_BIN_LOG_H_
-#define RUNTIME_BIN_LOG_H_
+#ifndef RUNTIME_PLATFORM_SYSLOG_H_
+#define RUNTIME_PLATFORM_SYSLOG_H_
 
 #include <stdarg.h>
 
 #include "platform/globals.h"
 
 namespace dart {
-namespace bin {
 
-class Log {
+class Syslog {
  public:
   // Print formatted output for debugging.
   static void Print(const char* format, ...) PRINTF_ATTRIBUTE(1, 2) {
@@ -35,10 +34,9 @@
 
  private:
   DISALLOW_ALLOCATION();
-  DISALLOW_IMPLICIT_CONSTRUCTORS(Log);
+  DISALLOW_IMPLICIT_CONSTRUCTORS(Syslog);
 };
 
-}  // namespace bin
 }  // namespace dart
 
-#endif  // RUNTIME_BIN_LOG_H_
+#endif  // RUNTIME_PLATFORM_SYSLOG_H_
diff --git a/runtime/bin/log_android.cc b/runtime/platform/syslog_android.cc
similarity index 86%
rename from runtime/bin/log_android.cc
rename to runtime/platform/syslog_android.cc
index 164db7f..9aa77c0 100644
--- a/runtime/bin/log_android.cc
+++ b/runtime/platform/syslog_android.cc
@@ -5,18 +5,17 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_ANDROID)
 
-#include "bin/log.h"
+#include "platform/syslog.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) {
+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.
@@ -25,7 +24,7 @@
   __android_log_vprint(ANDROID_LOG_INFO, "Dart", format, args);
 }
 
-void Log::VPrintErr(const char* format, va_list 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.
@@ -34,7 +33,6 @@
   __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/platform/syslog_fuchsia.cc
similarity index 74%
rename from runtime/bin/log_fuchsia.cc
rename to runtime/platform/syslog_fuchsia.cc
index f84fc49..85e4c80 100644
--- a/runtime/bin/log_fuchsia.cc
+++ b/runtime/platform/syslog_fuchsia.cc
@@ -5,24 +5,22 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_FUCHSIA)
 
-#include "bin/log.h"
+#include "platform/syslog.h"
 
 #include <stdio.h>  // NOLINT
 
 namespace dart {
-namespace bin {
 
-void Log::VPrint(const char* format, va_list args) {
+void Syslog::VPrint(const char* format, va_list args) {
   vfprintf(stdout, format, args);
   fflush(stdout);
 }
 
-void Log::VPrintErr(const char* format, va_list args) {
+void Syslog::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/platform/syslog_linux.cc
similarity index 74%
rename from runtime/bin/log_linux.cc
rename to runtime/platform/syslog_linux.cc
index 2844a17..269bc9f2 100644
--- a/runtime/bin/log_linux.cc
+++ b/runtime/platform/syslog_linux.cc
@@ -5,24 +5,22 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_LINUX)
 
-#include "bin/log.h"
+#include "platform/syslog.h"
 
 #include <stdio.h>  // NOLINT
 
 namespace dart {
-namespace bin {
 
-void Log::VPrint(const char* format, va_list args) {
+void Syslog::VPrint(const char* format, va_list args) {
   vfprintf(stdout, format, args);
   fflush(stdout);
 }
 
-void Log::VPrintErr(const char* format, va_list args) {
+void Syslog::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/platform/syslog_macos.cc
similarity index 74%
rename from runtime/bin/log_macos.cc
rename to runtime/platform/syslog_macos.cc
index 4044acf..f01bfbf 100644
--- a/runtime/bin/log_macos.cc
+++ b/runtime/platform/syslog_macos.cc
@@ -5,24 +5,22 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_MACOS)
 
-#include "bin/log.h"
+#include "platform/syslog.h"
 
 #include <stdio.h>  // NOLINT
 
 namespace dart {
-namespace bin {
 
-void Log::VPrint(const char* format, va_list args) {
+void Syslog::VPrint(const char* format, va_list args) {
   vfprintf(stdout, format, args);
   fflush(stdout);
 }
 
-void Log::VPrintErr(const char* format, va_list args) {
+void Syslog::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/platform/syslog_win.cc
similarity index 74%
rename from runtime/bin/log_win.cc
rename to runtime/platform/syslog_win.cc
index 650e47e..07ab815 100644
--- a/runtime/bin/log_win.cc
+++ b/runtime/platform/syslog_win.cc
@@ -5,24 +5,22 @@
 #include "platform/globals.h"
 #if defined(HOST_OS_WINDOWS)
 
-#include "bin/log.h"
+#include "platform/syslog.h"
 
 #include <stdio.h>  // NOLINT
 
 namespace dart {
-namespace bin {
 
-void Log::VPrint(const char* format, va_list args) {
+void Syslog::VPrint(const char* format, va_list args) {
   vfprintf(stdout, format, args);
   fflush(stdout);
 }
 
-void Log::VPrintErr(const char* format, va_list args) {
+void Syslog::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/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/vm/unicode.h b/runtime/platform/unicode.h
similarity index 86%
rename from runtime/vm/unicode.h
rename to runtime/platform/unicode.h
index d2050be..b784823 100644
--- a/runtime/vm/unicode.h
+++ b/runtime/platform/unicode.h
@@ -2,11 +2,11 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-#ifndef RUNTIME_VM_UNICODE_H_
-#define RUNTIME_VM_UNICODE_H_
+#ifndef RUNTIME_PLATFORM_UNICODE_H_
+#define RUNTIME_PLATFORM_UNICODE_H_
 
-#include "vm/allocation.h"
-#include "vm/globals.h"
+#include "platform/allocation.h"
+#include "platform/globals.h"
 
 namespace dart {
 
@@ -15,6 +15,7 @@
 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);
@@ -29,7 +30,7 @@
   }
 
   // Returns true if the code point value is above Plane 17.
-  static bool IsOutOfRange(intptr_t code_point) {
+  static bool IsOutOfRange(int32_t code_point) {
     return (code_point < 0) || (code_point > kMaxCodePoint);
   }
 };
@@ -152,6 +153,10 @@
   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));
@@ -187,11 +192,11 @@
 
   // The size of the stage 1 index.
   // TODO(cshapiro): improve indexing so this value is unnecessary.
-  static const int kStage1Size = 261;
+  static const intptr_t kStage1Size = 261;
 
   // The size of a stage 2 block in bytes.
-  static const int kBlockSizeLog2 = 8;
-  static const int kBlockSize = 1 << kBlockSizeLog2;
+  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)) {
@@ -222,6 +227,25 @@
   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_VM_UNICODE_H_
+#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/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/vm.status b/runtime/tests/vm/vm.status
index 195b548..79a253b 100644
--- a/runtime/tests/vm/vm.status
+++ b/runtime/tests/vm/vm.status
@@ -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.
 
-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.
@@ -18,7 +14,6 @@
 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.
@@ -28,10 +23,6 @@
 [ $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
@@ -115,7 +106,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.
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..e3b06fa 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.12';
 
-// 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.
@@ -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..599c9a9 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,10 +93,12 @@
 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 =
diff --git a/runtime/vm/benchmark_test.cc b/runtime/vm/benchmark_test.cc
index 10ddc29..265ca29 100644
--- a/runtime/vm/benchmark_test.cc
+++ b/runtime/vm/benchmark_test.cc
@@ -158,8 +158,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 +188,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;
@@ -652,13 +656,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 +679,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 +704,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 +738,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..34cfbc4 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)                                                    \
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..88858e7 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.
@@ -560,7 +560,7 @@
     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 +585,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
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index fd2bdc1..9404617 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -36,6 +36,7 @@
   intptr_t size_;
 
   friend class ClassTable;
+  friend class IsolateReloadContext;  // For VisitObjectPointers.
 };
 
 #if defined(ARCH_IS_32_BIT)
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 5f0accb..d30764c 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -601,7 +601,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);
@@ -3630,7 +3630,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 +3662,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 +4691,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 +5158,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_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/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index 58750f8..2355495 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 {
@@ -495,7 +495,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 +1080,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 +1947,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_);
           }
diff --git a/runtime/vm/compiler/assembler/assembler_arm.cc b/runtime/vm/compiler/assembler/assembler_arm.cc
index b3debf1..a232e37 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.cc
+++ b/runtime/vm/compiler/assembler/assembler_arm.cc
@@ -3165,8 +3165,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);
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..8794ba8 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32.cc
@@ -2262,6 +2262,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,
diff --git a/runtime/vm/compiler/assembler/assembler_ia32.h b/runtime/vm/compiler/assembler/assembler_ia32.h
index 91fa1c2..39086a3 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32.h
+++ b/runtime/vm/compiler/assembler/assembler_ia32.h
@@ -723,6 +723,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 +826,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..1ba6a08 100644
--- a/runtime/vm/compiler/assembler/assembler_ia32_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_ia32_test.cc
@@ -480,14 +480,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 +4669,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 +4681,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..300cf65 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64.cc
@@ -1732,19 +1732,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 +1749,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);
diff --git a/runtime/vm/compiler/assembler/assembler_x64_test.cc b/runtime/vm/compiler/assembler/assembler_x64_test.cc
index 9e380a4..e8d6883 100644
--- a/runtime/vm/compiler/assembler/assembler_x64_test.cc
+++ b/runtime/vm/compiler/assembler/assembler_x64_test.cc
@@ -1085,7 +1085,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 +1094,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 +5484,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 +5496,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/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index d27b6e2..acf4f9c 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -1272,8 +1272,8 @@
   }
 }
 
-void ConstantPropagator::VisitCaseInsensitiveCompareUC16(
-    CaseInsensitiveCompareUC16Instr* instr) {
+void ConstantPropagator::VisitCaseInsensitiveCompare(
+    CaseInsensitiveCompareInstr* instr) {
   SetValue(instr, non_constant_);
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 3b9481f..8872e8a 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -44,6 +44,17 @@
   return false;
 }
 
+// Returns true if instruction appears on def's use list.
+static bool IsInDefUseList(Definition* def, Instruction* instruction) {
+  for (Value* use = def->input_use_list(); use != nullptr;
+       use = use->next_use()) {
+    if (use->instruction() == instruction) {
+      return true;
+    }
+  }
+  return false;
+}
+
 // Returns true if instruction forces control flow.
 static bool IsControlFlow(Instruction* instruction) {
   return instruction->IsBranch() || instruction->IsGoto() ||
@@ -114,7 +125,11 @@
   // Visit phis in join.
   if (auto join_entry = block->AsJoinEntry()) {
     for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
-      VisitInstruction(it.Current());
+      PhiInstr* phi = it.Current();
+      // Make sure block lookup agrees.
+      ASSERT(phi->GetBlock() == join_entry);
+      // Visit phi as instruction.
+      VisitInstruction(phi);
     }
   }
   // Visit regular instructions.
@@ -146,6 +161,32 @@
 }
 
 void FlowGraphChecker::VisitInstruction(Instruction* instruction) {
+  // Make sure all inputs are properly defined by something that
+  // dominates the use that is not a Phi instruction (note that the
+  // proper dominance relation on the input values of Phis are checked
+  // by the Phi visitor below). Also verify some graph sanity.
+  for (intptr_t i = 0, n = instruction->InputCount(); i < n; ++i) {
+    Definition* def = instruction->InputAt(i)->definition();
+    bool test_def = def->HasSSATemp();
+    if (def->IsPhi()) {
+      // Phis are never linked into graph.
+      ASSERT(def->next() == nullptr);
+      ASSERT(def->previous() == nullptr);
+    } else if (def->IsConstant() || def->IsParameter() ||
+               def->IsSpecialParameter()) {
+      test_def = false;
+    } else {
+      ASSERT(def->next() != nullptr);
+      ASSERT(def->previous() != nullptr);
+    }
+    if (test_def) {
+      ASSERT(IsInDefUseList(def, instruction));  // proper def-use
+      ASSERT(instruction->IsPhi() ||
+             instruction->IsMaterializeObject() ||  // does not have dominance
+             instruction->IsDominatedBy(def));
+    }
+  }
+  // Visit specific instructions (definitions and anything with Visit()).
   if (auto def = instruction->AsDefinition()) {
     VisitDefinition(def);
   }
@@ -156,17 +197,32 @@
   // 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).
+  // Also verify some graph sanity.
   for (Value* use = def->input_use_list(); use != nullptr;
        use = use->next_use()) {
+    ASSERT(use->definition() == def);  // proper use-def
     Instruction* use_instr = use->instruction();
     ASSERT(use_instr != nullptr);
-    ASSERT(use_instr->IsPhi() ||
-           use_instr->IsMaterializeObject() ||  // not in graph
-           use_instr->IsDominatedBy(def));
+    if (use_instr->IsPhi()) {
+      ASSERT(use_instr->next() == nullptr);
+      ASSERT(use_instr->previous() == nullptr);
+      ASSERT(use_instr->GetBlock()->IsJoinEntry());
+    } else {
+      ASSERT(IsControlFlow(use_instr) || use_instr->next() != nullptr);
+      ASSERT(use_instr->previous() != nullptr);
+      ASSERT(use_instr->IsMaterializeObject() ||  // does not have dominance
+             use_instr->IsDominatedBy(def));
+    }
   }
 }
 
 void FlowGraphChecker::VisitConstant(ConstantInstr* constant) {
+  const Object& value = constant->value();
+  if (value.IsSmi()) {
+    const int64_t smi_value = Integer::Cast(value).AsInt64Value();
+    ASSERT(kSmiMin <= smi_value);
+    ASSERT(smi_value <= kSmiMax);
+  }
   // 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.
@@ -174,6 +230,7 @@
 }
 
 void FlowGraphChecker::VisitPhi(PhiInstr* phi) {
+  // Phis are never linked into graph.
   ASSERT(phi->next() == nullptr);
   ASSERT(phi->previous() == nullptr);
   // Make sure each incoming input value of a Phi is dominated
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 9e5377b..05a3d92 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -1191,8 +1191,16 @@
     // 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.
@@ -1207,8 +1215,13 @@
       }
       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)) {
@@ -1668,6 +1681,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 +1777,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 +1803,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 +1995,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;
 }
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index 56046747..7f5c1a3 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);
@@ -427,6 +470,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,
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 04a4a85..0252b7b 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -1054,6 +1054,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,6 +1068,8 @@
                                          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);
   __ Drop(ic_data.CountWithTypeArgs());
@@ -1309,13 +1313,11 @@
 }
 
 #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 (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ mov(destination.reg(), Operand(source.reg()));
@@ -1347,24 +1349,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 +1395,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();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 943aaec..0458549 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -1040,6 +1040,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,6 +1052,7 @@
                                          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);
   __ Drop(ic_data.CountWithTypeArgs());
@@ -1303,13 +1305,11 @@
 }
 
 #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 (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ mov(destination.reg(), source.reg());
@@ -1326,15 +1326,17 @@
       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 +1353,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 +1375,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_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index dfa2fc7..0336895 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -911,7 +911,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,6 +925,8 @@
                                          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);
   __ Drop(ic_data.CountWithTypeArgs());
@@ -1170,13 +1174,11 @@
 }
 
 #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 (source.IsRegister()) {
     if (destination.IsRegister()) {
       __ movl(destination.reg(), source.reg());
@@ -1189,8 +1191,10 @@
       __ movl(destination.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 +1204,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 +1215,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 +1261,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 +1276,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 +1327,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..91fe976 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -1046,6 +1046,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,6 +1060,8 @@
                                          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);
   __ Drop(ic_data.CountWithTypeArgs(), RCX);
@@ -1077,8 +1081,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 +1120,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 +1300,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 +1343,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 +1387,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 +1402,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..dee6cab 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1173,9 +1173,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();
 }
@@ -2635,6 +2632,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 +2727,16 @@
       if (call->is_known_list_constructor() &&
           IsFixedLengthArrayCid(call->Type()->ToCid())) {
         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,6 +2753,24 @@
         }
       }
     }
+  } 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 (slot().IsTypeArguments()) {
     Definition* array = instance()->definition()->OriginalDefinition();
     if (StaticCallInstr* call = array->AsStaticCall()) {
@@ -4051,8 +4100,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:
@@ -4265,7 +4314,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;
     }
@@ -5164,10 +5213,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);
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 3ce025c..5450f5f 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"
 
@@ -422,7 +423,7 @@
   M(Unbox, kNoGC)                                                              \
   M(BoxInt64, _)                                                               \
   M(UnboxInt64, kNoGC)                                                         \
-  M(CaseInsensitiveCompareUC16, _)                                             \
+  M(CaseInsensitiveCompare, _)                                                 \
   M(BinaryInt64Op, kNoGC)                                                      \
   M(ShiftInt64Op, kNoGC)                                                       \
   M(SpeculativeShiftInt64Op, kNoGC)                                            \
@@ -934,8 +935,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 +1378,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)
 
@@ -1835,12 +1835,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
@@ -4922,7 +4922,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 +4979,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 +5134,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);
   }
 
@@ -5303,6 +5303,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 +5430,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 +5622,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 +5792,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 +5959,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,7 +5984,7 @@
   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_); }
@@ -5985,17 +5993,18 @@
 
   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 +7544,8 @@
 
   bool IsRedundant(const RangeBoundary& length);
 
+  virtual bool MayThrow() const { return true; }
+
  private:
   DISALLOW_COPY_AND_ASSIGN(GenericCheckBoundInstr);
 };
@@ -7631,6 +7642,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 +7673,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 +7725,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 +7740,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 +7755,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 +7765,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..ebe2a08 100644
--- a/runtime/vm/compiler/backend/il_arm.cc
+++ b/runtime/vm/compiler/backend/il_arm.cc
@@ -1002,45 +1002,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
@@ -1225,18 +1193,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:
@@ -1333,19 +1302,12 @@
     } 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) {
@@ -1438,94 +1400,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, kWordSize));
+      } else {
+        __ LoadWordUnaligned(result_lo, address, TMP);
+        __ AddImmediate(address, address, 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 +1500,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:
@@ -1708,19 +1672,20 @@
     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()));
         __ 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();
@@ -1734,24 +1699,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;
     }
@@ -1865,13 +1829,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.
   }
 
@@ -2025,13 +1982,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.
   }
 
@@ -2635,7 +2585,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);
@@ -3600,7 +3550,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 +3560,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;
   }
@@ -5149,7 +5101,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -5163,8 +5115,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -5723,7 +5674,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()));
@@ -6723,7 +6675,7 @@
   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 = (kWordSize - from_width_bytes()) * kBitsPerByte;
   __ Lsl(reg, reg, Operand(shift_length));
   switch (representation_) {
     case kUnboxedInt32:  // Sign extend operand.
diff --git a/runtime/vm/compiler/backend/il_arm64.cc b/runtime/vm/compiler/backend/il_arm64.cc
index 5ba37ca..198269b 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
@@ -1105,18 +1094,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 +1238,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 +1276,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 +1375,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 +1500,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 +1508,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 +1529,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 +1657,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 +1807,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 +2284,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 +2770,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 +4339,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4389,8 +4353,7 @@
   return summary;
 }
 
-void CaseInsensitiveCompareUC16Instr::EmitNativeCode(
-    FlowGraphCompiler* compiler) {
+void CaseInsensitiveCompareInstr::EmitNativeCode(FlowGraphCompiler* compiler) {
   // Call the function.
   __ CallRuntime(TargetFunction(), TargetFunction().argument_count());
 }
@@ -5099,7 +5062,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 +5905,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();
diff --git a/runtime/vm/compiler/backend/il_dbc.cc b/runtime/vm/compiler/backend/il_dbc.cc
index e75bfef..107a3c8 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)                                                             \
@@ -1681,33 +1679,43 @@
   }
 }
 
-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);
+  const Register value = locs()->in(0).reg();
+  const Register out = locs()->out(0).reg();
+  EmitAllocateBox(compiler);
   __ WriteIntoDouble(out, value);
 }
 
 EMIT_NATIVE_CODE(Unbox, 1, Location::RequiresRegister()) {
+  if (representation() == kUnboxedInt64) {
+    EmitLoadInt64FromBoxOrSmi(compiler);
+    return;
+  }
   ASSERT(representation() == kUnboxedDouble);
   const intptr_t value_cid = value()->Type()->ToCid();
   const intptr_t box_cid = BoxCid();
@@ -1761,6 +1769,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();
diff --git a/runtime/vm/compiler/backend/il_ia32.cc b/runtime/vm/compiler/backend/il_ia32.cc
index 88ce5ba..349a09c 100644
--- a/runtime/vm/compiler/backend/il_ia32.cc
+++ b/runtime/vm/compiler/backend/il_ia32.cc
@@ -217,14 +217,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 +846,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 +866,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
@@ -1129,18 +1097,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 +1153,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 +1177,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 +1208,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 +1293,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 +1428,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 +1454,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 +1469,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 +1482,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 +1553,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.
   }
 
@@ -1751,13 +1707,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 +2177,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);
@@ -4473,7 +4422,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4487,8 +4436,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 +4451,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 +4667,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 +4780,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 +4795,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 +6026,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();
diff --git a/runtime/vm/compiler/backend/il_printer.cc b/runtime/vm/compiler/backend/il_printer.cc
index 19b2aed..fe7508f 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(" | ");
     }
@@ -1001,7 +1001,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);
 }
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..ce0b196 100644
--- a/runtime/vm/compiler/backend/il_x64.cc
+++ b/runtime/vm/compiler/backend/il_x64.cc
@@ -315,13 +315,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 +902,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
@@ -1183,18 +1171,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 +1250,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 +1277,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 +1302,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 +1395,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 +1527,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 +1557,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 +1572,8 @@
     }
     case kTypedDataInt16ArrayCid:
     case kTypedDataUint16ArrayCid: {
+      ASSERT(RequiredInputRepresentation(2) == kUnboxedIntPtr);
       Register value = locs()->in(2).reg();
-      __ SmiUntag(value);
       __ movw(element_address, value);
       break;
     }
@@ -1672,13 +1643,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.
   }
 
@@ -1823,13 +1787,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 +1866,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 +2282,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 +4482,7 @@
   }
 }
 
-LocationSummary* CaseInsensitiveCompareUC16Instr::MakeLocationSummary(
+LocationSummary* CaseInsensitiveCompareInstr::MakeLocationSummary(
     Zone* zone,
     bool opt) const {
   const intptr_t kNumTemps = 0;
@@ -4545,8 +4496,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 +4696,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 +4816,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 +4837,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 +6181,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();
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 8a7550f..634729f8 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -415,11 +415,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.
@@ -1170,21 +1170,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 +1182,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 +1499,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();
         }
       }
 
@@ -2485,16 +2463,29 @@
   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 +2625,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,16 +2650,30 @@
         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);
   }
@@ -3109,24 +3121,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
@@ -3182,10 +3220,13 @@
   LoadIndexedInstr* load_indexed = new (Z) LoadIndexedInstr(
       new (Z) Value(str), new (Z) Value(index), 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,
@@ -4065,7 +4106,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(),
@@ -4128,16 +4169,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/locations.h b/runtime/vm/compiler/backend/locations.h
index 513d61b..d127790 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,
@@ -392,11 +410,25 @@
  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 +594,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 +826,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/redundancy_elimination.cc b/runtime/vm/compiler/backend/redundancy_elimination.cc
index f29815c..f0fa894 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));
+                }
+              }
             }
           }
         }
diff --git a/runtime/vm/compiler/backend/redundancy_elimination_test.cc b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
index e06aca3..9aee1ee 100644
--- a/runtime/vm/compiler/backend/redundancy_elimination_test.cc
+++ b/runtime/vm/compiler/backend/redundancy_elimination_test.cc
@@ -551,4 +551,167 @@
                        /* 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);
+  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},
+          kMatchAndMoveBranchTrue,
+          kMatchAndMoveBranchTrue,
+          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/type_propagator.cc b/runtime/vm/compiler/backend/type_propagator.cc
index 0dec0c9..0352767 100644
--- a/runtime/vm/compiler/backend/type_propagator.cc
+++ b/runtime/vm/compiler/backend/type_propagator.cc
@@ -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..5f12916 100644
--- a/runtime/vm/compiler/call_specializer.cc
+++ b/runtime/vm/compiler/call_specializer.cc
@@ -1862,20 +1862,54 @@
 
   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),
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 3e08c06..84f2cad 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -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();
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/ffi.cc b/runtime/vm/compiler/ffi.cc
index 8d8d136..f01e742 100644
--- a/runtime/vm/compiler/ffi.cc
+++ b/runtime/vm/compiler/ffi.cc
@@ -3,7 +3,9 @@
 // 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/runtime_api.h"
 
@@ -13,8 +15,6 @@
 
 namespace ffi {
 
-#if !defined(TARGET_ARCH_DBC)
-
 static const size_t kSizeUnknown = 0;
 
 static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
@@ -73,6 +73,23 @@
   }
 }
 
+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;
+  }
+}
+
+#if !defined(TARGET_ARCH_DBC)
+
 bool NativeTypeIsVoid(const AbstractType& result_type) {
   return result_type.type_class_id() == kFfiVoidCid;
 }
@@ -299,16 +316,10 @@
   return max_height_in_slots;
 }
 
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
-
-#else
-
-size_t ElementSizeInBytes(intptr_t class_id) {
-  UNREACHABLE();
-}
-
 #endif  // !defined(TARGET_ARCH_DBC)
 
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+
 }  // namespace ffi
 
 }  // namespace compiler
diff --git a/runtime/vm/compiler/ffi.h b/runtime/vm/compiler/ffi.h
index efed0cc..63700b5 100644
--- a/runtime/vm/compiler/ffi.h
+++ b/runtime/vm/compiler/ffi.h
@@ -28,6 +28,10 @@
 // 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);
 
diff --git a/runtime/vm/compiler/frontend/base_flow_graph_builder.cc b/runtime/vm/compiler/frontend/base_flow_graph_builder.cc
index 07ac0b0..aff93f9 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.
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 19b94e1..35ee872 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -799,13 +799,16 @@
   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::_simpleInstanceOf()).raw()) {
+    ASSERT(arg_desc.Count() == 2);
+    checked_argument_count = 2;
+    token_kind = Token::kIS;
+  } else if (name.raw() ==
              Library::PrivateCoreLibName(Symbols::_instanceOf()).raw()) {
     token_kind = Token::kIS;
   }
@@ -1407,24 +1410,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() {
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index c2a6590..2b3f515 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -58,11 +58,27 @@
     case RawFunction::kImplicitSetter:
       function.AttachBytecode(Object::implicit_setter_bytecode());
       return;
+    case RawFunction::kImplicitStaticGetter:
+      if (IsStaticFieldGetterGeneratedAsInitializer(function, helper_->zone_)) {
+        break;
+      }
+      function.AttachBytecode(Object::implicit_static_getter_bytecode());
+      return;
     case RawFunction::kMethodExtractor:
       function.AttachBytecode(Object::method_extractor_bytecode());
       return;
-    default: {
-    }
+    case RawFunction::kInvokeFieldDispatcher:
+      if (Class::Handle(function.Owner()).id() == kClosureCid) {
+        function.AttachBytecode(Object::invoke_closure_bytecode());
+      } else {
+        function.AttachBytecode(Object::invoke_field_bytecode());
+      }
+      return;
+    case RawFunction::kNoSuchMethodDispatcher:
+      function.AttachBytecode(Object::nsm_dispatcher_bytecode());
+      return;
+    default:
+      break;
   }
 
   intptr_t code_offset = 0;
@@ -103,7 +119,10 @@
   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;
   }
 
@@ -423,7 +442,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();
 }
 
@@ -1414,7 +1433,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();
 }
 
@@ -1536,15 +1555,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);
@@ -1902,7 +1920,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 {
@@ -2234,7 +2252,7 @@
 
 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_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..37236d7 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -165,7 +165,11 @@
       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());
+    }
     return Fragment();
   }
 
@@ -936,7 +940,7 @@
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
         return B->BuildGraphOfFieldAccessor(function);
-      case RawFunction::kImplicitStaticFinalGetter: {
+      case RawFunction::kImplicitStaticGetter: {
         if (IsStaticFieldGetterGeneratedAsInitializer(function, Z)) {
           break;
         }
@@ -946,6 +950,8 @@
         return B->BuildGraphOfDynamicInvocationForwarder(function);
       case RawFunction::kMethodExtractor:
         return B->BuildGraphOfMethodExtractor(function);
+      case RawFunction::kNoSuchMethodDispatcher:
+        return B->BuildGraphOfNoSuchMethodDispatcher(function);
       default:
         break;
     }
@@ -968,7 +974,10 @@
     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)) {
       BytecodeFlowGraphBuilder bytecode_compiler(
           flow_graph_builder_, parsed_function(),
           &(flow_graph_builder_->ic_data_array_));
@@ -991,7 +1000,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 +1062,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 +1986,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 +2916,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 +4024,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;
diff --git a/runtime/vm/compiler/frontend/kernel_fingerprints.cc b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
index 848365d..2ac1adf 100644
--- a/runtime/vm/compiler/frontend/kernel_fingerprints.cc
+++ b/runtime/vm/compiler/frontend/kernel_fingerprints.cc
@@ -795,9 +795,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 +820,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..755ccb6 100644
--- a/runtime/vm/compiler/frontend/kernel_to_il.cc
+++ b/runtime/vm/compiler/frontend/kernel_to_il.cc
@@ -1799,9 +1799,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());
@@ -2433,12 +2433,12 @@
 
 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);
 }
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.cc b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
index 6f46ea7..26f5476 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.cc
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.cc
@@ -2899,7 +2899,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 +2924,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 +2936,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 +2951,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 +2963,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/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 268e3d9..dde3667 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
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
index 85b9e11..ddf564b 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)) {
@@ -173,6 +176,31 @@
       new Value(array), new Value(index),
       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:
@@ -453,9 +488,22 @@
         new Value(str), ExternalTwoByteString::external_data_offset()));
   }
 
-  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
+  Definition* load = builder.AddDefinition(new LoadIndexedInstr(
       new Value(str), new Value(index), 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;
 }
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 412e6b0..d334330 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -101,7 +101,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 +166,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);
@@ -427,12 +425,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 +778,6 @@
         }
         done = true;
       }
-
     }
   }
   return result->raw();
@@ -794,7 +785,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());
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/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..5d9aad0 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -837,7 +837,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();
@@ -1768,11 +1768,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 +1787,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 +1844,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 +1855,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 +1901,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 +1916,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 +1939,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 +1956,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 +2019,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 +2035,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 +2092,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 +2111,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 +2272,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 +2389,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)
 }
diff --git a/runtime/vm/compiler/stub_code_compiler_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
index 2205c2b..211a6c4 100644
--- a/runtime/vm/compiler/stub_code_compiler_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -887,7 +887,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();
@@ -1827,12 +1827,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 +1845,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 +1904,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 +1914,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 +1964,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 +1979,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 +2003,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 +2021,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 +2084,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 +2099,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 +2168,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 +2184,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 +2349,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 +2481,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)
 }
 
diff --git a/runtime/vm/compiler/stub_code_compiler_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
index 12259cc..657ec31 100644
--- a/runtime/vm/compiler/stub_code_compiler_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -627,7 +627,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();
@@ -1471,8 +1471,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 +1492,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 +1503,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 +1543,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 +1555,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 +1607,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 +1622,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 +1644,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 +1692,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--) {
@@ -1777,105 +1783,119 @@
   __ jmp(EBX);
 
 #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)
   {
@@ -1936,18 +1956,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.
@@ -2040,14 +2066,13 @@
   __ 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()));
@@ -2583,32 +2608,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..6179c7d 100644
--- a/runtime/vm/compiler/stub_code_compiler_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -847,7 +847,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 +870,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);
@@ -1804,8 +1804,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 +1825,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 +1876,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 +1888,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 +1941,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 +1956,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 +1977,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 +1993,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.
@@ -2033,9 +2053,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 +2102,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 +2141,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 +2153,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 +2176,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 +2348,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 +2473,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()));
@@ -3053,7 +3095,7 @@
 }
 
 // Called from megamorphic calls.
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  CODE_REG: target Code
@@ -3061,12 +3103,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 +3176,7 @@
 }
 
 // Called from switchable IC calls.
-//  RDI: receiver
+//  RDX: receiver
 //  RBX: ICData (preserved)
 // Passed to target:
 //  CODE_REG: target Code object
@@ -3146,7 +3188,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 +3228,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 +3263,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 +3288,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 +3311,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 +3330,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/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..ff89001 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.
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..b84d411 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.
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..2d7483b 100644
--- a/runtime/vm/constants_dbc.h
+++ b/runtime/vm/constants_dbc.h
@@ -300,6 +300,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].
@@ -810,11 +831,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 +920,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 +1136,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..8e8c304 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.
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index dc8e954..bc25ff8 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -231,7 +231,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 +346,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
 //
@@ -526,12 +528,19 @@
   V(CompareDoubleGe,                       0, ___, ___, ___)                   \
   V(CompareDoubleLe,                       0, ___, ___, ___)                   \
 
-  // 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_ImplicitStaticGetter,       0, ___, ___, ___)                   \
   V(VMInternal_MethodExtractor,            0, ___, ___, ___)                   \
+  V(VMInternal_InvokeClosure,              0, ___, ___, ___)                   \
+  V(VMInternal_InvokeField,                0, ___, ___, ___)                   \
+  V(VMInternal_ForwardDynamicInvocation,   0, ___, ___, ___)                   \
+  V(VMInternal_NoSuchMethodDispatcher,     0, ___, ___, ___)                   \
+  V(VMInternal_ImplicitStaticClosure,      0, ___, ___, ___)                   \
+  V(VMInternal_ImplicitInstanceClosure,    0, ___, ___, ___)                   \
 
 #define KERNEL_BYTECODES_LIST(V)                                               \
   PUBLIC_KERNEL_BYTECODES_LIST(V)                                              \
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..f6eb461 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,
diff --git a/runtime/vm/dart.cc b/runtime/vm/dart.cc
index ffb115e..822cab8 100644
--- a/runtime/vm/dart.cc
+++ b/runtime/vm/dart.cc
@@ -379,8 +379,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 +401,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..7f7a646 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -20,6 +20,7 @@
 #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 +33,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 +51,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"
 
@@ -1092,8 +1093,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 +1114,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);
 }
@@ -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();
   }
@@ -3700,10 +3717,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 +5170,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);
@@ -5938,6 +5955,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();
@@ -6133,7 +6153,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 +6161,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_test.cc b/runtime/vm/dart_api_impl_test.cc
index 406901a..0682bb9 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);
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..a4c22c3 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);
diff --git a/runtime/vm/debugger.cc b/runtime/vm/debugger.cc
index e117e1d..13e4621 100644
--- a/runtime/vm/debugger.cc
+++ b/runtime/vm/debugger.cc
@@ -445,7 +445,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:
@@ -633,7 +633,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();
@@ -960,9 +960,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 +1367,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()) {
@@ -1627,20 +1634,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);
@@ -2055,7 +2062,7 @@
           function = it.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--;
@@ -2110,7 +2117,7 @@
         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 {
@@ -2427,7 +2434,8 @@
 TokenPosition Debugger::ResolveBreakpointPos(const Function& func,
                                              TokenPosition requested_token_pos,
                                              TokenPosition last_token_pos,
-                                             intptr_t requested_column) {
+                                             intptr_t requested_column,
+                                             TokenPosition exact_token_pos) {
   ASSERT(func.HasCode());
   ASSERT(!func.HasOptimizedCode());
 
@@ -2449,6 +2457,9 @@
   TokenPosition best_fit_pos = TokenPosition::kMaxSource;
   intptr_t best_column = INT_MAX;
   intptr_t best_line = INT_MAX;
+  // best_token_pos and exact_token_pos are only used
+  // if column number is provided.
+  TokenPosition best_token_pos = TokenPosition::kNoSource;
   PcDescriptors::Iterator iter(desc, kSafepointKind);
   while (iter.MoveNext()) {
     const TokenPosition pos = iter.TokenPos();
@@ -2461,17 +2472,26 @@
     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) ||
+      // 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.
@@ -2484,6 +2504,9 @@
       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));
     }
   }
 
@@ -2520,12 +2543,7 @@
       }
 
       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 (pos != best_token_pos) {
           continue;
         }
       }
@@ -2545,7 +2563,7 @@
   // 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 */);
+                                -1 /* no column */, TokenPosition::kNoSource);
   }
   return TokenPosition::kNoSource;
 }
@@ -2813,26 +2831,35 @@
       // have already been compiled. We can resolve the breakpoint now.
       DeoptimizeWorld();
       func ^= functions.At(0);
+      TokenPosition exact_token_pos = TokenPosition(-1);
+      // if requested_column is larger than zero, [token_pos, last_token_pos]
+      // governs one single line of code.
+      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)
+      }
       TokenPosition breakpoint_pos = ResolveBreakpointPos(
-          func, token_pos, last_token_pos, requested_column);
+          func, token_pos, last_token_pos, requested_column, exact_token_pos);
       if (breakpoint_pos.IsReal()) {
-        BreakpointLocation* bpt =
-            GetBreakpointLocation(script, breakpoint_pos, requested_column);
-        if (bpt != NULL) {
+        BreakpointLocation* loc = GetBreakpointLocation(script, breakpoint_pos,
+                                                        requested_column, true);
+        if (loc != NULL) {
           // A source breakpoint for this location already exists.
-          return bpt;
+          return loc;
         }
-        bpt = new BreakpointLocation(script, token_pos, last_token_pos,
+        loc = new BreakpointLocation(script, breakpoint_pos, breakpoint_pos,
                                      requested_line, requested_column);
-        bpt->SetResolved(func, breakpoint_pos);
-        RegisterBreakpointLocation(bpt);
+        loc->SetResolved(func, breakpoint_pos);
+        RegisterBreakpointLocation(loc);
 
         // 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);
+          MakeCodeBreakpointAt(func, loc);
         }
         if (FLAG_verbose_debug) {
           intptr_t line_number;
@@ -2843,7 +2870,7 @@
               "function '%s' at line %" Pd " col %" Pd "\n",
               func.ToFullyQualifiedCString(), line_number, column_number);
         }
-        return bpt;
+        return loc;
       }
     }
   }
@@ -2866,14 +2893,14 @@
           func.ToFullyQualifiedCString(), line_number, column_number);
     }
   }
-  BreakpointLocation* bpt =
+  BreakpointLocation* loc =
       GetBreakpointLocation(script, token_pos, requested_column);
-  if (bpt == NULL) {
-    bpt = new BreakpointLocation(script, token_pos, last_token_pos,
+  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 +3069,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) {
@@ -3793,6 +3820,22 @@
   return best_fit.raw();
 }
 
+#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::NotifyCompilation(const Function& func) {
   if (breakpoint_locations_ == NULL) {
     // Return with minimal overhead if there are no breakpoints.
@@ -3814,7 +3857,18 @@
     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)
+      }
+      inner_function = FindInnermostClosure(func, token_pos);
       if (!inner_function.IsNull()) {
         // The local function of a function we just compiled cannot
         // be compiled already.
@@ -3837,7 +3891,7 @@
         // Resolve source breakpoint in the newly compiled function.
         TokenPosition bp_pos =
             ResolveBreakpointPos(func, loc->token_pos(), loc->end_token_pos(),
-                                 loc->requested_column_number());
+                                 loc->requested_column_number(), token_pos);
         if (!bp_pos.IsDebugPause()) {
           if (FLAG_verbose_debug) {
             OS::PrintErr("Failed resolving breakpoint for function '%s'\n",
@@ -4004,25 +4058,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();
@@ -4149,14 +4203,22 @@
 
 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;
+                                                    intptr_t requested_column,
+                                                    bool is_resolved) {
+  BreakpointLocation* loc = breakpoint_locations_;
+  while (loc != NULL) {
+    // When BreakpointLocation has been resolved BreakpointLocation
+    // should check only token position. Whether column or line
+    // breakpoint should be the same once resolved into the
+    // same token position.
+    bool column_match =
+        (is_resolved) ? true
+                      : (loc->requested_column_number_ == requested_column);
+    if ((loc->script_ == script.raw()) && (loc->token_pos_ == token_pos) &&
+        column_match) {
+      return loc;
     }
-    bpt = bpt->next();
+    loc = loc->next();
   }
   return NULL;
 }
@@ -4208,33 +4270,33 @@
 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..05230cd 100644
--- a/runtime/vm/debugger.h
+++ b/runtime/vm/debugger.h
@@ -636,7 +636,8 @@
   TokenPosition ResolveBreakpointPos(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();
   BreakpointLocation* SetBreakpoint(const Script& script,
                                     TokenPosition token_pos,
@@ -655,7 +656,8 @@
   void RegisterCodeBreakpoint(CodeBreakpoint* bpt);
   BreakpointLocation* GetBreakpointLocation(const Script& script,
                                             TokenPosition token_pos,
-                                            intptr_t requested_column);
+                                            intptr_t requested_column,
+                                            bool is_resolved = false);
   void MakeCodeBreakpointAt(const Function& func, BreakpointLocation* bpt);
   // Returns NULL if no breakpoint exists for the given address.
   CodeBreakpoint* GetCodeBreakpoint(uword breakpoint_address);
@@ -677,6 +679,9 @@
   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/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..1165836 100644
--- a/runtime/vm/dwarf.cc
+++ b/runtime/vm/dwarf.cc
@@ -511,7 +511,7 @@
   String& uri = String::Handle(zone_);
   for (intptr_t i = 0; i < scripts_.length(); i++) {
     const Script& script = *(scripts_[i]);
-    uri ^= script.url();
+    uri = script.url();
     Print(".string \"%s\"\n", uri.ToCString());
     uleb128(0);  // Include directory index.
     uleb128(0);  // File modification time.
diff --git a/runtime/vm/exceptions.cc b/runtime/vm/exceptions.cc
index 058d9c7..4acc536 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);
+    }
   }
 }
 
@@ -695,7 +698,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()));
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/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..4f0b6fc 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,
@@ -919,23 +907,6 @@
 }
 #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_);
@@ -1107,13 +1078,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 +1087,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();
@@ -1393,7 +1357,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..c1608af 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_;
 
@@ -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);
 
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/interpreter.cc b/runtime/vm/interpreter.cc
index c72f6b0..5069504 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -615,221 +615,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,
+                                                   uint32_t** 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,6 +630,8 @@
               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);
@@ -850,6 +645,38 @@
   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);
+
+  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,
@@ -1104,18 +931,24 @@
 #define DECLARE_A
 #define DECODE_A
 
-#define DECLARE___D                                                            \
+#define DECLARE_T
+#define DECODE_T
+
+#define DECLARE_D                                                              \
   uint32_t rD;                                                                 \
   USE(rD)
-#define DECODE___D rD = (op >> KernelBytecode::kDShift);
+#define DECODE_D rD = (op >> KernelBytecode::kDShift);
 
-#define DECLARE_A_D DECLARE___D
-#define DECODE_A_D DECODE___D
+#define DECLARE_A_D DECLARE_D
+#define DECODE_A_D DECODE_D
 
-#define DECLARE_A_X                                                            \
+#define DECLARE_X                                                              \
   int32_t rD;                                                                  \
   USE(rD)
-#define DECODE_A_X rD = (static_cast<int32_t>(op) >> KernelBytecode::kDShift);
+#define DECODE_X rD = (static_cast<int32_t>(op) >> KernelBytecode::kDShift);
+
+#define DECLARE_A_X DECLARE_X
+#define DECODE_A_X DECODE_X
 
 #define HANDLE_EXCEPTION                                                       \
   do {                                                                         \
@@ -1183,6 +1016,21 @@
   }                                                                            \
   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);                                            \
+    }                                                                          \
+  }
+
 bool Interpreter::AssertAssignable(Thread* thread,
                                    uint32_t* pc,
                                    RawObject** FP,
@@ -1405,7 +1253,7 @@
                                 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())) {
@@ -1592,10 +1440,6 @@
   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,
@@ -1619,7 +1463,7 @@
 
   // KernelBytecode handlers (see constants_kbc.h for bytecode descriptions).
   {
-    BYTECODE(Entry, A_D);
+    BYTECODE(Entry, D);
     const uint16_t num_locals = rD;
 
     // Initialize locals with null & set SP.
@@ -1639,7 +1483,7 @@
     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.
@@ -1666,7 +1510,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.
@@ -1729,7 +1573,7 @@
       // between formal parameters and concrete arguments. This can only
       // occur if the current function is a closure.
       if (i != -1) {
-        goto ClosureNoSuchMethod;
+        goto NoSuchMethodFromPrologue;
       }
 
       // Skip LoadConstant-s encoding information about named parameters.
@@ -1743,7 +1587,7 @@
         // 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
@@ -1774,7 +1618,7 @@
   }
 
   {
-    BYTECODE(Frame, A_D);
+    BYTECODE(Frame, D);
     // Initialize locals with null and increment SP.
     const uint16_t num_locals = rD;
     for (intptr_t i = 1; i <= num_locals; i++) {
@@ -1826,7 +1670,7 @@
     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 +1684,7 @@
   }
 
   {
-    BYTECODE(InstantiateType, A_D);
+    BYTECODE(InstantiateType, D);
     // Stack: instantiator type args, function type args
     RawObject* type = LOAD_CONSTANT(rD);
     SP[1] = type;
@@ -1925,7 +1769,7 @@
   }
 
   {
-    BYTECODE(PushConstant, __D);
+    BYTECODE(PushConstant, D);
     *++SP = LOAD_CONSTANT(rD);
     DISPATCH();
   }
@@ -1949,25 +1793,25 @@
   }
 
   {
-    BYTECODE(PushInt, A_X);
+    BYTECODE(PushInt, X);
     *++SP = Smi::New(rD);
     DISPATCH();
   }
 
   {
-    BYTECODE(Push, A_X);
+    BYTECODE(Push, X);
     *++SP = FP[rD];
     DISPATCH();
   }
 
   {
-    BYTECODE(StoreLocal, A_X);
+    BYTECODE(StoreLocal, X);
     FP[rD] = *SP;
     DISPATCH();
   }
 
   {
-    BYTECODE(PopLocal, A_X);
+    BYTECODE(PopLocal, X);
     FP[rD] = *SP--;
     DISPATCH();
   }
@@ -2152,7 +1996,7 @@
   }
 
   {
-    BYTECODE(NativeCall, __D);
+    BYTECODE(NativeCall, D);
     RawTypedData* data = static_cast<RawTypedData*>(LOAD_CONSTANT(rD));
     MethodRecognizer::Kind kind = NativeEntryData::GetKind(data);
     switch (kind) {
@@ -2383,7 +2227,7 @@
   }
 
   {
-    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 +2235,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 +2243,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,7 +2333,7 @@
   }
 
   {
-    BYTECODE(StoreContextVar, __D);
+    BYTECODE(StoreContextVar, A_D);
     const uword offset_in_words =
         static_cast<uword>(Context::variable_offset(rD) / kWordSize);
     RawContext* instance = reinterpret_cast<RawContext*>(SP[-1]);
@@ -2504,7 +2348,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 +2367,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,7 +2385,7 @@
   }
 
   {
-    BYTECODE(LoadContextVar, __D);
+    BYTECODE(LoadContextVar, A_D);
     const uword offset_in_words =
         static_cast<uword>(Context::variable_offset(rD) / kWordSize);
     RawContext* instance = static_cast<RawContext*>(SP[0]);
@@ -2561,7 +2405,7 @@
   }
 
   {
-    BYTECODE(CloneContext, A);
+    BYTECODE(CloneContext, A_D);
     {
       SP[1] = SP[0];  // Context to clone.
       Exit(thread, FP, SP + 2, pc);
@@ -2572,7 +2416,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_;
@@ -2667,7 +2511,7 @@
   }
 
   {
-    BYTECODE(AssertSubtype, A);
+    BYTECODE(AssertSubtype, 0);
     RawObject** args = SP - 4;
 
     // TODO(kustermann): Implement fast case for common arguments.
@@ -2720,13 +2564,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 +2578,7 @@
   }
 
   {
-    BYTECODE(JumpIfNotZeroTypeArgs, 0);
+    BYTECODE(JumpIfNotZeroTypeArgs, T);
     if (InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) != 0) {
       LOAD_JUMP_TARGET();
     }
@@ -2742,7 +2586,7 @@
   }
 
   {
-    BYTECODE(JumpIfEqStrict, 0);
+    BYTECODE(JumpIfEqStrict, T);
     SP -= 2;
     if (SP[1] == SP[2]) {
       LOAD_JUMP_TARGET();
@@ -2751,7 +2595,7 @@
   }
 
   {
-    BYTECODE(JumpIfNeStrict, 0);
+    BYTECODE(JumpIfNeStrict, T);
     SP -= 2;
     if (SP[1] != SP[2]) {
       LOAD_JUMP_TARGET();
@@ -2760,7 +2604,7 @@
   }
 
   {
-    BYTECODE(JumpIfTrue, 0);
+    BYTECODE(JumpIfTrue, T);
     SP -= 1;
     if (SP[1] == true_value) {
       LOAD_JUMP_TARGET();
@@ -2769,7 +2613,7 @@
   }
 
   {
-    BYTECODE(JumpIfFalse, 0);
+    BYTECODE(JumpIfFalse, T);
     SP -= 1;
     if (SP[1] == false_value) {
       LOAD_JUMP_TARGET();
@@ -2778,7 +2622,7 @@
   }
 
   {
-    BYTECODE(JumpIfNull, 0);
+    BYTECODE(JumpIfNull, T);
     SP -= 1;
     if (SP[1] == null_value) {
       LOAD_JUMP_TARGET();
@@ -2787,7 +2631,7 @@
   }
 
   {
-    BYTECODE(JumpIfNotNull, 0);
+    BYTECODE(JumpIfNotNull, T);
     SP -= 1;
     if (SP[1] != null_value) {
       LOAD_JUMP_TARGET();
@@ -3102,7 +2946,7 @@
   }
 
   {
-    BYTECODE(AllocateClosure, A_D);
+    BYTECODE(AllocateClosure, D);
     ++SP;
     if (!AllocateClosure(thread, pc, FP, SP)) {
       HANDLE_EXCEPTION;
@@ -3120,17 +2964,9 @@
     BYTECODE(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_);
@@ -3177,17 +3013,9 @@
     BYTECODE(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 +3090,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,20 +3131,44 @@
   }
 
   {
+    BYTECODE(VMInternal_ImplicitStaticGetter, 0);
+
+    RawFunction* function = FrameFunction(FP);
+    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_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(VMInternal_MethodExtractor, 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::kMethodExtractor);
+
+    BUMP_USAGE_COUNTER_ON_ENTRY(function);
 
     ASSERT(InterpreterHelpers::ArgDescTypeArgsLen(argdesc_) == 0);
 
@@ -3349,64 +3202,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(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(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(VMInternal_ForwardDynamicInvocation, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) ==
+           RawFunction::kDynamicInvocationForwarder);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(VMInternal_NoSuchMethodDispatcher, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kNoSuchMethodDispatcher);
+    goto NoSuchMethodFromPrologue;
+  }
+
+  {
+    BYTECODE(VMInternal_ImplicitStaticClosure, 0);
+    RawFunction* function = FrameFunction(FP);
+    ASSERT(Function::kind(function) == RawFunction::kImplicitClosureFunction);
+    UNIMPLEMENTED();
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(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<uint32_t*>(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();
diff --git a/runtime/vm/interpreter.h b/runtime/vm/interpreter.h
index e8fe9db..db8d6e7 100644
--- a/runtime/vm/interpreter.h
+++ b/runtime/vm/interpreter.h
@@ -153,15 +153,6 @@
               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,
@@ -170,6 +161,14 @@
                       RawObject*** FP,
                       RawObject*** SP);
 
+  bool InvokeBytecode(Thread* thread,
+                      RawFunction* function,
+                      RawObject** call_base,
+                      RawObject** call_top,
+                      uint32_t** pc,
+                      RawObject*** FP,
+                      RawObject*** SP);
+
   void InlineCacheMiss(int checked_args,
                        Thread* thread,
                        RawICData* icdata,
diff --git a/runtime/vm/isolate.cc b/runtime/vm/isolate.cc
index 49caa27..49810ef 100644
--- a/runtime/vm/isolate.cc
+++ b/runtime/vm/isolate.cc
@@ -69,7 +69,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 +103,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 +239,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 +395,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 +475,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 +499,7 @@
 }
 
 MessageHandler::MessageStatus IsolateMessageHandler::HandleMessage(
-    Message* message) {
+    std::unique_ptr<Message> message) {
   ASSERT(IsCurrentIsolate());
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
@@ -496,16 +521,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 +540,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 +636,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,60 +857,33 @@
 #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_"))),
       type_canonicalization_mutex_(
@@ -916,27 +898,17 @@
           new 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),
       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_"))),
       boxed_field_list_(GrowableObjectArray::null()),
       spawn_count_monitor_(new Monitor()),
-      spawn_count_(0),
       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 +945,73 @@
 
   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.
+  mutex_ = nullptr;  // Fail fast if interrupts are scheduled on a dead isolate.
   delete symbols_mutex_;
-  symbols_mutex_ = NULL;
+  symbols_mutex_ = nullptr;
   delete type_canonicalization_mutex_;
-  type_canonicalization_mutex_ = NULL;
+  type_canonicalization_mutex_ = nullptr;
   delete constant_canonicalization_mutex_;
-  constant_canonicalization_mutex_ = NULL;
+  constant_canonicalization_mutex_ = nullptr;
   delete megamorphic_lookup_mutex_;
-  megamorphic_lookup_mutex_ = NULL;
+  megamorphic_lookup_mutex_ = nullptr;
   delete kernel_constants_mutex_;
   kernel_constants_mutex_ = nullptr;
   delete kernel_data_lib_cache_mutex_;
-  kernel_data_lib_cache_mutex_ = NULL;
+  kernel_data_lib_cache_mutex_ = nullptr;
   delete kernel_data_class_cache_mutex_;
-  kernel_data_class_cache_mutex_ = NULL;
+  kernel_data_class_cache_mutex_ = nullptr;
   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;
+  field_list_mutex_ = nullptr;
   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 +1021,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 +1033,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 +1070,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 +1104,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 +1123,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 +1144,7 @@
 }
 
 Thread* Isolate::mutator_thread() const {
-  ASSERT(thread_registry() != NULL);
+  ASSERT(thread_registry() != nullptr);
   return thread_registry()->mutator_thread();
 }
 
@@ -1199,7 +1174,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 +1192,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 +1216,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 +1257,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 +1275,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 +1291,7 @@
   SafepointOperationScope safepoint_scope(thread);
 
   delete reload_context_;
-  reload_context_ = NULL;
+  reload_context_ = nullptr;
 }
 #endif  // !defined(PRODUCT) && !defined(DART_PRECOMPILED_RUNTIME)
 
@@ -1329,7 +1304,7 @@
 }
 
 const char* Isolate::MakeRunnable() {
-  ASSERT(Isolate::Current() == NULL);
+  ASSERT(Isolate::Current() == nullptr);
 
   MutexLocker ml(mutex_);
   // Check if we are in a valid state to make the isolate runnable.
@@ -1349,15 +1324,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 +1354,7 @@
     GetRunnableHeapSizeMetric()->set_value(heap_size);
   }
 #endif  // !PRODUCT
-  return NULL;
+  return nullptr;
 }
 
 bool Isolate::VerifyPauseCapability(const Object& capability) const {
@@ -1578,7 +1553,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 +1765,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 +1783,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 +1849,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 +1878,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 +1908,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 +1920,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 +1947,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 +1972,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 +1984,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 +1995,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 +2016,7 @@
 }
 
 void Isolate::VisitWeakPersistentHandles(HandleVisitor* visitor) {
-  if (api_state() != NULL) {
+  if (api_state() != nullptr) {
     api_state()->VisitWeakHandles(visitor);
   }
 }
@@ -2052,7 +2027,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 +2036,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 +2053,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 +2117,7 @@
       return "Unhandled";
     default:
       UNIMPLEMENTED();
-      return NULL;
+      return nullptr;
   }
 }
 
@@ -2180,12 +2155,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 +2170,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 +2236,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);
   }
@@ -2386,14 +2362,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 +2425,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 +2457,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 +2476,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 +2506,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 +2565,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 +2575,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 +2593,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 +2614,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 +2631,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 +2641,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 +2655,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 +2664,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 +2672,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 +2740,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 +2753,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 +2763,7 @@
   virtual ~IsolateKillerVisitor() {}
 
   void VisitIsolate(Isolate* isolate) {
-    ASSERT(isolate != NULL);
+    ASSERT(isolate != nullptr);
     if (ShouldKill(isolate)) {
       isolate->KillLocked(msg_id_);
     }
@@ -2779,8 +2773,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_;
@@ -2817,9 +2811,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 +2822,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 +2834,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 +2876,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 +2885,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 +2903,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();
@@ -2943,7 +2937,7 @@
                                      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),
@@ -2952,11 +2946,11 @@
       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),
@@ -2968,8 +2962,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());
@@ -2994,7 +2988,7 @@
                                      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),
@@ -3003,9 +2997,9 @@
       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()),
@@ -3029,8 +3023,6 @@
   delete[] class_name_;
   delete[] function_name_;
   delete[] debug_name_;
-  delete serialized_args_;
-  delete serialized_message_;
 }
 
 RawObject* IsolateSpawnState::ResolveFunction() {
@@ -3039,7 +3031,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 +3067,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 +3086,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,23 +3096,23 @@
         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_);
+  return DeserializeMessage(thread, serialized_message_.get());
 }
 
 void IsolateSpawnState::DecrementSpawnCount() {
-  ASSERT(spawn_count_monitor_ != NULL);
-  ASSERT(spawn_count_ != NULL);
+  ASSERT(spawn_count_monitor_ != nullptr);
+  ASSERT(spawn_count_ != nullptr);
   MonitorLocker ml(spawn_count_monitor_);
   ASSERT(*spawn_count_ > 0);
   *spawn_count_ = *spawn_count_ - 1;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index 584eeae..f0484c9 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -9,6 +9,8 @@
 #error "Should not include runtime"
 #endif
 
+#include <memory>
+
 #include "include/dart_api.h"
 #include "platform/assert.h"
 #include "platform/atomic.h"
@@ -170,6 +172,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 +185,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 +308,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)
@@ -368,7 +371,7 @@
 
 #if !defined(PRODUCT)
   Debugger* debugger() const {
-    ASSERT(debugger_ != NULL);
+    ASSERT(debugger_ != nullptr);
     return debugger_;
   }
 
@@ -468,10 +471,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 +532,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 +661,7 @@
   RawField* GetDeoptimizingBoxedField();
 
 #ifndef PRODUCT
-  RawObject* InvokePendingServiceExtensionCalls();
+  RawError* InvokePendingServiceExtensionCalls();
   void AppendServiceExtensionCall(const Instance& closure,
                                   const String& method_name,
                                   const Array& parameter_keys,
@@ -783,8 +786,8 @@
   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 +873,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)                                                               \
@@ -918,23 +921,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,41 +961,42 @@
   };
   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_;
+  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.
@@ -1001,11 +1005,11 @@
   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_;
+  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,12 +1024,12 @@
   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_;
@@ -1035,15 +1039,15 @@
   // 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_;
+  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 +1092,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 +1106,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();
@@ -1171,7 +1174,7 @@
   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_; }
@@ -1196,8 +1199,8 @@
   const char* class_name_;
   const char* function_name_;
   const char* debug_name_;
-  Message* serialized_args_;
-  Message* serialized_message_;
+  std::unique_ptr<Message> serialized_args_;
+  std::unique_ptr<Message> serialized_message_;
 
   // This counter tracks the number of outstanding calls to spawn by the parent
   // isolate.
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 76e8e9d..30bedb0 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();
     }
@@ -987,25 +987,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 +1090,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 +1200,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());
   }
 
@@ -1840,8 +1855,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 +1958,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 +1966,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 +2118,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 +2139,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",
diff --git a/runtime/vm/json_stream.cc b/runtime/vm/json_stream.cc
index c320591..05f474e 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,
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_isolate.cc b/runtime/vm/kernel_isolate.cc
index 4862219..660934f 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;
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b90a609..962d878 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -1996,14 +1996,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 +2017,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;
         }
       }
@@ -2091,7 +2091,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/message.cc b/runtime/vm/message.cc
index 985c5b5..4d08a30 100644
--- a/runtime/vm/message.cc
+++ b/runtime/vm/message.cc
@@ -93,7 +93,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 +137,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..4bf2303 100644
--- a/runtime/vm/message.h
+++ b/runtime/vm/message.h
@@ -5,6 +5,8 @@
 #ifndef RUNTIME_VM_MESSAGE_H_
 #define RUNTIME_VM_MESSAGE_H_
 
+#include <memory>
+
 #include "platform/assert.h"
 #include "vm/allocation.h"
 #include "vm/finalizable_data.h"
@@ -61,6 +63,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 +121,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..9bf957d 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;
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..f81220e 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_;
+  uint32_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..9e94f0d 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 {
@@ -902,6 +902,18 @@
   implicit_setter_bytecode_->set_exception_handlers(
       Object::empty_exception_handlers());
 
+  static const KBCInstr static_getter_instr[2] = {
+      KernelBytecode::Encode(KernelBytecode::kVMInternal_ImplicitStaticGetter),
+      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
+  };
+  *implicit_static_getter_bytecode_ = Bytecode::New(
+      reinterpret_cast<uword>(static_getter_instr), sizeof(static_getter_instr),
+      -1, Object::empty_object_pool());
+  implicit_static_getter_bytecode_->set_pc_descriptors(
+      Object::empty_descriptors());
+  implicit_static_getter_bytecode_->set_exception_handlers(
+      Object::empty_exception_handlers());
+
   static const KBCInstr method_extractor_instr[2] = {
       KernelBytecode::Encode(KernelBytecode::kVMInternal_MethodExtractor),
       KernelBytecode::Encode(KernelBytecode::kReturnTOS),
@@ -913,6 +925,40 @@
   method_extractor_bytecode_->set_exception_handlers(
       Object::empty_exception_handlers());
 
+  static const KBCInstr invoke_closure_instr[2] = {
+      KernelBytecode::Encode(KernelBytecode::kVMInternal_InvokeClosure),
+      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
+  };
+  *invoke_closure_bytecode_ = Bytecode::New(
+      reinterpret_cast<uword>(invoke_closure_instr),
+      sizeof(invoke_closure_instr), -1, Object::empty_object_pool());
+  invoke_closure_bytecode_->set_pc_descriptors(Object::empty_descriptors());
+  invoke_closure_bytecode_->set_exception_handlers(
+      Object::empty_exception_handlers());
+
+  static const KBCInstr invoke_field_instr[2] = {
+      KernelBytecode::Encode(KernelBytecode::kVMInternal_InvokeField),
+      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
+  };
+  *invoke_field_bytecode_ = Bytecode::New(
+      reinterpret_cast<uword>(invoke_field_instr), sizeof(invoke_field_instr),
+      -1, Object::empty_object_pool());
+  invoke_field_bytecode_->set_pc_descriptors(Object::empty_descriptors());
+  invoke_field_bytecode_->set_exception_handlers(
+      Object::empty_exception_handlers());
+
+  static const KBCInstr nsm_dispatcher_instr[2] = {
+      KernelBytecode::Encode(
+          KernelBytecode::kVMInternal_NoSuchMethodDispatcher),
+      KernelBytecode::Encode(KernelBytecode::kReturnTOS),
+  };
+  *nsm_dispatcher_bytecode_ = Bytecode::New(
+      reinterpret_cast<uword>(nsm_dispatcher_instr),
+      sizeof(nsm_dispatcher_instr), -1, Object::empty_object_pool());
+  nsm_dispatcher_bytecode_->set_pc_descriptors(Object::empty_descriptors());
+  nsm_dispatcher_bytecode_->set_exception_handlers(
+      Object::empty_exception_handlers());
+
   // Some thread fields need to be reinitialized as null constants have not been
   // initialized until now.
   Thread* thr = Thread::Current();
@@ -974,8 +1020,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 +1507,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);
@@ -2528,13 +2582,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 +2611,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 +2634,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();
@@ -2756,7 +2810,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 +2888,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,7 +3041,7 @@
   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();
@@ -3425,7 +3479,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 +3502,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())) {
@@ -4502,7 +4556,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 +4588,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 +4608,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 +4643,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 +4680,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 +4702,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 +4728,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 +5573,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 +5746,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;
   }
@@ -5724,14 +5774,6 @@
     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 +5967,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 +5976,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());
@@ -6160,8 +6202,8 @@
     case RawFunction::kImplicitSetter:
       return "ImplicitSetter";
       break;
-    case RawFunction::kImplicitStaticFinalGetter:
-      return "ImplicitStaticFinalGetter";
+    case RawFunction::kImplicitStaticGetter:
+      return "ImplicitStaticGetter";
       break;
     case RawFunction::kStaticFieldInitializer:
       return "StaticFieldInitializer";
@@ -6407,7 +6449,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 +6462,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 +6480,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 +6498,7 @@
       // function with identical type parameters.
       break;
     }
-    function ^= function.parent_function();
+    function = function.parent_function();
     if (function_level != NULL) {
       (*function_level)--;
     }
@@ -6714,7 +6756,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 +6795,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 +6807,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 +6833,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 +6847,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 +7022,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();
@@ -7866,6 +7908,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 +8112,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";
@@ -9449,15 +9494,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 +10397,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 +10491,7 @@
       AddScriptIfUnique(scripts, owner_script);
     }
 
-    cls ^= toplevel_class();
+    cls = toplevel_class();
     if (!cls.IsNull()) {
       owner_script = cls.script();
       AddScriptIfUnique(scripts, owner_script);
@@ -10610,7 +10658,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 +11103,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 +11143,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())) {
@@ -11944,12 +11992,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 +12128,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 +12151,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 +12177,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 +12200,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);
@@ -14820,7 +14868,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 +14927,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()) {
@@ -15146,35 +15194,41 @@
                                                   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);
@@ -15200,7 +15254,7 @@
   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 +15660,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 +15969,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 +16027,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 +16083,7 @@
 
   TypeArguments& type_args = TypeArguments::Handle(zone);
   if (klass.NumTypeArguments() > 0) {
-    type_args ^= GetTypeArguments();
+    type_args = GetTypeArguments();
   }
 
   if (function.IsNull()) {
@@ -16230,7 +16284,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 +16293,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 +17293,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 +17654,7 @@
           if (this->IsNew()) {
             type ^= Object::Clone(*this, Heap::kOld);
           } else {
-            type ^= this->raw();
+            type = this->raw();
           }
           ASSERT(type.IsOld());
           type.ComputeHash();
@@ -17675,7 +17729,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 +18674,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 +18682,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 +18807,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 +18815,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 +20449,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 +21178,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 +21224,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);
 }
@@ -21570,7 +21624,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 +21694,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 +21757,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 +21817,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 +21826,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 +21953,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..8974dd0 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)                                                \
@@ -1969,9 +1973,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 {
@@ -2151,7 +2152,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 +2173,7 @@
   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;
 #endif
 
   virtual intptr_t Hash() const;
@@ -2218,7 +2219,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 +2297,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 +2316,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 +2531,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 +2600,7 @@
     switch (kind()) {
       case RawFunction::kImplicitGetter:
       case RawFunction::kImplicitSetter:
-      case RawFunction::kImplicitStaticFinalGetter:
+      case RawFunction::kImplicitStaticGetter:
       case RawFunction::kNoSuchMethodDispatcher:
       case RawFunction::kInvokeFieldDispatcher:
       case RawFunction::kDynamicInvocationForwarder:
@@ -3140,8 +3145,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 +3384,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);
   }
@@ -4398,8 +4416,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;
@@ -5528,13 +5546,17 @@
            (kWordSize * context_index);
   }
 
+  static bool IsValidLength(intptr_t len) {
+    return 0 <= len && len <= 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));
   }
 
@@ -7447,8 +7469,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
 };
@@ -8009,6 +8029,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 +8041,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));
   }
 
@@ -9106,6 +9130,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 +9192,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 +9206,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 +9273,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 +9330,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 +9477,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..cab61e5 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);
@@ -1487,8 +1487,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..ace33b6 100644
--- a/runtime/vm/object_test.cc
+++ b/runtime/vm/object_test.cc
@@ -2488,7 +2488,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 +2525,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 +3113,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..58acf87 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) {
@@ -252,8 +264,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_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_macos.cc b/runtime/vm/os_thread_macos.cc
index eecfe67..50a2952 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 {
@@ -86,6 +88,20 @@
   DISALLOW_COPY_AND_ASSIGN(ThreadStartData);
 };
 
+// Spawned threads inherit their spawner's signal mask. We sometimes spawn
+// threads for running Dart code from a thread that is blocking SIGPROF.
+// This function explicitly unblocks SIGPROF so the profiler continues to
+// sample this thread.
+static void UnblockSIGPROF() {
+  sigset_t set;
+  sigemptyset(&set);
+  sigaddset(&set, SIGPROF);
+  int r = pthread_sigmask(SIG_UNBLOCK, &set, NULL);
+  USE(r);
+  ASSERT(r == 0);
+  ASSERT(!CHECK_IS_BLOCKING(SIGPROF));
+}
+
 // Dispatch to the thread start function provided by the caller. This trampoline
 // is used to ensure that the thread is properly destroyed if the thread just
 // exits.
@@ -105,7 +121,7 @@
   if (thread != NULL) {
     OSThread::SetCurrent(thread);
     thread->set_name(name);
-
+    UnblockSIGPROF();
     // 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..ed05a74 100644
--- a/runtime/vm/profiler.cc
+++ b/runtime/vm/profiler.cc
@@ -791,7 +791,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 +806,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_service.cc b/runtime/vm/profiler_service.cc
index a92e31e..b06927d 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);
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..27d808f 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)
@@ -495,73 +496,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);
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index ffff441..75e7a92 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -693,7 +693,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;
@@ -847,10 +846,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 +874,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.
 
@@ -1329,7 +1323,6 @@
   friend class Function;
   template <bool>
   friend class MarkingVisitorBase;
-  friend class SkippedCodeFunctions;
   friend class StackFrame;
   friend class Profiler;
   friend class FunctionDeserializationCluster;
@@ -1415,7 +1408,6 @@
   friend class StackFrame;
   template <bool>
   friend class MarkingVisitorBase;
-  friend class SkippedCodeFunctions;
   friend class Function;
   friend class ImageReader;
   friend class ImageWriter;
@@ -2436,11 +2428,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_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 20e3983..296b478 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -42,7 +42,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 +316,7 @@
 
   // Set the canonical bit.
   if (is_canonical) {
-    type_arguments ^= type_arguments.Canonicalize();
+    type_arguments = type_arguments.Canonicalize();
   }
 
   return type_arguments.raw();
@@ -738,7 +738,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 +1226,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);
@@ -2172,7 +2172,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 +2204,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/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index da70f90..1a7ba2e 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -237,7 +237,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 =
@@ -1067,7 +1067,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 +1670,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 +1717,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 +1745,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 +1778,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);
 }
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index bb2eca9..dd4159d 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,7 +79,9 @@
   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)
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index e96f9a5..50ba1c5 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 {
@@ -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/service.md b/runtime/vm/service/service.md
index e3c2fd1..a04b348 100644
--- a/runtime/vm/service/service.md
+++ b/runtime/vm/service/service.md
@@ -2453,6 +2453,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];
diff --git a/runtime/vm/service/service_dev.md b/runtime/vm/service/service_dev.md
index dbfa952..2b4edd8 100644
--- a/runtime/vm/service/service_dev.md
+++ b/runtime/vm/service/service_dev.md
@@ -2453,6 +2453,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];
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..52c385d 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -16,6 +16,7 @@
 
 #include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/backend/locations.h"
 #include "vm/compiler/jit/compiler.h"
 #include "vm/constants_dbc.h"
 #include "vm/cpu.h"
@@ -2107,6 +2108,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 +2435,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 +2676,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 +2715,7 @@
 
     BYTECODE(ReturnTOS, 0);
     result = *SP;
-  // Fall through to the ReturnImpl.
+    // Fall through to the ReturnImpl.
 
   ReturnImpl:
     // Restore caller PC.
@@ -3018,7 +3103,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;
@@ -4040,8 +4125,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 +4157,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/snapshot.cc b/runtime/vm/snapshot.cc
index c676560..aeb1714 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -1461,15 +1461,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) {
@@ -1486,8 +1487,8 @@
 
   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..995afc7 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -728,22 +728,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 +747,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..8f0e9cf 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:
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_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_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..6c84a32 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -181,9 +181,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 +207,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..7f93f5b8 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)                                          \
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/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..3fa4cff 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,7 +59,7 @@
   const char* fuchsia_name() const { return fuchsia_name_; }
 
   bool enabled() {
-#if defined(HOST_OS_FUCHSIA)
+#if defined(HOST_OS_FUCHSIA) && !defined(FUCHSIA_SDK)
     return trace_is_category_enabled(fuchsia_name_);
 #else
     return enabled_ != 0;
@@ -78,7 +78,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 +90,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 +907,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..1b78344 100644
--- a/runtime/vm/type_testing_stubs.cc
+++ b/runtime/vm/type_testing_stubs.cc
@@ -814,7 +814,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/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_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..398ecc8 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 {
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/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..cc283ee 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -46,6 +46,7 @@
   "constants_arm.h",
   "constants_arm64.cc",
   "constants_arm64.h",
+  "constants_dbc.cc",
   "constants_dbc.h",
   "constants_ia32.cc",
   "constants_ia32.h",
@@ -345,7 +346,6 @@
   "unibrow.cc",
   "unibrow.h",
   "unicode.cc",
-  "unicode.h",
   "unicode_data.cc",
   "uri.cc",
   "uri.h",
diff --git a/runtime/vm/zone.cc b/runtime/vm/zone.cc
index 2d95479..595871a 100644
--- a/runtime/vm/zone.cc
+++ b/runtime/vm/zone.cc
@@ -337,11 +337,20 @@
                  reinterpret_cast<intptr_t>(this),
                  reinterpret_cast<intptr_t>(&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() {
+  // 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) {
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/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/lib/_internal/js_runtime/lib/core_patch.dart b/sdk/lib/_internal/js_runtime/lib/core_patch.dart
index e31fe29..998f42b 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);
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/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/core/regexp.dart b/sdk/lib/core/regexp.dart
index c0bd153..b604413 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,
+      bool unicode = false,
+      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,33 @@
    * 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.
+   */
+  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.
+   */
+  bool get isDotAll;
 }
 
 /**
diff --git a/sdk/lib/io/socket.dart b/sdk/lib/io/socket.dart
index 02fb46a..ec03664 100644
--- a/sdk/lib/io/socket.dart
+++ b/sdk/lib/io/socket.dart
@@ -556,8 +556,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> {
   /**
@@ -830,12 +835,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/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index e637ca2..b1086d7 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
@@ -1168,7 +1177,6 @@
 [ $strong && ($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/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..e0b3aea 100644
--- a/tests/compiler/dart2js/codegen/is_function_test.dart
+++ b/tests/compiler/dart2js/codegen/is_function_test.dart
@@ -24,7 +24,7 @@
         memorySourceFiles: {'main.dart': SOURCE}, options: options);
     Expect.isTrue(result.isSuccess);
     Compiler compiler = result.compiler;
-    Program program = compiler.backend.emitter.emitter.programForTesting;
+    Program program = compiler.backend.emitterTask.emitter.programForTesting;
     var name = compiler.backend.namer.operatorIs(
         compiler.backendClosedWorldForTesting.commonElements.functionClass);
     for (Fragment fragment in program.fragments) {
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/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/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/end_to_end/exit_code_test.dart b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
index aea5404..fbae05a 100644
--- a/tests/compiler/dart2js/end_to_end/exit_code_test.dart
+++ b/tests/compiler/dart2js/end_to_end/exit_code_test.dart
@@ -110,10 +110,10 @@
             useNewSourceInfo: compiler.options.useNewSourceInfo);
 
   @override
-  WorldImpact codegen(CodegenWorkItem work, JClosedWorld closedWorld,
-      GlobalTypeInferenceResults results) {
+  WorldImpact generateCode(CodegenWorkItem work, JClosedWorld closedWorld,
+      GlobalTypeInferenceResults results, CodegenInputs codegen) {
     compiler.test('Compiler.codegen');
-    return super.codegen(work, closedWorld, results);
+    return super.generateCode(work, closedWorld, results, codegen);
   }
 }
 
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..6aff382 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -43,7 +43,7 @@
   final Namer namer;
 
   ProgramLookup(Compiler compiler)
-      : this.program = compiler.backend.emitter.emitter.programForTesting,
+      : this.program = compiler.backend.emitterTask.emitter.programForTesting,
         this.namer = compiler.backend.namer;
 
   Fragment getFragment(OutputUnit outputUnit) {
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/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_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/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/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/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/type_representation_test.dart b/tests/compiler/dart2js/rti/type_representation_test.dart
index d93fab1..97bd3d6 100644
--- a/tests/compiler/dart2js/rti/type_representation_test.dart
+++ b/tests/compiler/dart2js/rti/type_representation_test.dart
@@ -85,12 +85,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,8 +104,8 @@
   }
 
   String getJsName(Entity cls) {
-    Expression name =
-        typeRepresentation.getJavaScriptClassName(cls, backend.emitter.emitter);
+    Expression name = typeRepresentation.getJavaScriptClassName(
+        cls, backend.emitterTask.emitter);
     return stringify(name);
   }
 
@@ -199,44 +205,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/static_type/data/closure.dart b/tests/compiler/dart2js/static_type/data/closure.dart
index b8768de..0878854 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) {
@@ -65,6 +68,22 @@
       /*dynamic*/ c.next;
     }
 
+    /*Class*/ c.next;
+    /*invoke: Null*/ local();
+    /*Class*/ c.next;
+    c = 0;
+    /*dynamic*/ c.next;
+  }
+}
+
+closure4a(dynamic c) {
+  if (/*dynamic*/ c is Class) {
+    /*Class*/ c.next;
+    local() {
+      /*dynamic*/ c.next;
+      c = 0;
+    }
+
     /*dynamic*/ c.next;
     /*invoke: Null*/ local();
     /*dynamic*/ c.next;
@@ -87,3 +106,55 @@
   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*/ f());
+  /*dynamic*/ x;
+  x = new A();
+  /*dynamic*/ closure. /*invoke: 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: dynamic*/ f()
+      : x = new C();
+  _returnTrue((() => /*C*/ x)) && /*C*/ x is D
+      ? /*D*/ x. /*invoke: dynamic*/ f()
+      : x = new C();
+
+  (/*C*/ x is D && _returnTrue((() => /*C*/ x))) &&
+          (/*D*/ x is E && _returnTrue((() => /*C*/ x)))
+      ? /*E*/ x. /*invoke: dynamic*/ g()
+      : x = new C();
+
+  (_returnTrue((() => /*C*/ x)) && /*C*/ x is E) &&
+          (_returnTrue((() => /*C*/ x)) && /*E*/ x is D)
+      ? /*E*/ x. /*invoke: dynamic*/ g()
+      : x = new C();
+}
+
+closure7() {
+  _closure7(new D());
+  _closure7(new E());
+}
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/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..58ec517 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();
 }
 
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/block_expression_on_field_test.dart b/tests/compiler/dart2js_extra/block_expression_on_field_test.dart
new file mode 100644
index 0000000..7b6449f
--- /dev/null
+++ b/tests/compiler/dart2js_extra/block_expression_on_field_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.
+
+/// Regression test for #36864
+///
+/// Block expressions in top-level fields used to crash the compiler.
+import "package:expect/expect.dart";
+
+final _a = {
+  ...{1}
+};
+
+class B {
+  static Set _b = {
+    ...{2}
+  };
+  Set _c = {
+    ...{3}
+  };
+}
+
+main() {
+  Expect.setEquals({1}, _a);
+  Expect.setEquals({2}, B._b);
+  Expect.setEquals({3}, (new B()._c));
+}
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/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/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_null_test.dart b/tests/language_2/control_flow_collections/await_for_null_test.dart
index 7e2fc5e..b2ba223 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
@@ -11,11 +11,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/if_const_error_test.dart b/tests/language_2/control_flow_collections/if_const_error_test.dart
index f3645f2..c644acf 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=control-flow-collections,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..917d9f4
--- /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=control-flow-collections
+
+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..db38174
--- /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=control-flow-collections,spread-collections,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/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/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/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/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/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/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..9ef8798
--- /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}) => null;
+}
+
+class B extends A { B() : super(); } //# 02: compile-time error
+
+void f({required int a}) {}
+
+void Function({required int a}) g() => null;
+
+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_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/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/const_error_test.dart b/tests/language_2/spread_collections/const_error_test.dart
index c186f13..f1d6920 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=spread-collections,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..6bf98fe
--- /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=spread-collections
+
+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..dccfab2
--- /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=spread-collections,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/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/unsigned_right_shift_test.dart b/tests/language_2/unsigned_right_shift_test.dart
index 64d46d0..a487465 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 / *}");
+  Expect.equals("((*>>*)>>>*)>>*)", "${a >> a >>> a >> *}");
+  Expect.equals("((*&(*>>>*))&*)", "${a & a >>> a & *}");
+  Expect.equals("((*|(*>>>*)|)*)", "${a | a >>> a | *}");
+  Expect.equals("((*^(*>>>*)^)*)", "${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/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..cd14026 100644
--- a/tests/language_2/vm/osr_nonempty_stack_test.dart
+++ b/tests/language_2/vm/osr_nonempty_stack_test.dart
@@ -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/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/lib_2_kernel.status b/tests/lib_2/lib_2_kernel.status
index 04313d4..b582fa7 100644
--- a/tests/lib_2/lib_2_kernel.status
+++ b/tests/lib_2/lib_2_kernel.status
@@ -172,7 +172,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
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/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index ceb859a..5bece55 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -73,7 +73,6 @@
 
 # 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.
diff --git a/tests/standalone_2/standalone_2_precompiled.status b/tests/standalone_2/standalone_2_precompiled.status
index 64e4609..3209e7b 100644
--- a/tests/standalone_2/standalone_2_precompiled.status
+++ b/tests/standalone_2/standalone_2_precompiled.status
@@ -79,5 +79,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..f6f03df 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
@@ -93,7 +92,6 @@
 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 +99,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/tools/VERSION b/tools/VERSION
index 3cbb7b3..9bf1a57 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -32,8 +32,8 @@
 CHANNEL dev
 MAJOR 2
 MINOR 3
-PATCH 0
+PATCH 1
 PRERELEASE 0
-PRERELEASE_PATCH 5
+PRERELEASE_PATCH 0
 ABI_VERSION 4
-OLDEST_SUPPORTED_ABI_VERSION 1
+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..e39d0d6 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -318,7 +318,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 +392,7 @@
         },
         {
           "name": "unit tests",
+          "script": "tools/disguised_test.py",
           "arguments": [
             "-nunittest-asserts-${mode}-${system}",
              "pkg/(kernel|front_end|fasta)"
@@ -1346,6 +1347,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 +1369,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 +1395,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"
+          ]
         }
       ]
     },
@@ -1674,7 +1725,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 +1759,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 +1969,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/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/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/make_version.py b/tools/make_version.py
index d63dfa8..4bb7f75 100755
--- a/tools/make_version.py
+++ b/tools/make_version.py
@@ -67,9 +67,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(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 +81,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()
@@ -114,6 +118,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 +135,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 +150,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/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/testing/dart/compiler_configuration.dart b/tools/testing/dart/compiler_configuration.dart
index 9edb9fb..f3fee45 100644
--- a/tools/testing/dart/compiler_configuration.dart
+++ b/tools/testing/dart/compiler_configuration.dart
@@ -712,15 +712,17 @@
   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>[];
diff --git a/tools/testing/dart/configuration.dart b/tools/testing/dart/configuration.dart
index 85a0433..fac39a9 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,
@@ -125,6 +126,7 @@
   final String firefoxPath;
   final String dartPath;
   final String dartPrecompiledPath;
+  final String genSnapshotPath;
   final List<String> testList;
 
   final int taskCount;
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index 67f5b27..bf979ac 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -229,6 +229,7 @@
         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),
@@ -727,6 +728,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/test_runner.dart b/tools/testing/dart/test_runner.dart
index 6deb34a..ed69296 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;
diff --git a/tools/testing/dart/test_suite.dart b/tools/testing/dart/test_suite.dart
index b3ad21d..6202455 100644
--- a/tools/testing/dart/test_suite.dart
+++ b/tools/testing/dart/test_suite.dart
@@ -451,22 +451,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 +504,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 +521,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 +544,7 @@
   bool hasCompileError;
   bool hasRuntimeError;
   bool hasStaticWarning;
+  bool hasCrash;
   String multitestKey;
 
   TestInformation(
@@ -519,7 +555,8 @@
       this.hasCompileError,
       this.hasRuntimeError,
       this.hasStaticWarning,
-      {this.multitestKey: ''}) {
+      {this.multitestKey: '',
+      this.hasCrash: false}) {
     assert(filePath.isAbsolute);
   }
 }
diff --git a/tools/utils.py b/tools/utils.py
index 32d843e..7b69465 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()
@@ -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/bazel/kernel_worker.dart b/utils/bazel/kernel_worker.dart
index 53cf818..2ff11ba 100644
--- a/utils/bazel/kernel_worker.dart
+++ b/utils/bazel/kernel_worker.dart
@@ -16,10 +16,13 @@
 import 'package:bazel_worker/bazel_worker.dart';
 import 'package:build_integration/file_system/multi_root.dart';
 import 'package:dev_compiler/src/kernel/target.dart';
+import 'package:dev_compiler/src/flutter/track_widget_constructor_locations.dart';
 import 'package:front_end/src/api_unstable/bazel_worker.dart' as fe;
 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 +56,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 +110,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 +128,8 @@
   ..addMultiOption('source')
   ..addOption('output')
   ..addFlag('reuse-compiler-result', defaultsTo: false)
-  ..addFlag('use-incremental-compiler', defaultsTo: false);
+  ..addFlag('use-incremental-compiler', defaultsTo: false)
+  ..addFlag('track-kernel-creation', defaultsTo: false);
 
 class ComputeKernelResult {
   final bool succeeded;
@@ -176,6 +173,13 @@
   var excludeNonSources = parsedArgs['exclude-non-sources'] as bool;
 
   var summaryOnly = parsedArgs['summary-only'] as bool;
+  var trackKernelCreation = parsedArgs['track-kernel-creation'] as bool;
+
+  if (summaryOnly && trackKernelCreation) {
+    throw new ArgumentError('error: --summary-only is not compatible with '
+        '--track-kernel-creation');
+  }
+
   // TODO(sigmund,jakemac): make target mandatory. We allow null to be backwards
   // compatible while we migrate existing clients of this tool.
   var targetName =
@@ -189,6 +193,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) {
@@ -278,13 +296,23 @@
         incrementalComponent.problemsAsJson = null;
         incrementalComponent.mainMethod = null;
         target.performOutlineTransformations(incrementalComponent);
+      } else if (trackKernelCreation) {
+        (new WidgetCreatorTracker()).transform(incrementalComponent);
       }
 
       return Future.value(fe.serializeComponent(incrementalComponent));
     });
+  } else if (summaryOnly) {
+    kernel = await fe.compileSummary(state, sources, onDiagnostic);
   } else {
-    kernel = await fe.compile(state, sources, onDiagnostic,
-        summaryOnly: summaryOnly);
+    Component component =
+        await fe.compileComponent(state, sources, onDiagnostic);
+
+    if (trackKernelCreation) {
+      (new WidgetCreatorTracker()).transform(component);
+    }
+    kernel = fe.serializeComponent(component,
+        filter: (library) => sources.contains(library.importUri));
   }
 
   if (kernel != null) {