Version 2.2.0-dev.2.0

Merge commit 'c92d5ca288da15b54b04c0a40ffe5d94a8883d77' into dev
diff --git a/.gitignore b/.gitignore
index 3e23d6d..2e3efaa3 100644
--- a/.gitignore
+++ b/.gitignore
@@ -37,6 +37,7 @@
 .idea
 CMakeLists.txt
 .clang_complete
+cmake-build-debug
 
 # VSCode project files
 .vscode
@@ -49,6 +50,9 @@
 # GDB files
 .gdb_history
 
+# https://github.com/Dart-Code/Dart-Code/issues/1295
+analysis_options.yaml
+
 # Built by chromebot and downloaded from Google Storage
 client/tests/drt
 
diff --git a/.packages b/.packages
index 9d7e756..a686ef2 100644
--- a/.packages
+++ b/.packages
@@ -8,6 +8,7 @@
 #
 analysis_server:pkg/analysis_server/lib
 analysis_server_client:pkg/analysis_server_client/lib
+analysis_tool:pkg/analysis_tool/lib
 analyzer:pkg/analyzer/lib
 analyzer_cli:pkg/analyzer_cli/lib
 analyzer_fe_comparison:pkg/analyzer_fe_comparison/lib
diff --git a/BUILD.gn b/BUILD.gn
index ae4c230..6d899ee 100644
--- a/BUILD.gn
+++ b/BUILD.gn
@@ -47,6 +47,8 @@
     "runtime/bin:sample_extension",
     "runtime/bin:test_extension",
     "runtime/bin:entrypoints_verification_test_extension",
+    "runtime/bin:ffi_test_dynamic_library",
+    "runtime/bin:ffi_test_functions",
     "runtime/vm:kernel_platform_files($host_toolchain)",
     "utils/kernel-service:kernel-service",
   ]
diff --git a/CHANGELOG.md b/CHANGELOG.md
index dc9f141..44b7ec9 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,29 +1,103 @@
-## 2.1.2-dev.0.0
+## 2.2.0-dev.2.0
 
-* Merge commit 011a1239fc4c0ed140ddce4773cc791da1936cd4 into dev
+### Language
 
-## 2.1.1
+Sets now have a literal syntax like lists and maps do:
 
-* Identical to 2.1.1-dev.3.2
+```dart
+var set = {1, 2, 3};
+```
 
-## 2.1.1-dev.3.2
+Using curly braces makes empty sets ambiguous with maps:
 
-* Cherry-pick 9d25cc93e850d4717cdc9e1c4bd3623e09c16d47 to dev
+```dart
+var collection = {}; // Empty set or map?
+```
 
-## 2.1.1-dev.3.1
+To avoid breaking existing code, an ambiguous literal is treated as a map.
+To create an empty set, you can rely on either a surrounding context type
+or an explicit type argument:
 
-* Cherry-pick 46080dd886a622c5520895d49c97506ecedb1df8 to dev
-* Cherry-pick fc62cf037343248c5ace87629d8eb1063f9f2428 to dev
-* Cherry-pick 770ab5275ac34af62d7c39da8eac8c56fdc48edb to dev
-* Cherry-pick 957e194735bda4fcf06cdcc68fa80f3290b17d79 to dev
+```dart
+// Variable type forces this to be a set:
+Set<int> set = {};
 
-## 2.1.1-dev.3.0
+// A single type argument means this must be a set:
+var set2 = <int>{};
+```
 
-* Cherry-pick 3cb16d20e7810a2a378bb897d939f67c0b380d88 to dev
+Set literals are released on all platforms. The `set-literals` experiment flag
+has been disabled.
 
-## 2.1.1-dev.2.0
+### Tools
 
-### Core library changes
+#### Analyzer
+
+*   The `DEPRECATED_MEMBER_USE` hint was split into two hints:
+
+    *   `DEPRECATED_MEMBER_USE` reports on usage of `@deprecated` members
+        declared in a different package.
+    *   `DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE` reports on usage of
+        `@deprecated` members declared in the same package.
+
+#### Linter
+
+Upgraded the linter to `0.1.82` which adds the following improvements:
+
+*   Added `provide_deprecation_message`, and
+    `use_full_hex_values_for_flutter_colors`, `prefer_null_aware_operators`.
+*   Fixed `prefer_const_declarations` set literal false-positives.
+*   Updated `prefer_collection_literals` to support set literals.
+*   Updated `unnecessary_parenthesis` play nicer with cascades.
+*   Removed deprecated lints from the "all options" sample.
+*   Stopped registering "default lints".
+*   Fixed `hash_and_equals` to respect `hashCode` fields.
+
+### Other libraries
+
+#### `package:kernel`
+
+*   **Breaking change:** The `klass` getter on the `InstanceConstant` class in
+    the Kernel AST API has been renamed to `classNode` for consistency.
+
+*   **Breaking change:** Updated `Link` implementation to utilize true symbolic
+    links instead of junctions on Windows. Existing junctions will continue to
+    work with the new `Link` implementation, but all new links will create
+    symbolic links.
+
+    To create a symbolic link, Dart must be run with administrative privileges
+    or Developer Mode must be enabled, otherwise a `FileSystemException` will be
+    raised with errno set to `ERROR_PRIVILEGE_NOT_HELD` (Issue [33966]).
+
+[33966]: https://github.com/dart-lang/sdk/issues/33966
+
+## 2.1.1 - 2019-02-18
+
+This is a patch version release. Again, the team's focus was mostly on improving
+performance and stability after the large changes in Dart 2.0.0. In particular,
+dart2js now always uses the "fast startup" emitter and the old emitter has been
+removed.
+
+There are a couple of very minor **breaking changes:**
+
+*   In `dart:io`, adding to a closed `IOSink` now throws a `StateError`.
+
+*   On the Dart VM, a soundness hole when using `dart:mirrors` to reflectively
+    invoke a method in an incorrect way that violates its static types has
+    been fixed (Issue [35611][]).
+
+### Language
+
+This release has no language changes.
+
+### Core library
+
+#### `dart:core`
+
+*   Made `DateTime.parse()` also recognize `,` as a valid decimal separator
+    when parsing from a string (Issue [35576][]).
+
+[35576]: https://github.com/dart-lang/sdk/issues/35576
 
 #### `dart:html`
 
@@ -32,10 +106,10 @@
 *   Improved dart2js compilation of `element.attributes.remove(name)` to
     generate `element.removeAttribute(name)`, so that there is no performance
     reason to migrate to the above methods.
-*   Fixed a number of `dart:html` P1 bugs:
+*   Fixed a number of `dart:html` bugs:
 
     *   Fixed HTML API's with callback typedef to correctly convert Dart
-        function to JS function (Issue [35484]).
+        functions to JS functions (Issue [35484]).
     *   HttpStatus constants exposed in `dart:html` (Issue [34318]).
     *   Expose DomName `ondblclick` and `dblclickEvent` for Angular analyzer.
     *   Fixed `removeAll` on `classes`; `elements` parameter should be
@@ -54,110 +128,16 @@
 
 #### `dart:io`
 
+*   **Breaking Change:** Adding to a closed `IOSink` now throws a `StateError`.
 *   Added ability to get and set low level socket options.
-* **Breaking Change:** Adding to a closed `IOSink` now throws a `StateError`.
 
 [29554]: https://github.com/dart-lang/sdk/issues/29554
 
-### Other library changes
-
-#### `package:kernel`
-
-*   **Breaking change:** The `klass` getter on the `InstanceConstant` class in
-    the Kernel AST API has been renamed to `classNode` for consistency.
-
-*   **Breaking change:** Updated `Link` implementation to utilize true symbolic
-    links instead of junctions on Windows. Existing junctions will continue to
-    work with the new `Link` implementation, but all new links will create
-    symbolic links.
-    
-    To create a symbolic link, Dart must be run with
-    administrative privileges or Developer Mode must be enabled, otherwise a
-    `FileSystemException` will be raised with errno set to
-    `ERROR_PRIVILEGE_NOT_HELD` (Issue [33966]).
-
-[33966]: https://github.com/dart-lang/sdk/issues/33966
-
-### Dart VM
-
-### Tool Changes
-
-#### Analyzer
-
-*   The `DEPRECATED_MEMBER_USE` hint was split into two hints:
-
-    *   `DEPRECATED_MEMBER_USE` reports on usage of `@deprecated` members
-        declared in a different package.
-    *   `DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE` reports on usage of
-        `@deprecated` members declared in the same package.
-
-### Linter
-
-The linter was bumped to `0.1.79` which introduces the following linter improvements to the SDK:
-
-* `unnecessary_parenthesis` updated to play nicer with cascades
-* new lint: `use_full_hex_values_for_flutter_colors`
-* new lint: `prefer_null_aware_operators`
-* miscellaneous documentation fixes
-* removed deprecated lints from the "all options" sample
-* stopped registering "default lints"
-* `hash_and_equals` fixed to respect `hashCode` fields
-
-
-#### Other Tools
-
-## 2.1.1-dev.3.2
-
-* Cherry-pick 9d25cc93e850d4717cdc9e1c4bd3623e09c16d47 to dev
-
-## 2.1.1-dev.3.1
-
-* Cherry-pick 46080dd886a622c5520895d49c97506ecedb1df8 to dev
-* Cherry-pick fc62cf037343248c5ace87629d8eb1063f9f2428 to dev
-* Cherry-pick 770ab5275ac34af62d7c39da8eac8c56fdc48edb to dev
-* Cherry-pick 957e194735bda4fcf06cdcc68fa80f3290b17d79 to dev
-
-## 2.1.1-dev.3.0
-
-* Cherry-pick 3cb16d20e7810a2a378bb897d939f67c0b380d88 to dev
-
-## 2.1.1-dev.2.0
-
-### Core library changes
-
-#### `dart:core`
-
-*   Made `DateTime.parse()` also recognize `,` as a valid decimal separator
-    when parsing from a string. (Issue [35576][])
-
-[35576]: https://github.com/dart-lang/sdk/issues/35576
-
-### Tool Changes
-
-#### Analyzer
-
-*   New hints added:
-
-    *   `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR` and
-        `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW` when a `@literal`
-        const constructor is called in a non-const context (or with `new`).
-
-#### dart2js
-
-* `--fast-startup` is forced on.  The flag is silently ignored and will be
-  deprecated and then removed at a later date.
-
-  The alternative 'full emitter' is no longer available. The generated code for
-  `--fast-startup` is optimized to load faster, even though it can be slightly
-  larger.
-
-## 2.1.1-dev.1.0
-
 ### Dart VM
 
 In previous releases it was possible to violate static types using
-`dart:mirrors` but this bug is fixed now. Meaning that the code below would run
-without any TypeErrors and print "impossible" output.
+`dart:mirrors`. This code would run without any TypeErrors and print
+"impossible" output:
 
 ```dart
 import 'dart:mirrors';
@@ -176,11 +156,89 @@
 }
 ```
 
-Only code that already violates static typing will break.
+This bug is fixed now. Only code that already violates static typing will break.
+See Issue [35611][] for more details.
 
-See Issue [#35611](https://github.com/dart-lang/sdk/issues/35611) for more details.
+[35611]: https://github.com/dart-lang/sdk/issues/35611
 
-### Tool Changes
+### Dart for the Web
+
+#### dart2js
+
+*   The old "full emitter" back-end is removed and dart2js always uses the "fast
+    startup" back-end. The generated fast startup code is optimized to load
+    faster, even though it can be slightly larger. The `--fast-startup` and
+    `--no-fast-startup` are allowed but ignored. They will be removed in a
+    future version.
+
+*   We fixed a bug in how deferred constructor calls were incorrectly not marked
+    as deferred. The old behavior didn't cause breakages, but was imprecise and
+    pushed more code to the main output unit.
+
+*   A new deferred split algorithm implementation was added.
+
+    This implementation fixes a soundness bug and addresses performance issues
+    of the previous implementation, because of that it can have a visible impact
+    on apps. In particular:
+
+    *   We fixed a performance issue which was introduced when we migrated to
+        the common front-end. On large apps, the fix can cut 2/3 of the time
+        spent on this task.
+
+    *   We fixed a bug in how inferred types were categorized (Issue [35311][]).
+        The old behavior was unsound and could produce broken programs. The fix
+        may cause more code to be pulled into the main output unit.
+
+        This shows up frequently when returning deferred values from closures
+        since the closure's inferred return type is the deferred type. For
+        example, if you have:
+
+        ```dart
+        () async {
+          await deferred_prefix.loadLibrary();
+          return new deferred_prefix.Foo();
+        }
+        ```
+
+        The closure's return type is `Future<Foo>`. The old implementation
+        defers `Foo`, and incorrectly makes the return type `Future<dynamic>`.
+        This may break in places where the correct type is expected.
+
+        The new implementation will not defer `Foo`, and will place it in the
+        main output unit. If your intent is to defer it, then you need to ensure
+        the return type is not inferred to be `Foo`. For example, you can do so
+        by changing the code to a named closure with a declared type, or by
+        ensuring that the return expression has the type you want, like:
+
+        ```dart
+        () async {
+          await deferred_prefix.loadLibrary();
+          return new deferred_prefix.Foo() as dynamic;
+        }
+        ```
+
+        Because the new implementation might require you to inspect and fix your
+        app, we exposed two temporary flags:
+
+    *   The `--report-invalid-deferred-types` causes dart2js to run both the
+        old and new algorithms and report any cases where an invalid type was
+        detected.
+
+    *   The `--new-deferred-split` flag enables this new algorithm.
+
+*   The `--categories=*` flag is being replaced. `--categories=all` was only
+    used for testing and it is no longer supported. `--categories=Server`
+    continues to work at this time but it is deprecated, please use
+    `--server-mode` instead.
+
+*   The `--library-root` flag was replaced by `--libraries-spec`. This flag is
+    rarely used by developers invoking dart2js directly. It's important for
+    integrating dart2js with build systems. See `--help` for more details on the
+    new flag.
+
+[35311]: https://github.com/dart-lang/sdk/issues/35311
+
+### Tools
 
 #### Analyzer
 
@@ -191,135 +249,39 @@
 
 *   New hints added:
 
-    *   `INVALID_LITERAL_ANNOTATION` when something other than a const
+    *   `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR` and
+        `NON_CONST_CALL_TO_LITERAL_CONSTRUCTOR_USING_NEW` inform you when a
+        `@literal` const constructor is called in a non-const context (or with
+        `new`).
+    *   `INVALID_LITERAL_ANNOTATION` reports when something other than a const
         constructor is annotated with `@literal`.
-    *   `SUBTYPE_OF_SEALED_CLASS` when any class or mixin subclasses (extends,
-        implements, mixes in, or constrains to) a `@sealed` class, and the two
-        are declared in different packages.
-    *   `MIXIN_ON_SEALED_CLASS` when a `@sealed` class is used as a superclass
-        constraint of a mixin.
-
-#### dart2js
-
-* We fixed a bug in how deferred constructor calls were incorrectly not
-  marked as deferred. The old behavior didn't cause breakages, but was imprecise
-  and pushed more code to the main output unit.
-
-* A new deferred split algorithm implementation was added.
-
-  This implementation fixes a soundness bug and addresses performance issues of
-  the previous implementation, because of that it can have a visible impact
-  on apps. In particular,
-
-    * We fixed a performance issue which was introduced when we migrated to the
-      Common front-end. On large apps, the fix can cut down 2/3 of the time
-      spent on this task.
-
-    * We fixed a bug in how inferred types were miscategorized (Issue [35311]). The old
-      behavior was unsound and could produce broken programs. The fix may cause
-      more code to be pulled into the main output unit.
-
-      This shows up frequently when returning deferred values from closures
-      since the closure's inferred return type is the deferred type.
-      For example, if you have:
-
-      ```dart
-      () async {
-        await deferred_prefix.loadLibrary();
-        return new deferred_prefix.Foo();
-      }
-      ```
-
-      The closure's return type is `Future<Foo>`. The old implementation defers
-      `Foo`, and incorrectly makes the return type `Future<dynamic>`. This may
-      break in places where the correct type is expected.
-
-      The new implementation will not defer `Foo`, and will place it in the main
-      output unit. If your intent is to defer it, then you need to ensure the
-      return type is not inferred to be `Foo`. For example, you can do so by
-      changing the code to a named closure with a declared type, or by ensuring
-      that the return expression has the type you want, like:
-
-      ```dart
-      () async {
-        await deferred_prefix.loadLibrary();
-        return new deferred_prefix.Foo() as dynamic;
-      }
-      ```
-
-  Because the new implementation might require you to inspect and fix
-  your app, we exposed two temporary flags:
-
-    * `--report-invalid-deferred-types`: when provided, we will run both the
-      old and new algorithm and report where the issue was detected.
-
-    * `--new-deferred-split`: enables the new algorithm.
-
-[35311]: https://github.com/dart-lang/sdk/issues/35311
+    *   `SUBTYPE_OF_SEALED_CLASS` reports when any class or mixin subclasses
+        (extends, implements, mixes in, or constrains to) a `@sealed` class, and
+        the two are declared in different packages.
+    *   `MIXIN_ON_SEALED_CLASS` reports when a `@sealed` class is used as a
+        superclass constraint of a mixin.
 
 #### dartdoc
 
-* dartdoc default styles now work much better on mobile.  Simple browsing
-  and searching of API docs now work in many cases.
+Default styles now work much better on mobile. Simple browsing and searching of
+API docs now work in many cases.
 
-#### Linter
+Upgraded the linter to `0.1.78` which adds the following improvements:
 
-The linter was bumped to `0.1.78` which introduces the following linter fixes to the SDK:
-
-* fixed `type_annotate_public_apis` false positives on local functions
-* fixed `avoid_shadowing_type_parameters` to report shadowed type parameters in generic typedefs
-* fixed `use_setters_to_change_properties` to not wrongly lint overriding methods
-* fixed `cascade_invocations` to not lint awaited targets
-* fixed `prefer_conditional_assignment` false positives
-* fixed `join_return_with_assignment` false positives
-* fixed `cascade_invocations` false positives
-* miscellaneous documentation improvements
-* updated `invariant_booleans` status to experimental
-
-and adds:
-
-* a new `prefer_final_in_for_each` lint rule to flag loop variables that could be declared final
-
-## 2.1.1-dev.0.1
-
-* Cherry-pick 4914fe57ea9e034b948ef3ab5a4e7e511991f845 to dev
-* Cherry-pick 5a8ec419829337b60d705cabe0b3b1ab5d0d0883 to dev
-
-## 2.1.1-dev.0.0
-
-* Cherry-pick f8a680e5116493f8795c148a52dbecf8a84e4536 to dev
-* Cherry-pick b1c963c84b20e715bc5c1f7d443168071c2b971d to dev
-
-## 2.2.0-dev.1.1
-
-### Tool Changes
-
-#### Linter
-
-The linter was bumped to `0.1.73` which introduces the following new lints to the SDK:
-
-* `unnecessary_await_in_return`
-* `use_function_type_syntax_for_parameters`
-* `avoid_returning_null_for_future`
-* `avoid_shadowing_type_parameters`
-
-In addition, `prefer_bool_in_asserts` has been deprecated as its semantics are
-redundant with Dart 2 checks.
-
-## 2.2.0-dev.0.0
-
-### Dart for the Web
-
-#### dart2js
-
-* The `--categories=*` flag is being replaced. `--categories=all` was only used
-  for testing and it is no longer supported. `--categories=Server` continues to
-  work at this time but it is deprecated, please use `--server-mode` instead.
-
-* The `--library-root` flag was replaced by `--libraries-spec`. This flag is
-  rarely used by developers invoking dart2js directly. It's important for
-  integrating dart2js with build systems. See `--help` for more details on the
-  new flag.
+*   Added `prefer_final_in_for_each`, `unnecessary_await_in_return`,
+    `use_function_type_syntax_for_parameters`,
+    `avoid_returning_null_for_future`, and `avoid_shadowing_type_parameters`.
+*   Updated `invariant_booleans` status to experimental.
+*   Fixed `type_annotate_public_apis` false positives on local functions.
+*   Fixed `avoid_shadowing_type_parameters` to report shadowed type parameters
+    in generic typedefs.
+*   Fixed `use_setters_to_change_properties` to not wrongly lint overriding
+    methods.
+*   Fixed `cascade_invocations` to not lint awaited targets.
+*   Fixed `prefer_conditional_assignment` false positives.
+*   Fixed `join_return_with_assignment` false positives.
+*   Fixed `cascade_invocations` false positives.
+*   Deprecated `prefer_bool_in_asserts` as it is redundant in Dart 2.
 
 ## 2.1.0 - 2018-11-15
 
diff --git a/DEPS b/DEPS
index 6fe9b46..e8098e9 100644
--- a/DEPS
+++ b/DEPS
@@ -81,7 +81,7 @@
   # For more details, see https://github.com/dart-lang/sdk/issues/30164
   "dart_style_tag": "1.2.2",  # Please see the note above before updating.
 
-  "dartdoc_tag" : "v0.28.0",
+  "dartdoc_tag" : "v0.28.1+2",
   "fixnum_tag": "0.10.9",
   "glob_tag": "1.1.7",
   "html_tag" : "0.13.3+2",
@@ -95,7 +95,7 @@
   "intl_tag": "0.15.7",
   "jinja2_rev": "2222b31554f03e62600cd7e383376a7c187967a1",
   "json_rpc_2_tag": "2.0.9",
-  "linter_tag": "0.1.79",
+  "linter_tag": "0.1.82",
   "logging_tag": "0.11.3+2",
   "markupsafe_rev": "8f45f5cfa0009d2a70589bcda0349b8cb2b72783",
   "markdown_tag": "2.0.2",
diff --git a/dartdoc_options.yaml b/dartdoc_options.yaml
deleted file mode 100644
index 6c233f4..0000000
--- a/dartdoc_options.yaml
+++ /dev/null
@@ -1,2 +0,0 @@
-dartdoc:
-  categoryOrder: ["Core", VM", "Web"]
diff --git a/pkg/analysis_server/doc/api.html b/pkg/analysis_server/doc/api.html
index bf31832..f7ed499 100644
--- a/pkg/analysis_server/doc/api.html
+++ b/pkg/analysis_server/doc/api.html
@@ -109,7 +109,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  1.22.1
+  1.23.0
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1447,6 +1447,10 @@
   </p>
   
   
+  
+  
+  
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_completion.getSuggestions">completion.getSuggestions</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "completion.getSuggestions"
@@ -1493,6 +1497,9 @@
     "<b>replacementLength</b>": int
     "<b>results</b>": List&lt;<a href="#type_CompletionSuggestion">CompletionSuggestion</a>&gt;
     "<b>isLast</b>": bool
+    "<b>includedSuggestionSets</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;
+    "<b>includedSuggestionKinds</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_ElementKind">ElementKind</a>&gt;
+    "<b>includedSuggestionRelevanceTags</b>": <span style="color:#999999">optional</span> List&lt;<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>&gt;
   }
 }</pre></div>
     <p>
@@ -1541,6 +1548,44 @@
           True if this is that last set of results that will be
           returned for the indicated completion.
         </p>
+      </dd><dt class="field"><b>includedSuggestionSets: List&lt;<a href="#type_IncludedSuggestionSet">IncludedSuggestionSet</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          References to <tt>AvailableSuggestionSet</tt> objects previously sent
+          to the client. The client can include applicable names from the
+          referenced library in code completion suggestions.
+        </p>
+      </dd><dt class="field"><b>includedSuggestionKinds: List&lt;<a href="#type_ElementKind">ElementKind</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          The client is expected to check this list against the
+          <tt>ElementKind</tt> sent in <tt>IncludedSuggestionSet</tt> to decide
+          whether or not these symbols should should be presented to the user.
+        </p>
+      </dd><dt class="field"><b>includedSuggestionRelevanceTags: List&lt;<a href="#type_IncludedSuggestionRelevanceTag">IncludedSuggestionRelevanceTag</a>&gt;<span style="color:#999999"> (optional)</span></b></dt><dd>
+        
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          The client is expected to check this list against the values of the
+          field <tt>relevanceTags</tt> of <tt>AvailableSuggestion</tt> to
+          decide if the suggestion should be given a different relevance than
+          the <tt>IncludedSuggestionSet</tt> that contains it. This might be
+          used for example to give higher relevance to suggestions of matching
+          types.
+        </p>
+        <p>
+          If an <tt>AvailableSuggestion</tt> has relevance tags that match more
+          than one <tt>IncludedSuggestionRelevanceTag</tt>, the maximum
+          relevance boost is used.
+        </p>
       </dd></dl></dd></dl>
 <h2 class="domain"><a name="domain_search">search domain</a></h2>
   <p>
@@ -1835,6 +1880,7 @@
   
   
   
+  
 <h3>Requests</h3><dl><dt class="request"><a name="request_edit.format">edit.format</a></dt><dd><div class="box"><pre>request: {
   "id": String
   "method": "edit.format"
@@ -2644,6 +2690,14 @@
   
   
   
+  
+  
+  
+  
+  
+  
+  
+  
 <dl><dt class="typeDefinition"><a name="type_AddContentOverlay">AddContentOverlay: object</a></dt><dd>
     <p>
       A directive to begin overlaying the contents of a file. The supplied
@@ -2827,7 +2881,12 @@
           The name of the current target of analysis. This field is
           omitted if analyzing is false.
         </p>
-      </dd></dl></dd><dt class="typeDefinition"><a name="type_ChangeContentOverlay">ChangeContentOverlay: object</a></dt><dd>
+      </dd></dl></dd><dt class="typeDefinition"><a name="type_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag: String</a></dt><dd>
+    
+    <p>
+      The opaque tag value.
+    </p>
+  </dd><dt class="typeDefinition"><a name="type_ChangeContentOverlay">ChangeContentOverlay: object</a></dt><dd>
     <p>
       A directive to modify an existing file content overlay. One or more ranges
       of text are deleted from the old file content overlay and replaced with
@@ -4348,6 +4407,12 @@
           An "edit.sortMembers" request specified a Dart file that has
           scan or parse errors.
         </p>
+      </dd><dt class="value">UNKNOWN_FIX</dt><dd>
+        
+        <p>
+          A dartfix request was received containing the name of a fix
+          which does not match the name of any known fixes.
+        </p>
       </dd><dt class="value">UNKNOWN_REQUEST</dt><dd>
         
         <p>
@@ -5045,7 +5110,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></ul><h5>Notifications</h5><div class="subindex"><ul><li><a href="#notification_completion.results">results</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_ChangeContentOverlay">ChangeContentOverlay</a></li><li><a href="#type_ClosingLabel">ClosingLabel</a></li><li><a href="#type_CompletionId">CompletionId</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_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_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></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_AvailableSuggestionRelevanceTag">AvailableSuggestionRelevanceTag</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_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_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_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/protocol/protocol_constants.dart b/pkg/analysis_server/lib/protocol/protocol_constants.dart
index fd21adb..d599adc 100644
--- a/pkg/analysis_server/lib/protocol/protocol_constants.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.22.1';
+const String PROTOCOL_VERSION = '1.23.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -110,8 +110,21 @@
 const String ANALYTICS_REQUEST_SEND_TIMING_EVENT = 'event';
 const String ANALYTICS_REQUEST_SEND_TIMING_MILLIS = 'millis';
 const String ANALYTICS_RESPONSE_IS_ENABLED_ENABLED = 'enabled';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS =
+    'completion.availableSuggestions';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_CHANGED_LIBRARIES =
+    'changedLibraries';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
+    'removedLibraries';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
+const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_KINDS =
+    'includedSuggestionKinds';
+const String
+    COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_RELEVANCE_TAGS =
+    'includedSuggestionRelevanceTags';
+const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
+    'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
@@ -121,13 +134,33 @@
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_OFFSET = 'offset';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS =
+    'completion.getSuggestionDetails';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_OFFSET = 'offset';
+const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS =
+    'completion.registerLibraryPaths';
+const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS_PATHS = 'paths';
+const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS =
+    'completion.setSubscriptions';
+const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS =
+    'subscriptions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS_ID = 'id';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
+    'completion';
 const String DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
 const String DIAGNOSTIC_REQUEST_GET_SERVER_PORT = 'diagnostic.getServerPort';
 const String DIAGNOSTIC_RESPONSE_GET_DIAGNOSTICS_CONTEXTS = 'contexts';
 const String DIAGNOSTIC_RESPONSE_GET_SERVER_PORT_PORT = 'port';
 const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
+const String EDIT_REQUEST_DARTFIX_EXCLUDED_FIXES = 'excludedFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
+const String EDIT_REQUEST_DARTFIX_INCLUDED_FIXES = 'includedFixes';
+const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
+    'includeRequiredFixes';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
@@ -142,6 +175,7 @@
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_FILE = 'file';
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_LENGTH = 'length';
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_OFFSET = 'offset';
+const String EDIT_REQUEST_GET_DARTFIX_INFO = 'edit.getDartfixInfo';
 const String EDIT_REQUEST_GET_FIXES = 'edit.getFixes';
 const String EDIT_REQUEST_GET_FIXES_FILE = 'file';
 const String EDIT_REQUEST_GET_FIXES_OFFSET = 'offset';
@@ -183,6 +217,7 @@
 const String EDIT_RESPONSE_FORMAT_SELECTION_OFFSET = 'selectionOffset';
 const String EDIT_RESPONSE_GET_ASSISTS_ASSISTS = 'assists';
 const String EDIT_RESPONSE_GET_AVAILABLE_REFACTORINGS_KINDS = 'kinds';
+const String EDIT_RESPONSE_GET_DARTFIX_INFO_FIXES = 'fixes';
 const String EDIT_RESPONSE_GET_FIXES_FIXES = 'fixes';
 const String EDIT_RESPONSE_GET_POSTFIX_COMPLETION_CHANGE = 'change';
 const String EDIT_RESPONSE_GET_REFACTORING_CHANGE = 'change';
diff --git a/pkg/analysis_server/lib/protocol/protocol_generated.dart b/pkg/analysis_server/lib/protocol/protocol_generated.dart
index 5130033..9f29f1a 100644
--- a/pkg/analysis_server/lib/protocol/protocol_generated.dart
+++ b/pkg/analysis_server/lib/protocol/protocol_generated.dart
@@ -5071,6 +5071,415 @@
 }
 
 /**
+ * AvailableSuggestion
+ *
+ * {
+ *   "label": String
+ *   "element": Element
+ *   "docComplete": optional String
+ *   "docSummary": optional String
+ *   "parameterNames": optional List<String>
+ *   "parameterTypes": optional List<String>
+ *   "relevanceTags": optional List<AvailableSuggestionRelevanceTag>
+ *   "requiredParameterCount": optional int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class AvailableSuggestion implements HasToJson {
+  String _label;
+
+  Element _element;
+
+  String _docComplete;
+
+  String _docSummary;
+
+  List<String> _parameterNames;
+
+  List<String> _parameterTypes;
+
+  List<String> _relevanceTags;
+
+  int _requiredParameterCount;
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  String get label => _label;
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  void set label(String value) {
+    assert(value != null);
+    this._label = value;
+  }
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  Element get element => _element;
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  void set element(Element value) {
+    assert(value != null);
+    this._element = value;
+  }
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  String get docComplete => _docComplete;
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  void set docComplete(String value) {
+    this._docComplete = value;
+  }
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being
+   * suggested. This field is omitted if there is no Dartdoc associated with
+   * the element.
+   */
+  String get docSummary => _docSummary;
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being
+   * suggested. This field is omitted if there is no Dartdoc associated with
+   * the element.
+   */
+  void set docSummary(String value) {
+    this._docSummary = value;
+  }
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all
+   * kinds - required, optional positional, and optional named. The names of
+   * positional parameters are empty strings. Omitted if the element is not an
+   * executable.
+   */
+  List<String> get parameterNames => _parameterNames;
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all
+   * kinds - required, optional positional, and optional named. The names of
+   * positional parameters are empty strings. Omitted if the element is not an
+   * executable.
+   */
+  void set parameterNames(List<String> value) {
+    this._parameterNames = value;
+  }
+
+  /**
+   * If the element is an executable, the declared types of the formal
+   * parameters of all kinds - required, optional positional, and optional
+   * named. Omitted if the element is not an executable.
+   */
+  List<String> get parameterTypes => _parameterTypes;
+
+  /**
+   * If the element is an executable, the declared types of the formal
+   * parameters of all kinds - required, optional positional, and optional
+   * named. Omitted if the element is not an executable.
+   */
+  void set parameterTypes(List<String> value) {
+    this._parameterTypes = value;
+  }
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed
+   * depending on where completion is requested.
+   */
+  List<String> get relevanceTags => _relevanceTags;
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed
+   * depending on where completion is requested.
+   */
+  void set relevanceTags(List<String> value) {
+    this._relevanceTags = value;
+  }
+
+  int get requiredParameterCount => _requiredParameterCount;
+
+  void set requiredParameterCount(int value) {
+    this._requiredParameterCount = value;
+  }
+
+  AvailableSuggestion(String label, Element element,
+      {String docComplete,
+      String docSummary,
+      List<String> parameterNames,
+      List<String> parameterTypes,
+      List<String> relevanceTags,
+      int requiredParameterCount}) {
+    this.label = label;
+    this.element = element;
+    this.docComplete = docComplete;
+    this.docSummary = docSummary;
+    this.parameterNames = parameterNames;
+    this.parameterTypes = parameterTypes;
+    this.relevanceTags = relevanceTags;
+    this.requiredParameterCount = requiredParameterCount;
+  }
+
+  factory AvailableSuggestion.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String label;
+      if (json.containsKey("label")) {
+        label = jsonDecoder.decodeString(jsonPath + ".label", json["label"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "label");
+      }
+      Element element;
+      if (json.containsKey("element")) {
+        element = new Element.fromJson(
+            jsonDecoder, jsonPath + ".element", json["element"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "element");
+      }
+      String docComplete;
+      if (json.containsKey("docComplete")) {
+        docComplete = jsonDecoder.decodeString(
+            jsonPath + ".docComplete", json["docComplete"]);
+      }
+      String docSummary;
+      if (json.containsKey("docSummary")) {
+        docSummary = jsonDecoder.decodeString(
+            jsonPath + ".docSummary", json["docSummary"]);
+      }
+      List<String> parameterNames;
+      if (json.containsKey("parameterNames")) {
+        parameterNames = jsonDecoder.decodeList(jsonPath + ".parameterNames",
+            json["parameterNames"], jsonDecoder.decodeString);
+      }
+      List<String> parameterTypes;
+      if (json.containsKey("parameterTypes")) {
+        parameterTypes = jsonDecoder.decodeList(jsonPath + ".parameterTypes",
+            json["parameterTypes"], jsonDecoder.decodeString);
+      }
+      List<String> relevanceTags;
+      if (json.containsKey("relevanceTags")) {
+        relevanceTags = jsonDecoder.decodeList(jsonPath + ".relevanceTags",
+            json["relevanceTags"], jsonDecoder.decodeString);
+      }
+      int requiredParameterCount;
+      if (json.containsKey("requiredParameterCount")) {
+        requiredParameterCount = jsonDecoder.decodeInt(
+            jsonPath + ".requiredParameterCount",
+            json["requiredParameterCount"]);
+      }
+      return new AvailableSuggestion(label, element,
+          docComplete: docComplete,
+          docSummary: docSummary,
+          parameterNames: parameterNames,
+          parameterTypes: parameterTypes,
+          relevanceTags: relevanceTags,
+          requiredParameterCount: requiredParameterCount);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "AvailableSuggestion", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["label"] = label;
+    result["element"] = element.toJson();
+    if (docComplete != null) {
+      result["docComplete"] = docComplete;
+    }
+    if (docSummary != null) {
+      result["docSummary"] = docSummary;
+    }
+    if (parameterNames != null) {
+      result["parameterNames"] = parameterNames;
+    }
+    if (parameterTypes != null) {
+      result["parameterTypes"] = parameterTypes;
+    }
+    if (relevanceTags != null) {
+      result["relevanceTags"] = relevanceTags;
+    }
+    if (requiredParameterCount != null) {
+      result["requiredParameterCount"] = requiredParameterCount;
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is AvailableSuggestion) {
+      return label == other.label &&
+          element == other.element &&
+          docComplete == other.docComplete &&
+          docSummary == other.docSummary &&
+          listEqual(parameterNames, other.parameterNames,
+              (String a, String b) => a == b) &&
+          listEqual(parameterTypes, other.parameterTypes,
+              (String a, String b) => a == b) &&
+          listEqual(relevanceTags, other.relevanceTags,
+              (String a, String b) => a == b) &&
+          requiredParameterCount == other.requiredParameterCount;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, element.hashCode);
+    hash = JenkinsSmiHash.combine(hash, docComplete.hashCode);
+    hash = JenkinsSmiHash.combine(hash, docSummary.hashCode);
+    hash = JenkinsSmiHash.combine(hash, parameterNames.hashCode);
+    hash = JenkinsSmiHash.combine(hash, parameterTypes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevanceTags.hashCode);
+    hash = JenkinsSmiHash.combine(hash, requiredParameterCount.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * AvailableSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "uri": String
+ *   "items": List<AvailableSuggestion>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class AvailableSuggestionSet implements HasToJson {
+  int _id;
+
+  String _uri;
+
+  List<AvailableSuggestion> _items;
+
+  /**
+   * The id associated with the library.
+   */
+  int get id => _id;
+
+  /**
+   * The id associated with the library.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The URI of the library.
+   */
+  String get uri => _uri;
+
+  /**
+   * The URI of the library.
+   */
+  void set uri(String value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  List<AvailableSuggestion> get items => _items;
+
+  void set items(List<AvailableSuggestion> value) {
+    assert(value != null);
+    this._items = value;
+  }
+
+  AvailableSuggestionSet(int id, String uri, List<AvailableSuggestion> items) {
+    this.id = id;
+    this.uri = uri;
+    this.items = items;
+  }
+
+  factory AvailableSuggestionSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      String uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeString(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<AvailableSuggestion> items;
+      if (json.containsKey("items")) {
+        items = jsonDecoder.decodeList(
+            jsonPath + ".items",
+            json["items"],
+            (String jsonPath, Object json) =>
+                new AvailableSuggestion.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "items");
+      }
+      return new AvailableSuggestionSet(id, uri, items);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "AvailableSuggestionSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["id"] = id;
+    result["uri"] = uri;
+    result["items"] =
+        items.map((AvailableSuggestion value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is AvailableSuggestionSet) {
+      return id == other.id &&
+          uri == other.uri &&
+          listEqual(items, other.items,
+              (AvailableSuggestion a, AvailableSuggestion b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, items.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ClosingLabel
  *
  * {
@@ -5196,6 +5605,417 @@
 }
 
 /**
+ * completion.availableSuggestions params
+ *
+ * {
+ *   "changedLibraries": optional List<AvailableSuggestionSet>
+ *   "removedLibraries": optional List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionAvailableSuggestionsParams implements HasToJson {
+  List<AvailableSuggestionSet> _changedLibraries;
+
+  List<int> _removedLibraries;
+
+  /**
+   * A list of pre-computed, potential completions coming from this set of
+   * completion suggestions.
+   */
+  List<AvailableSuggestionSet> get changedLibraries => _changedLibraries;
+
+  /**
+   * A list of pre-computed, potential completions coming from this set of
+   * completion suggestions.
+   */
+  void set changedLibraries(List<AvailableSuggestionSet> value) {
+    this._changedLibraries = value;
+  }
+
+  /**
+   * A list of library ids that no longer apply.
+   */
+  List<int> get removedLibraries => _removedLibraries;
+
+  /**
+   * A list of library ids that no longer apply.
+   */
+  void set removedLibraries(List<int> value) {
+    this._removedLibraries = value;
+  }
+
+  CompletionAvailableSuggestionsParams(
+      {List<AvailableSuggestionSet> changedLibraries,
+      List<int> removedLibraries}) {
+    this.changedLibraries = changedLibraries;
+    this.removedLibraries = removedLibraries;
+  }
+
+  factory CompletionAvailableSuggestionsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<AvailableSuggestionSet> changedLibraries;
+      if (json.containsKey("changedLibraries")) {
+        changedLibraries = jsonDecoder.decodeList(
+            jsonPath + ".changedLibraries",
+            json["changedLibraries"],
+            (String jsonPath, Object json) =>
+                new AvailableSuggestionSet.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
+      List<int> removedLibraries;
+      if (json.containsKey("removedLibraries")) {
+        removedLibraries = jsonDecoder.decodeList(
+            jsonPath + ".removedLibraries",
+            json["removedLibraries"],
+            jsonDecoder.decodeInt);
+      }
+      return new CompletionAvailableSuggestionsParams(
+          changedLibraries: changedLibraries,
+          removedLibraries: removedLibraries);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.availableSuggestions params", json);
+    }
+  }
+
+  factory CompletionAvailableSuggestionsParams.fromNotification(
+      Notification notification) {
+    return new CompletionAvailableSuggestionsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    if (changedLibraries != null) {
+      result["changedLibraries"] = changedLibraries
+          .map((AvailableSuggestionSet value) => value.toJson())
+          .toList();
+    }
+    if (removedLibraries != null) {
+      result["removedLibraries"] = removedLibraries;
+    }
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.availableSuggestions", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionAvailableSuggestionsParams) {
+      return listEqual(changedLibraries, other.changedLibraries,
+              (AvailableSuggestionSet a, AvailableSuggestionSet b) => a == b) &&
+          listEqual(removedLibraries, other.removedLibraries,
+              (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, changedLibraries.hashCode);
+    hash = JenkinsSmiHash.combine(hash, removedLibraries.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.getSuggestionDetails params
+ *
+ * {
+ *   "file": FilePath
+ *   "id": int
+ *   "label": String
+ *   "offset": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionGetSuggestionDetailsParams implements RequestParams {
+  String _file;
+
+  int _id;
+
+  String _label;
+
+  int _offset;
+
+  /**
+   * The path of the file into which this completion is being inserted.
+   */
+  String get file => _file;
+
+  /**
+   * The path of the file into which this completion is being inserted.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The identifier of the AvailableSuggestionSet containing the selected
+   * label.
+   */
+  int get id => _id;
+
+  /**
+   * The identifier of the AvailableSuggestionSet containing the selected
+   * label.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The label from the AvailableSuggestionSet with the `id` for which
+   * insertion information is requested.
+   */
+  String get label => _label;
+
+  /**
+   * The label from the AvailableSuggestionSet with the `id` for which
+   * insertion information is requested.
+   */
+  void set label(String value) {
+    assert(value != null);
+    this._label = value;
+  }
+
+  /**
+   * The offset in the file where the completion will be inserted.
+   */
+  int get offset => _offset;
+
+  /**
+   * The offset in the file where the completion will be inserted.
+   */
+  void set offset(int value) {
+    assert(value != null);
+    this._offset = value;
+  }
+
+  CompletionGetSuggestionDetailsParams(
+      String file, int id, String label, int offset) {
+    this.file = file;
+    this.id = id;
+    this.label = label;
+    this.offset = offset;
+  }
+
+  factory CompletionGetSuggestionDetailsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      String label;
+      if (json.containsKey("label")) {
+        label = jsonDecoder.decodeString(jsonPath + ".label", json["label"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "label");
+      }
+      int offset;
+      if (json.containsKey("offset")) {
+        offset = jsonDecoder.decodeInt(jsonPath + ".offset", json["offset"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "offset");
+      }
+      return new CompletionGetSuggestionDetailsParams(file, id, label, offset);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.getSuggestionDetails params", json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetailsParams.fromRequest(Request request) {
+    return new CompletionGetSuggestionDetailsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["id"] = id;
+    result["label"] = label;
+    result["offset"] = offset;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.getSuggestionDetails", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetailsParams) {
+      return file == other.file &&
+          id == other.id &&
+          label == other.label &&
+          offset == other.offset;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, offset.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.getSuggestionDetails result
+ *
+ * {
+ *   "completion": String
+ *   "change": optional SourceChange
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionGetSuggestionDetailsResult implements ResponseResult {
+  String _completion;
+
+  SourceChange _change;
+
+  /**
+   * The full text to insert, including any optional import prefix.
+   */
+  String get completion => _completion;
+
+  /**
+   * The full text to insert, including any optional import prefix.
+   */
+  void set completion(String value) {
+    assert(value != null);
+    this._completion = value;
+  }
+
+  /**
+   * A change for the client to apply in case the library containing the
+   * accepted completion suggestion needs to be imported. The field will be
+   * omitted if there are no additional changes that need to be made.
+   */
+  SourceChange get change => _change;
+
+  /**
+   * A change for the client to apply in case the library containing the
+   * accepted completion suggestion needs to be imported. The field will be
+   * omitted if there are no additional changes that need to be made.
+   */
+  void set change(SourceChange value) {
+    this._change = value;
+  }
+
+  CompletionGetSuggestionDetailsResult(String completion,
+      {SourceChange change}) {
+    this.completion = completion;
+    this.change = change;
+  }
+
+  factory CompletionGetSuggestionDetailsResult.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String completion;
+      if (json.containsKey("completion")) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + ".completion", json["completion"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "completion");
+      }
+      SourceChange change;
+      if (json.containsKey("change")) {
+        change = new SourceChange.fromJson(
+            jsonDecoder, jsonPath + ".change", json["change"]);
+      }
+      return new CompletionGetSuggestionDetailsResult(completion,
+          change: change);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.getSuggestionDetails result", json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetailsResult.fromResponse(Response response) {
+    return new CompletionGetSuggestionDetailsResult.fromJson(
+        new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        "result",
+        response.result);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["completion"] = completion;
+    if (change != null) {
+      result["change"] = change.toJson();
+    }
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetailsResult) {
+      return completion == other.completion && change == other.change;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, completion.hashCode);
+    hash = JenkinsSmiHash.combine(hash, change.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestions params
  *
  * {
@@ -5391,6 +6211,130 @@
 }
 
 /**
+ * completion.registerLibraryPaths params
+ *
+ * {
+ *   "paths": List<LibraryPathSet>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionRegisterLibraryPathsParams implements RequestParams {
+  List<LibraryPathSet> _paths;
+
+  /**
+   * A list of objects each containing a path and the additional libraries from
+   * which the client is interested in receiving completion suggestions. If one
+   * configured path is beneath another, the descendent will override the
+   * ancestors' configured libraries of interest.
+   */
+  List<LibraryPathSet> get paths => _paths;
+
+  /**
+   * A list of objects each containing a path and the additional libraries from
+   * which the client is interested in receiving completion suggestions. If one
+   * configured path is beneath another, the descendent will override the
+   * ancestors' configured libraries of interest.
+   */
+  void set paths(List<LibraryPathSet> value) {
+    assert(value != null);
+    this._paths = value;
+  }
+
+  CompletionRegisterLibraryPathsParams(List<LibraryPathSet> paths) {
+    this.paths = paths;
+  }
+
+  factory CompletionRegisterLibraryPathsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<LibraryPathSet> paths;
+      if (json.containsKey("paths")) {
+        paths = jsonDecoder.decodeList(
+            jsonPath + ".paths",
+            json["paths"],
+            (String jsonPath, Object json) =>
+                new LibraryPathSet.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "paths");
+      }
+      return new CompletionRegisterLibraryPathsParams(paths);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.registerLibraryPaths params", json);
+    }
+  }
+
+  factory CompletionRegisterLibraryPathsParams.fromRequest(Request request) {
+    return new CompletionRegisterLibraryPathsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["paths"] =
+        paths.map((LibraryPathSet value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.registerLibraryPaths", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionRegisterLibraryPathsParams) {
+      return listEqual(
+          paths, other.paths, (LibraryPathSet a, LibraryPathSet b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, paths.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.registerLibraryPaths result
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionRegisterLibraryPathsResult implements ResponseResult {
+  @override
+  Map<String, dynamic> toJson() => <String, dynamic>{};
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: null);
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionRegisterLibraryPathsResult) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    return 104675661;
+  }
+}
+
+/**
  * completion.results params
  *
  * {
@@ -5399,6 +6343,9 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
+ *   "includedSuggestionKinds": optional List<ElementKind>
+ *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -5414,6 +6361,12 @@
 
   bool _isLast;
 
+  List<IncludedSuggestionSet> _includedSuggestionSets;
+
+  List<ElementKind> _includedSuggestionKinds;
+
+  List<IncludedSuggestionRelevanceTag> _includedSuggestionRelevanceTags;
+
   /**
    * The id associated with the completion.
    */
@@ -5499,13 +6452,92 @@
     this._isLast = value;
   }
 
+  /**
+   * This field is experimental.
+   *
+   * References to AvailableSuggestionSet objects previously sent to the
+   * client. The client can include applicable names from the referenced
+   * library in code completion suggestions.
+   */
+  List<IncludedSuggestionSet> get includedSuggestionSets =>
+      _includedSuggestionSets;
+
+  /**
+   * This field is experimental.
+   *
+   * References to AvailableSuggestionSet objects previously sent to the
+   * client. The client can include applicable names from the referenced
+   * library in code completion suggestions.
+   */
+  void set includedSuggestionSets(List<IncludedSuggestionSet> value) {
+    this._includedSuggestionSets = value;
+  }
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the ElementKind sent in
+   * IncludedSuggestionSet to decide whether or not these symbols should should
+   * be presented to the user.
+   */
+  List<ElementKind> get includedSuggestionKinds => _includedSuggestionKinds;
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the ElementKind sent in
+   * IncludedSuggestionSet to decide whether or not these symbols should should
+   * be presented to the user.
+   */
+  void set includedSuggestionKinds(List<ElementKind> value) {
+    this._includedSuggestionKinds = value;
+  }
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the values of the field
+   * relevanceTags of AvailableSuggestion to decide if the suggestion should be
+   * given a different relevance than the IncludedSuggestionSet that contains
+   * it. This might be used for example to give higher relevance to suggestions
+   * of matching types.
+   *
+   * If an AvailableSuggestion has relevance tags that match more than one
+   * IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
+   */
+  List<IncludedSuggestionRelevanceTag> get includedSuggestionRelevanceTags =>
+      _includedSuggestionRelevanceTags;
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the values of the field
+   * relevanceTags of AvailableSuggestion to decide if the suggestion should be
+   * given a different relevance than the IncludedSuggestionSet that contains
+   * it. This might be used for example to give higher relevance to suggestions
+   * of matching types.
+   *
+   * If an AvailableSuggestion has relevance tags that match more than one
+   * IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
+   */
+  void set includedSuggestionRelevanceTags(
+      List<IncludedSuggestionRelevanceTag> value) {
+    this._includedSuggestionRelevanceTags = value;
+  }
+
   CompletionResultsParams(String id, int replacementOffset,
-      int replacementLength, List<CompletionSuggestion> results, bool isLast) {
+      int replacementLength, List<CompletionSuggestion> results, bool isLast,
+      {List<IncludedSuggestionSet> includedSuggestionSets,
+      List<ElementKind> includedSuggestionKinds,
+      List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
     this.replacementOffset = replacementOffset;
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.includedSuggestionSets = includedSuggestionSets;
+    this.includedSuggestionKinds = includedSuggestionKinds;
+    this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
   }
 
   factory CompletionResultsParams.fromJson(
@@ -5550,8 +6582,37 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      List<IncludedSuggestionSet> includedSuggestionSets;
+      if (json.containsKey("includedSuggestionSets")) {
+        includedSuggestionSets = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionSets",
+            json["includedSuggestionSets"],
+            (String jsonPath, Object json) =>
+                new IncludedSuggestionSet.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
+      List<ElementKind> includedSuggestionKinds;
+      if (json.containsKey("includedSuggestionKinds")) {
+        includedSuggestionKinds = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionKinds",
+            json["includedSuggestionKinds"],
+            (String jsonPath, Object json) =>
+                new ElementKind.fromJson(jsonDecoder, jsonPath, json));
+      }
+      List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+      if (json.containsKey("includedSuggestionRelevanceTags")) {
+        includedSuggestionRelevanceTags = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionRelevanceTags",
+            json["includedSuggestionRelevanceTags"],
+            (String jsonPath, Object json) =>
+                new IncludedSuggestionRelevanceTag.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
       return new CompletionResultsParams(
-          id, replacementOffset, replacementLength, results, isLast);
+          id, replacementOffset, replacementLength, results, isLast,
+          includedSuggestionSets: includedSuggestionSets,
+          includedSuggestionKinds: includedSuggestionKinds,
+          includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "completion.results params", json);
     }
@@ -5571,6 +6632,22 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (includedSuggestionSets != null) {
+      result["includedSuggestionSets"] = includedSuggestionSets
+          .map((IncludedSuggestionSet value) => value.toJson())
+          .toList();
+    }
+    if (includedSuggestionKinds != null) {
+      result["includedSuggestionKinds"] = includedSuggestionKinds
+          .map((ElementKind value) => value.toJson())
+          .toList();
+    }
+    if (includedSuggestionRelevanceTags != null) {
+      result["includedSuggestionRelevanceTags"] =
+          includedSuggestionRelevanceTags
+              .map((IncludedSuggestionRelevanceTag value) => value.toJson())
+              .toList();
+    }
     return result;
   }
 
@@ -5589,7 +6666,17 @@
           replacementLength == other.replacementLength &&
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
-          isLast == other.isLast;
+          isLast == other.isLast &&
+          listEqual(includedSuggestionSets, other.includedSuggestionSets,
+              (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
+          listEqual(includedSuggestionKinds, other.includedSuggestionKinds,
+              (ElementKind a, ElementKind b) => a == b) &&
+          listEqual(
+              includedSuggestionRelevanceTags,
+              other.includedSuggestionRelevanceTags,
+              (IncludedSuggestionRelevanceTag a,
+                      IncludedSuggestionRelevanceTag b) =>
+                  a == b);
     }
     return false;
   }
@@ -5602,11 +6689,191 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedSuggestionKinds.hashCode);
+    hash =
+        JenkinsSmiHash.combine(hash, includedSuggestionRelevanceTags.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
 
 /**
+ * CompletionService
+ *
+ * enum {
+ *   AVAILABLE_SUGGESTION_SETS
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionService implements Enum {
+  /**
+   * The client will receive notifications once subscribed with completion
+   * suggestion sets from the libraries of interest. The client should keep an
+   * up-to-date record of these in memory so that it will be able to union
+   * these candidates with other completion suggestions when applicable at
+   * completion time.
+   */
+  static const CompletionService AVAILABLE_SUGGESTION_SETS =
+      const CompletionService._("AVAILABLE_SUGGESTION_SETS");
+
+  /**
+   * A list containing all of the enum values that are defined.
+   */
+  static const List<CompletionService> VALUES = const <CompletionService>[
+    AVAILABLE_SUGGESTION_SETS
+  ];
+
+  @override
+  final String name;
+
+  const CompletionService._(this.name);
+
+  factory CompletionService(String name) {
+    switch (name) {
+      case "AVAILABLE_SUGGESTION_SETS":
+        return AVAILABLE_SUGGESTION_SETS;
+    }
+    throw new Exception('Illegal enum value: $name');
+  }
+
+  factory CompletionService.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json is String) {
+      try {
+        return new CompletionService(json);
+      } catch (_) {
+        // Fall through
+      }
+    }
+    throw jsonDecoder.mismatch(jsonPath, "CompletionService", json);
+  }
+
+  @override
+  String toString() => "CompletionService.$name";
+
+  String toJson() => name;
+}
+
+/**
+ * completion.setSubscriptions params
+ *
+ * {
+ *   "subscriptions": List<CompletionService>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionSetSubscriptionsParams implements RequestParams {
+  List<CompletionService> _subscriptions;
+
+  /**
+   * A list of the services being subscribed to.
+   */
+  List<CompletionService> get subscriptions => _subscriptions;
+
+  /**
+   * A list of the services being subscribed to.
+   */
+  void set subscriptions(List<CompletionService> value) {
+    assert(value != null);
+    this._subscriptions = value;
+  }
+
+  CompletionSetSubscriptionsParams(List<CompletionService> subscriptions) {
+    this.subscriptions = subscriptions;
+  }
+
+  factory CompletionSetSubscriptionsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<CompletionService> subscriptions;
+      if (json.containsKey("subscriptions")) {
+        subscriptions = jsonDecoder.decodeList(
+            jsonPath + ".subscriptions",
+            json["subscriptions"],
+            (String jsonPath, Object json) =>
+                new CompletionService.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "subscriptions");
+      }
+      return new CompletionSetSubscriptionsParams(subscriptions);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.setSubscriptions params", json);
+    }
+  }
+
+  factory CompletionSetSubscriptionsParams.fromRequest(Request request) {
+    return new CompletionSetSubscriptionsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["subscriptions"] =
+        subscriptions.map((CompletionService value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.setSubscriptions", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionSetSubscriptionsParams) {
+      return listEqual(subscriptions, other.subscriptions,
+          (CompletionService a, CompletionService b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, subscriptions.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.setSubscriptions result
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionSetSubscriptionsResult implements ResponseResult {
+  @override
+  Map<String, dynamic> toJson() => <String, dynamic>{};
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: null);
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionSetSubscriptionsResult) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    return 2482770;
+  }
+}
+
+/**
  * ContextData
  *
  * {
@@ -5877,6 +7144,132 @@
 }
 
 /**
+ * DartFix
+ *
+ * {
+ *   "name": String
+ *   "description": optional String
+ *   "isRequired": optional bool
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DartFix implements HasToJson {
+  String _name;
+
+  String _description;
+
+  bool _isRequired;
+
+  /**
+   * The name of the fix.
+   */
+  String get name => _name;
+
+  /**
+   * The name of the fix.
+   */
+  void set name(String value) {
+    assert(value != null);
+    this._name = value;
+  }
+
+  /**
+   * A human readable description of the fix.
+   */
+  String get description => _description;
+
+  /**
+   * A human readable description of the fix.
+   */
+  void set description(String value) {
+    this._description = value;
+  }
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  bool get isRequired => _isRequired;
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  void set isRequired(bool value) {
+    this._isRequired = value;
+  }
+
+  DartFix(String name, {String description, bool isRequired}) {
+    this.name = name;
+    this.description = description;
+    this.isRequired = isRequired;
+  }
+
+  factory DartFix.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String name;
+      if (json.containsKey("name")) {
+        name = jsonDecoder.decodeString(jsonPath + ".name", json["name"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "name");
+      }
+      String description;
+      if (json.containsKey("description")) {
+        description = jsonDecoder.decodeString(
+            jsonPath + ".description", json["description"]);
+      }
+      bool isRequired;
+      if (json.containsKey("isRequired")) {
+        isRequired = jsonDecoder.decodeBool(
+            jsonPath + ".isRequired", json["isRequired"]);
+      }
+      return new DartFix(name,
+          description: description, isRequired: isRequired);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "DartFix", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["name"] = name;
+    if (description != null) {
+      result["description"] = description;
+    }
+    if (isRequired != null) {
+      result["isRequired"] = isRequired;
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is DartFix) {
+      return name == other.name &&
+          description == other.description &&
+          isRequired == other.isRequired;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, name.hashCode);
+    hash = JenkinsSmiHash.combine(hash, description.hashCode);
+    hash = JenkinsSmiHash.combine(hash, isRequired.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * DartFixSuggestion
  *
  * {
@@ -6214,6 +7607,9 @@
  *
  * {
  *   "included": List<FilePath>
+ *   "includedFixes": optional List<String>
+ *   "includeRequiredFixes": optional bool
+ *   "excludedFixes": optional List<String>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -6221,6 +7617,12 @@
 class EditDartfixParams implements RequestParams {
   List<String> _included;
 
+  List<String> _includedFixes;
+
+  bool _includeRequiredFixes;
+
+  List<String> _excludedFixes;
+
   /**
    * A list of the files and directories for which edits should be suggested.
    *
@@ -6248,8 +7650,62 @@
     this._included = value;
   }
 
-  EditDartfixParams(List<String> included) {
+  /**
+   * A list of names indicating which fixes should be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  List<String> get includedFixes => _includedFixes;
+
+  /**
+   * A list of names indicating which fixes should be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  void set includedFixes(List<String> value) {
+    this._includedFixes = value;
+  }
+
+  /**
+   * A flag indicating that "required" fixes should be applied.
+   */
+  bool get includeRequiredFixes => _includeRequiredFixes;
+
+  /**
+   * A flag indicating that "required" fixes should be applied.
+   */
+  void set includeRequiredFixes(bool value) {
+    this._includeRequiredFixes = value;
+  }
+
+  /**
+   * A list of names indicating which fixes should not be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  List<String> get excludedFixes => _excludedFixes;
+
+  /**
+   * A list of names indicating which fixes should not be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  void set excludedFixes(List<String> value) {
+    this._excludedFixes = value;
+  }
+
+  EditDartfixParams(List<String> included,
+      {List<String> includedFixes,
+      bool includeRequiredFixes,
+      List<String> excludedFixes}) {
     this.included = included;
+    this.includedFixes = includedFixes;
+    this.includeRequiredFixes = includeRequiredFixes;
+    this.excludedFixes = excludedFixes;
   }
 
   factory EditDartfixParams.fromJson(
@@ -6265,7 +7721,25 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "included");
       }
-      return new EditDartfixParams(included);
+      List<String> includedFixes;
+      if (json.containsKey("includedFixes")) {
+        includedFixes = jsonDecoder.decodeList(jsonPath + ".includedFixes",
+            json["includedFixes"], jsonDecoder.decodeString);
+      }
+      bool includeRequiredFixes;
+      if (json.containsKey("includeRequiredFixes")) {
+        includeRequiredFixes = jsonDecoder.decodeBool(
+            jsonPath + ".includeRequiredFixes", json["includeRequiredFixes"]);
+      }
+      List<String> excludedFixes;
+      if (json.containsKey("excludedFixes")) {
+        excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
+            json["excludedFixes"], jsonDecoder.decodeString);
+      }
+      return new EditDartfixParams(included,
+          includedFixes: includedFixes,
+          includeRequiredFixes: includeRequiredFixes,
+          excludedFixes: excludedFixes);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
     }
@@ -6280,6 +7754,15 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["included"] = included;
+    if (includedFixes != null) {
+      result["includedFixes"] = includedFixes;
+    }
+    if (includeRequiredFixes != null) {
+      result["includeRequiredFixes"] = includeRequiredFixes;
+    }
+    if (excludedFixes != null) {
+      result["excludedFixes"] = excludedFixes;
+    }
     return result;
   }
 
@@ -6295,7 +7778,12 @@
   bool operator ==(other) {
     if (other is EditDartfixParams) {
       return listEqual(
-          included, other.included, (String a, String b) => a == b);
+              included, other.included, (String a, String b) => a == b) &&
+          listEqual(includedFixes, other.includedFixes,
+              (String a, String b) => a == b) &&
+          includeRequiredFixes == other.includeRequiredFixes &&
+          listEqual(excludedFixes, other.excludedFixes,
+              (String a, String b) => a == b);
     }
     return false;
   }
@@ -6304,6 +7792,9 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, included.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -7267,6 +8758,152 @@
 }
 
 /**
+ * edit.getDartfixInfo params
+ *
+ * {
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class EditGetDartfixInfoParams implements RequestParams {
+  EditGetDartfixInfoParams();
+
+  factory EditGetDartfixInfoParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      return new EditGetDartfixInfoParams();
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.getDartfixInfo params", json);
+    }
+  }
+
+  factory EditGetDartfixInfoParams.fromRequest(Request request) {
+    return new EditGetDartfixInfoParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "edit.getDartfixInfo", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is EditGetDartfixInfoParams) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * edit.getDartfixInfo result
+ *
+ * {
+ *   "fixes": List<DartFix>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class EditGetDartfixInfoResult implements ResponseResult {
+  List<DartFix> _fixes;
+
+  /**
+   * A list of fixes that can be specified in an edit.dartfix request.
+   */
+  List<DartFix> get fixes => _fixes;
+
+  /**
+   * A list of fixes that can be specified in an edit.dartfix request.
+   */
+  void set fixes(List<DartFix> value) {
+    assert(value != null);
+    this._fixes = value;
+  }
+
+  EditGetDartfixInfoResult(List<DartFix> fixes) {
+    this.fixes = fixes;
+  }
+
+  factory EditGetDartfixInfoResult.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<DartFix> fixes;
+      if (json.containsKey("fixes")) {
+        fixes = jsonDecoder.decodeList(
+            jsonPath + ".fixes",
+            json["fixes"],
+            (String jsonPath, Object json) =>
+                new DartFix.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "fixes");
+      }
+      return new EditGetDartfixInfoResult(fixes);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.getDartfixInfo result", json);
+    }
+  }
+
+  factory EditGetDartfixInfoResult.fromResponse(Response response) {
+    return new EditGetDartfixInfoResult.fromJson(
+        new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        "result",
+        response.result);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["fixes"] = fixes.map((DartFix value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is EditGetDartfixInfoResult) {
+      return listEqual(fixes, other.fixes, (DartFix a, DartFix b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, fixes.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * edit.getFixes params
  *
  * {
@@ -14330,6 +15967,213 @@
 }
 
 /**
+ * IncludedSuggestionRelevanceTag
+ *
+ * {
+ *   "tag": AvailableSuggestionRelevanceTag
+ *   "relevanceBoost": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class IncludedSuggestionRelevanceTag implements HasToJson {
+  String _tag;
+
+  int _relevanceBoost;
+
+  /**
+   * The opaque value of the tag.
+   */
+  String get tag => _tag;
+
+  /**
+   * The opaque value of the tag.
+   */
+  void set tag(String value) {
+    assert(value != null);
+    this._tag = value;
+  }
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this
+   * tag, which is added to the relevance of the containing
+   * IncludedSuggestionSet.
+   */
+  int get relevanceBoost => _relevanceBoost;
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this
+   * tag, which is added to the relevance of the containing
+   * IncludedSuggestionSet.
+   */
+  void set relevanceBoost(int value) {
+    assert(value != null);
+    this._relevanceBoost = value;
+  }
+
+  IncludedSuggestionRelevanceTag(String tag, int relevanceBoost) {
+    this.tag = tag;
+    this.relevanceBoost = relevanceBoost;
+  }
+
+  factory IncludedSuggestionRelevanceTag.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String tag;
+      if (json.containsKey("tag")) {
+        tag = jsonDecoder.decodeString(jsonPath + ".tag", json["tag"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "tag");
+      }
+      int relevanceBoost;
+      if (json.containsKey("relevanceBoost")) {
+        relevanceBoost = jsonDecoder.decodeInt(
+            jsonPath + ".relevanceBoost", json["relevanceBoost"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "relevanceBoost");
+      }
+      return new IncludedSuggestionRelevanceTag(tag, relevanceBoost);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "IncludedSuggestionRelevanceTag", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["tag"] = tag;
+    result["relevanceBoost"] = relevanceBoost;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is IncludedSuggestionRelevanceTag) {
+      return tag == other.tag && relevanceBoost == other.relevanceBoost;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, tag.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevanceBoost.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * IncludedSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "relevance": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class IncludedSuggestionSet implements HasToJson {
+  int _id;
+
+  int _relevance;
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be
+   * displayed to the user.
+   */
+  int get id => _id;
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be
+   * displayed to the user.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The relevance of completion suggestions from this library where a higher
+   * number indicates a higher relevance.
+   */
+  int get relevance => _relevance;
+
+  /**
+   * The relevance of completion suggestions from this library where a higher
+   * number indicates a higher relevance.
+   */
+  void set relevance(int value) {
+    assert(value != null);
+    this._relevance = value;
+  }
+
+  IncludedSuggestionSet(int id, int relevance) {
+    this.id = id;
+    this.relevance = relevance;
+  }
+
+  factory IncludedSuggestionSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      int relevance;
+      if (json.containsKey("relevance")) {
+        relevance =
+            jsonDecoder.decodeInt(jsonPath + ".relevance", json["relevance"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "relevance");
+      }
+      return new IncludedSuggestionSet(id, relevance);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "IncludedSuggestionSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["id"] = id;
+    result["relevance"] = relevance;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is IncludedSuggestionSet) {
+      return id == other.id && relevance == other.relevance;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * inlineLocalVariable feedback
  *
  * {
@@ -14905,6 +16749,113 @@
 }
 
 /**
+ * LibraryPathSet
+ *
+ * {
+ *   "scope": FilePath
+ *   "libraryPaths": List<FilePath>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class LibraryPathSet implements HasToJson {
+  String _scope;
+
+  List<String> _libraryPaths;
+
+  /**
+   * The filepath for which this request's libraries should be active in
+   * completion suggestions. This object associates filesystem regions to
+   * libraries and library directories of interest to the client.
+   */
+  String get scope => _scope;
+
+  /**
+   * The filepath for which this request's libraries should be active in
+   * completion suggestions. This object associates filesystem regions to
+   * libraries and library directories of interest to the client.
+   */
+  void set scope(String value) {
+    assert(value != null);
+    this._scope = value;
+  }
+
+  /**
+   * The paths of the libraries of interest to the client for completion
+   * suggestions.
+   */
+  List<String> get libraryPaths => _libraryPaths;
+
+  /**
+   * The paths of the libraries of interest to the client for completion
+   * suggestions.
+   */
+  void set libraryPaths(List<String> value) {
+    assert(value != null);
+    this._libraryPaths = value;
+  }
+
+  LibraryPathSet(String scope, List<String> libraryPaths) {
+    this.scope = scope;
+    this.libraryPaths = libraryPaths;
+  }
+
+  factory LibraryPathSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String scope;
+      if (json.containsKey("scope")) {
+        scope = jsonDecoder.decodeString(jsonPath + ".scope", json["scope"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "scope");
+      }
+      List<String> libraryPaths;
+      if (json.containsKey("libraryPaths")) {
+        libraryPaths = jsonDecoder.decodeList(jsonPath + ".libraryPaths",
+            json["libraryPaths"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "libraryPaths");
+      }
+      return new LibraryPathSet(scope, libraryPaths);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "LibraryPathSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["scope"] = scope;
+    result["libraryPaths"] = libraryPaths;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is LibraryPathSet) {
+      return scope == other.scope &&
+          listEqual(
+              libraryPaths, other.libraryPaths, (String a, String b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, scope.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryPaths.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * moveFile feedback
  *
  * Clients may not extend, implement or mix-in this class.
@@ -15953,6 +17904,7 @@
  *   SERVER_ERROR
  *   SORT_MEMBERS_INVALID_FILE
  *   SORT_MEMBERS_PARSE_ERRORS
+ *   UNKNOWN_FIX
  *   UNKNOWN_REQUEST
  *   UNSUPPORTED_FEATURE
  * }
@@ -16143,6 +18095,13 @@
       const RequestErrorCode._("SORT_MEMBERS_PARSE_ERRORS");
 
   /**
+   * A dartfix request was received containing the name of a fix which does not
+   * match the name of any known fixes.
+   */
+  static const RequestErrorCode UNKNOWN_FIX =
+      const RequestErrorCode._("UNKNOWN_FIX");
+
+  /**
    * A request was received which the analysis server does not recognize, or
    * cannot handle in its current configuration.
    */
@@ -16189,6 +18148,7 @@
     SERVER_ERROR,
     SORT_MEMBERS_INVALID_FILE,
     SORT_MEMBERS_PARSE_ERRORS,
+    UNKNOWN_FIX,
     UNKNOWN_REQUEST,
     UNSUPPORTED_FEATURE
   ];
@@ -16252,6 +18212,8 @@
         return SORT_MEMBERS_INVALID_FILE;
       case "SORT_MEMBERS_PARSE_ERRORS":
         return SORT_MEMBERS_PARSE_ERRORS;
+      case "UNKNOWN_FIX":
+        return UNKNOWN_FIX;
       case "UNKNOWN_REQUEST":
         return UNKNOWN_REQUEST;
       case "UNSUPPORTED_FEATURE":
diff --git a/pkg/analysis_server/lib/src/analysis_server.dart b/pkg/analysis_server/lib/src/analysis_server.dart
index aff4e6b..745f48d 100644
--- a/pkg/analysis_server/lib/src/analysis_server.dart
+++ b/pkg/analysis_server/lib/src/analysis_server.dart
@@ -31,6 +31,7 @@
 import 'package:analysis_server/src/domains/analysis/navigation_dart.dart';
 import 'package:analysis_server/src/domains/analysis/occurrences.dart';
 import 'package:analysis_server/src/domains/analysis/occurrences_dart.dart';
+import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/edit/edit_domain.dart';
 import 'package:analysis_server/src/flutter/flutter_domain.dart';
 import 'package:analysis_server/src/flutter/flutter_notifications.dart';
@@ -65,6 +66,7 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/utilities_general.dart';
 import 'package:analyzer/src/plugin/resolver_provider.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
 import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
 import 'package:telemetry/crash_reporting.dart';
@@ -150,6 +152,7 @@
 
   ByteStore byteStore;
   nd.AnalysisDriverScheduler analysisDriverScheduler;
+  DeclarationsTracker declarationsTracker;
 
   /// The controller for [onAnalysisSetChanged].
   final StreamController _onAnalysisSetChangedController =
@@ -276,6 +279,36 @@
     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);
+  }
+
+  /// 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);
+    }
+  }
+
+  void disposeDeclarationsTracker() {
+    declarationsTracker = null;
+    analysisDriverScheduler.outOfBandWorker = null;
+  }
+
   /// The socket from which requests are being read has been closed.
   void done() {}
 
@@ -483,6 +516,7 @@
   /// projects/contexts support.
   void setAnalysisRoots(String requestId, List<String> includedPaths,
       List<String> excludedPaths, Map<String, String> packageRoots) {
+    declarationsTracker?.discardContexts();
     if (notificationManager != null) {
       notificationManager.setAnalysisRoots(includedPaths, excludedPaths);
     }
@@ -492,6 +526,7 @@
       throw new RequestFailure(
           new Response.unsupportedFeature(requestId, e.message));
     }
+    _addContextsToDeclarationsTracker();
   }
 
   /// Implementation for `analysis.setSubscriptions`.
@@ -623,8 +658,11 @@
       }
 
       if (newContents != null) {
-        resourceProvider.setOverlay(file,
-            content: newContents, modificationStamp: 0);
+        resourceProvider.setOverlay(
+          file,
+          content: newContents,
+          modificationStamp: overlayModificationStamp++,
+        );
       } else {
         resourceProvider.removeOverlay(file);
       }
@@ -637,6 +675,8 @@
       // analyzed. Add it to driver to which it should have been added.
       contextManager.getDriverFor(file)?.addFile(file);
 
+      notifyDeclarationsTracker(file);
+
       // TODO(scheglov) implement other cases
     });
   }
@@ -666,6 +706,15 @@
 //    });
   }
 
+  void _addContextsToDeclarationsTracker() {
+    if (declarationsTracker != null) {
+      for (var driver in driverMap.values) {
+        declarationsTracker.addContext(driver.analysisContext);
+        driver.resetUriResolution();
+      }
+    }
+  }
+
   /// Return the path to the location of the byte store on disk, or `null` if
   /// there is no on-disk byte store.
   String _getByteStorePath() {
@@ -913,6 +962,7 @@
 
   @override
   void broadcastWatchEvent(WatchEvent event) {
+    analysisServer.notifyDeclarationsTracker(event.path);
     analysisServer.pluginManager.broadcastWatchEvent(event);
   }
 
diff --git a/pkg/analysis_server/lib/src/analysis_server_abstract.dart b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
index b0b3d34..50834b3 100644
--- a/pkg/analysis_server/lib/src/analysis_server_abstract.dart
+++ b/pkg/analysis_server/lib/src/analysis_server_abstract.dart
@@ -25,6 +25,7 @@
     show EvictingFileByteStore;
 import 'package:analyzer/src/dart/analysis/file_state.dart' as nd;
 import 'package:analyzer/src/dart/analysis/status.dart' as nd;
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/util/glob.dart';
@@ -75,6 +76,9 @@
   /// The [ResourceProvider] using which paths are converted into [Resource]s.
   final OverlayResourceProvider resourceProvider;
 
+  /// The next modification stamp for a changed file in the [resourceProvider].
+  int overlayModificationStamp = 0;
+
   /// A list of the globs used to determine which files should be analyzed. The
   /// list is lazily created and should be accessed using [analyzedFilesGlobs].
   List<Glob> _analyzedFilesGlobs = null;
@@ -228,6 +232,15 @@
     return null;
   }
 
+  /// Return the unresolved unit for the file with the given [path].
+  ParsedUnitResult getParsedUnit(String path) {
+    if (!AnalysisEngine.isDartFileName(path)) {
+      return null;
+    }
+
+    return getAnalysisDriver(path)?.currentSession?.getParsedUnit(path);
+  }
+
   /// Return the resolved unit for the file with the given [path]. The file is
   /// analyzed in one of the analysis drivers to which the file was added,
   /// otherwise in the first driver, otherwise `null` is returned.
@@ -246,13 +259,4 @@
         .getResult(path, sendCachedToStream: sendCachedToStream)
         .catchError((_) => null);
   }
-
-  /// Return the unresolved unit for the file with the given [path].
-  ParsedUnitResult getParsedUnit(String path) {
-    if (!AnalysisEngine.isDartFileName(path)) {
-      return null;
-    }
-
-    return getAnalysisDriver(path)?.currentSession?.getParsedUnit(path);
-  }
 }
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights.dart b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
index dddc8b4..0076909 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights.dart
@@ -415,20 +415,6 @@
   }
 
   @override
-  void visitCollectionForElement(CollectionForElement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
-    super.visitCollectionForElement(node);
-  }
-
-  @override
-  void visitCollectionIfElement(CollectionIfElement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
-    super.visitCollectionIfElement(node);
-  }
-
-  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     computer._addRegion_token(
         node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -509,6 +495,13 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+    super.visitForElement(node);
+  }
+
+  @override
   void visitForStatement(ForStatement node) {
     computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
     super.visitForStatement(node);
@@ -557,6 +550,13 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
@@ -622,20 +622,6 @@
   }
 
   @override
-  void visitMapForElement(MapForElement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
-    super.visitMapForElement(node);
-  }
-
-  @override
-  void visitMapIfElement(MapIfElement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
-    super.visitMapIfElement(node);
-  }
-
-  @override
   void visitMapLiteral(MapLiteral node) {
     computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
     computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
diff --git a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
index aaea61e..1f0326f 100644
--- a/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_highlights2.dart
@@ -506,20 +506,6 @@
   }
 
   @override
-  void visitCollectionForElement(CollectionForElement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
-    super.visitCollectionForElement(node);
-  }
-
-  @override
-  void visitCollectionIfElement(CollectionIfElement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
-    super.visitCollectionIfElement(node);
-  }
-
-  @override
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     computer._addRegion_token(
         node.externalKeyword, HighlightRegionType.BUILT_IN);
@@ -600,6 +586,13 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
+    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
+    super.visitForElement(node);
+  }
+
+  @override
   void visitForStatement(ForStatement node) {
     computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
     super.visitForStatement(node);
@@ -648,6 +641,13 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
+    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
     computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
@@ -719,20 +719,6 @@
   }
 
   @override
-  void visitMapForElement(MapForElement node) {
-    computer._addRegion_token(node.awaitKeyword, HighlightRegionType.BUILT_IN);
-    computer._addRegion_token(node.forKeyword, HighlightRegionType.KEYWORD);
-    super.visitMapForElement(node);
-  }
-
-  @override
-  void visitMapIfElement(MapIfElement node) {
-    computer._addRegion_token(node.ifKeyword, HighlightRegionType.KEYWORD);
-    computer._addRegion_token(node.elseKeyword, HighlightRegionType.KEYWORD);
-    super.visitMapIfElement(node);
-  }
-
-  @override
   void visitMapLiteral(MapLiteral node) {
     computer._addRegion_node(node, HighlightRegionType.LITERAL_MAP);
     computer._addRegion_token(node.constKeyword, HighlightRegionType.KEYWORD);
diff --git a/pkg/analysis_server/lib/src/computer/computer_hover.dart b/pkg/analysis_server/lib/src/computer/computer_hover.dart
index eb20b24..3af0fbd 100644
--- a/pkg/analysis_server/lib/src/computer/computer_hover.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_hover.dart
@@ -5,11 +5,12 @@
 import 'package:analysis_server/protocol/protocol_generated.dart'
     show HoverInformation;
 import 'package:analysis_server/src/computer/computer_overrides.dart';
-import 'package:analysis_server/src/utilities/documentation.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/util/comment.dart';
 
 /**
  * A computer for the hover at the specified offset of a Dart [CompilationUnit].
@@ -118,7 +119,7 @@
     }
     // The documentation of the element itself.
     if (element.documentationComment != null) {
-      return removeDartDocDelimiters(element.documentationComment);
+      return getDartDocPlainText(element.documentationComment);
     }
     // Look for documentation comments of overridden members.
     OverriddenElements overridden = findOverriddenElements(element);
@@ -128,7 +129,7 @@
       String rawDoc = superElement.documentationComment;
       if (rawDoc != null) {
         Element interfaceClass = superElement.enclosingElement;
-        return removeDartDocDelimiters(rawDoc) +
+        return getDartDocPlainText(rawDoc) +
             '\n\nCopied from `${interfaceClass.displayName}`.';
       }
     }
diff --git a/pkg/analysis_server/lib/src/computer/computer_overrides.dart b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
index cd1ff67..7eb2b68 100644
--- a/pkg/analysis_server/lib/src/computer/computer_overrides.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_overrides.dart
@@ -32,7 +32,7 @@
    */
   List<proto.Override> compute() {
     for (CompilationUnitMember unitMember in _unit.declarations) {
-      if (unitMember is ClassDeclaration) {
+      if (unitMember is ClassOrMixinDeclaration) {
         for (ClassMember classMember in unitMember.members) {
           if (classMember is MethodDeclaration) {
             if (classMember.isStatic) {
@@ -198,6 +198,7 @@
 
     _addSuperOverrides(type.superclass);
     type.mixins.forEach(_addSuperOverrides);
+    type.superclassConstraints.forEach(_addSuperOverrides);
   }
 
   Element _lookupMember(ClassElement classElement) {
diff --git a/pkg/analysis_server/lib/src/computer/computer_signature.dart b/pkg/analysis_server/lib/src/computer/computer_signature.dart
index 518a488..2dd950c 100644
--- a/pkg/analysis_server/lib/src/computer/computer_signature.dart
+++ b/pkg/analysis_server/lib/src/computer/computer_signature.dart
@@ -8,6 +8,7 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 
 /**
diff --git a/pkg/analysis_server/lib/src/domain_completion.dart b/pkg/analysis_server/lib/src/domain_completion.dart
index c70db3b..b9d51ae 100644
--- a/pkg/analysis_server/lib/src/domain_completion.dart
+++ b/pkg/analysis_server/lib/src/domain_completion.dart
@@ -10,6 +10,7 @@
 import 'package:analysis_server/src/analysis_server.dart';
 import 'package:analysis_server/src/collections.dart';
 import 'package:analysis_server/src/domain_abstract.dart';
+import 'package:analysis_server/src/domains/completion/available_suggestions.dart';
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/provisional/completion/completion_core.dart';
 import 'package:analysis_server/src/services/completion/completion_core.dart';
@@ -21,6 +22,7 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
 import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 
 /**
  * Instances of the class [CompletionDomainHandler] implement a [RequestHandler]
@@ -33,6 +35,11 @@
   static const int performanceListMaxLength = 50;
 
   /**
+   * The completion services that the client is currently subscribed.
+   */
+  final Set<CompletionService> _subscriptions = Set<CompletionService>();
+
+  /**
    * The next completion response id.
    */
   int _nextCompletionId = 0;
@@ -66,8 +73,12 @@
    * Subclasses should override this method, append at least one result
    * to the [controller], and close the controller stream once complete.
    */
-  Future<CompletionResult> computeSuggestions(CompletionRequestImpl request,
-      CompletionGetSuggestionsParams params) async {
+  Future<CompletionResult> computeSuggestions(
+    CompletionRequestImpl request,
+    CompletionGetSuggestionsParams params,
+    Set<ElementKind> includedSuggestionKinds,
+    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
+  ) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     //
@@ -91,11 +102,15 @@
       const COMPUTE_SUGGESTIONS_TAG = 'computeSuggestions';
       performance.logStartTime(COMPUTE_SUGGESTIONS_TAG);
 
-      CompletionContributor contributor = new DartCompletionManager();
-      String contributorTag = 'computeSuggestions - ${contributor.runtimeType}';
+      var manager = new DartCompletionManager(
+        includedSuggestionKinds: includedSuggestionKinds,
+        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+      );
+
+      String contributorTag = 'computeSuggestions - ${manager.runtimeType}';
       performance.logStartTime(contributorTag);
       try {
-        suggestions.addAll(await contributor.computeSuggestions(request));
+        suggestions.addAll(await manager.computeSuggestions(request));
       } on AbortCompletion {
         suggestions.clear();
       }
@@ -136,13 +151,78 @@
         request.replacementOffset, request.replacementLength, suggestions);
   }
 
+  /**
+   * Process a `completion.getSuggestionDetails` request.
+   */
+  void getSuggestionDetails(Request request) async {
+    var params = CompletionGetSuggestionDetailsParams.fromRequest(request);
+
+    var file = params.file;
+    if (server.sendResponseErrorIfInvalidFilePath(request, file)) {
+      return;
+    }
+
+    var libraryId = params.id;
+    var library = server.declarationsTracker.getLibrary(libraryId);
+    if (library == null) {
+      server.sendResponse(Response.invalidParameter(
+        request,
+        'libraryId',
+        'No such library: $libraryId',
+      ));
+      return;
+    }
+
+    var analysisDriver = server.getAnalysisDriver(file);
+    var session = analysisDriver.currentSession;
+    var resolvedLibrary = await session.getResolvedLibrary(file);
+    var requestedLibraryElement = await session.getLibraryByUri(library.uriStr);
+
+    // The label might be `MyEnum.myValue`, but we import only `MyEnum`.
+    var requestedName = params.label;
+    if (requestedName.contains('.')) {
+      requestedName = requestedName.substring(
+        0,
+        requestedName.indexOf('.'),
+      );
+    }
+
+    var completion = params.label;
+    var builder = DartChangeBuilder(session);
+    await builder.addFileEdit(file, (builder) {
+      var result = builder.importLibraryElement(
+        targetLibrary: resolvedLibrary,
+        targetPath: file,
+        targetOffset: params.offset,
+        requestedLibrary: requestedLibraryElement,
+        requestedName: requestedName,
+      );
+      if (result.prefix != null) {
+        completion = '${result.prefix}.$completion';
+      }
+    });
+
+    server.sendResponse(
+      CompletionGetSuggestionDetailsResult(
+        completion,
+        change: builder.sourceChange,
+      ).toResponse(request.id),
+    );
+  }
+
   @override
   Response handleRequest(Request request) {
     return runZoned(() {
       String requestName = request.method;
-      if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
+
+      if (requestName == COMPLETION_REQUEST_GET_SUGGESTION_DETAILS) {
+        getSuggestionDetails(request);
+        return Response.DELAYED_RESPONSE;
+      } else if (requestName == COMPLETION_REQUEST_GET_SUGGESTIONS) {
         processRequest(request);
         return Response.DELAYED_RESPONSE;
+      } else if (requestName == COMPLETION_REQUEST_SET_SUBSCRIPTIONS) {
+        return setSubscriptions(request);
       }
       return null;
     }, onError: (exception, stackTrace) {
@@ -177,10 +257,9 @@
       return;
     }
 
-    ResolvedUnitResult result = await server.getResolvedUnit(file);
-
-    if (result?.state == ResultState.VALID) {
-      if (offset < 0 || offset > result.content.length) {
+    ResolvedUnitResult resolvedUnit = await server.getResolvedUnit(file);
+    if (resolvedUnit?.state == ResultState.VALID) {
+      if (offset < 0 || offset > resolvedUnit.content.length) {
         server.sendResponse(new Response.invalidParameter(
             request,
             'params.offset',
@@ -189,10 +268,10 @@
         return;
       }
 
-      recordRequest(performance, file, result.content, offset);
+      recordRequest(performance, file, resolvedUnit.content, offset);
     }
     CompletionRequestImpl completionRequest =
-        new CompletionRequestImpl(result, offset, performance);
+        new CompletionRequestImpl(resolvedUnit, offset, performance);
 
     String completionId = (_nextCompletionId++).toString();
 
@@ -202,14 +281,45 @@
     server.sendResponse(new CompletionGetSuggestionsResult(completionId)
         .toResponse(request.id));
 
+    // If the client opted into using available suggestion sets,
+    // create the kinds set, so signal the completion manager about opt-in.
+    Set<ElementKind> includedSuggestionKinds;
+    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+    if (_subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
+      includedSuggestionKinds = Set<ElementKind>();
+      includedSuggestionRelevanceTags = <IncludedSuggestionRelevanceTag>[];
+    }
+
     // Compute suggestions in the background
-    computeSuggestions(completionRequest, params)
-        .then((CompletionResult result) {
+    computeSuggestions(
+      completionRequest,
+      params,
+      includedSuggestionKinds,
+      includedSuggestionRelevanceTags,
+    ).then((CompletionResult result) {
+      List<IncludedSuggestionSet> includedSuggestionSets;
+      if (includedSuggestionKinds != null && resolvedUnit != null) {
+        includedSuggestionSets = computeIncludedSetList(
+          server.declarationsTracker,
+          resolvedUnit,
+        );
+      } else {
+        includedSuggestionSets = [];
+      }
+
       const SEND_NOTIFICATION_TAG = 'send notification';
       performance.logStartTime(SEND_NOTIFICATION_TAG);
-      sendCompletionNotification(completionId, result.replacementOffset,
-          result.replacementLength, result.suggestions);
+      sendCompletionNotification(
+        completionId,
+        result.replacementOffset,
+        result.replacementLength,
+        result.suggestions,
+        includedSuggestionSets,
+        includedSuggestionKinds?.toList(),
+        includedSuggestionRelevanceTags,
+      );
       performance.logElapseTime(SEND_NOTIFICATION_TAG);
+
       performance.notificationCount = 1;
       performance.logFirstNotificationComplete('notification 1 complete');
       performance.suggestionCountFirst = result.suggestions.length;
@@ -237,11 +347,27 @@
   /**
    * Send completion notification results.
    */
-  void sendCompletionNotification(String completionId, int replacementOffset,
-      int replacementLength, Iterable<CompletionSuggestion> results) {
-    server.sendNotification(new CompletionResultsParams(
-            completionId, replacementOffset, replacementLength, results, true)
-        .toNotification());
+  void sendCompletionNotification(
+    String completionId,
+    int replacementOffset,
+    int replacementLength,
+    Iterable<CompletionSuggestion> results,
+    List<IncludedSuggestionSet> includedSuggestionSets,
+    List<ElementKind> includedSuggestionKinds,
+    List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags,
+  ) {
+    server.sendNotification(
+      new CompletionResultsParams(
+        completionId,
+        replacementOffset,
+        replacementLength,
+        results,
+        true,
+        includedSuggestionSets: includedSuggestionSets,
+        includedSuggestionKinds: includedSuggestionKinds,
+        includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
+      ).toNotification(),
+    );
   }
 
   void setNewRequest(CompletionRequest completionRequest) {
@@ -250,6 +376,28 @@
   }
 
   /**
+   * Implement the 'completion.setSubscriptions' request.
+   */
+  Response setSubscriptions(Request request) {
+    var params = CompletionSetSubscriptionsParams.fromRequest(request);
+
+    _subscriptions.clear();
+    _subscriptions.addAll(params.subscriptions);
+
+    if (_subscriptions.contains(CompletionService.AVAILABLE_SUGGESTION_SETS)) {
+      server.createDeclarationsTracker((change) {
+        server.sendNotification(
+          createCompletionAvailableSuggestionsNotification(change),
+        );
+      });
+    } else {
+      server.disposeDeclarationsTracker();
+    }
+
+    return CompletionSetSubscriptionsResult().toResponse(request.id);
+  }
+
+  /**
    * Abort the current completion request, if any.
    */
   void _abortCurrentRequest() {
diff --git a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
index 2885948..6139967 100644
--- a/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
+++ b/pkg/analysis_server/lib/src/domains/analysis/implemented_dart.dart
@@ -18,26 +18,11 @@
   ImplementedComputer(this.searchEngine, this.unitElement);
 
   compute() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    for (ClassElement type in unitElement.types) {
-      // Always include Object and its members.
-      if (type.supertype == null) {
-        _addImplementedClass(type);
-        type.accessors.forEach(_addImplementedMember);
-        type.fields.forEach(_addImplementedMember);
-        type.methods.forEach(_addImplementedMember);
-        continue;
-      }
-
-      // Analyze subtypes.
-      subtypeMembers = await searchEngine.membersOfSubtypes(type);
-      if (subtypeMembers != null) {
-        _addImplementedClass(type);
-        type.accessors.forEach(_addMemberIfImplemented);
-        type.fields.forEach(_addMemberIfImplemented);
-        type.methods.forEach(_addMemberIfImplemented);
-      }
+    for (var element in unitElement.mixins) {
+      await _computeForClassElement(element);
+    }
+    for (var element in unitElement.types) {
+      await _computeForClassElement(element);
     }
   }
 
@@ -62,6 +47,26 @@
     }
   }
 
+  Future<void> _computeForClassElement(ClassElement element) async {
+    // Always include Object and its members.
+    if (element.supertype == null && !element.isMixin) {
+      _addImplementedClass(element);
+      element.accessors.forEach(_addImplementedMember);
+      element.fields.forEach(_addImplementedMember);
+      element.methods.forEach(_addImplementedMember);
+      return;
+    }
+
+    // Analyze subtypes.
+    subtypeMembers = await searchEngine.membersOfSubtypes(element);
+    if (subtypeMembers != null) {
+      _addImplementedClass(element);
+      element.accessors.forEach(_addMemberIfImplemented);
+      element.fields.forEach(_addMemberIfImplemented);
+      element.methods.forEach(_addMemberIfImplemented);
+    }
+  }
+
   bool _hasOverride(Element element) {
     String name = element.displayName;
     return subtypeMembers.contains(name);
diff --git a/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
new file mode 100644
index 0000000..69f51f6
--- /dev/null
+++ b/pkg/analysis_server/lib/src/domains/completion/available_suggestions.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart' as protocol;
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/dart/analysis/driver.dart';
+import 'package:analyzer/src/services/available_declarations.dart';
+
+/// Compute which suggestion sets should be included into completion inside
+/// the given [resolvedUnit] of a file.  Depending on the file path, it might
+/// include different sets, e.g. inside the `lib/` directory of a `Pub` package
+/// only regular dependencies can be referenced, but `test/` can reference
+/// both regular and "dev" dependencies.
+List<protocol.IncludedSuggestionSet> computeIncludedSetList(
+  DeclarationsTracker tracker,
+  ResolvedUnitResult resolvedUnit,
+) {
+  var analysisContext = resolvedUnit.session.analysisContext;
+  var context = tracker.getContext(analysisContext);
+  if (context == null) return const [];
+
+  var librariesObject = context.getLibraries(resolvedUnit.path);
+  var includedSetList = <protocol.IncludedSuggestionSet>[];
+
+  var importedUriSet = resolvedUnit.libraryElement.importedLibraries
+      .map((importedLibrary) => importedLibrary.source.uri)
+      .toSet();
+
+  void includeLibrary(
+    Library library,
+    int importedRelevance,
+    int deprecatedRelevance,
+    int otherwiseRelevance,
+  ) {
+    int relevance;
+    if (importedUriSet.contains(library.uri)) {
+      relevance = importedRelevance;
+    } else if (library.isDeprecated) {
+      relevance = deprecatedRelevance;
+    } else {
+      relevance = otherwiseRelevance;
+    }
+
+    includedSetList.add(
+      protocol.IncludedSuggestionSet(library.id, relevance),
+    );
+  }
+
+  for (var library in librariesObject.context) {
+    includeLibrary(library, 8, 2, 5);
+  }
+
+  for (var library in librariesObject.dependencies) {
+    includeLibrary(library, 7, 1, 4);
+  }
+
+  for (var library in librariesObject.sdk) {
+    includeLibrary(library, 6, 0, 3);
+  }
+
+  return includedSetList;
+}
+
+/// Convert the [LibraryChange] into the corresponding protocol notification.
+protocol.Notification createCompletionAvailableSuggestionsNotification(
+  LibraryChange change,
+) {
+  return protocol.CompletionAvailableSuggestionsParams(
+    changedLibraries: change.changed.map((library) {
+      return protocol.AvailableSuggestionSet(
+        library.id,
+        library.uriStr,
+        library.declarations.map((declaration) {
+          return _protocolAvailableSuggestion(declaration);
+        }).toList(),
+      );
+    }).toList(),
+    removedLibraries: change.removed,
+  ).toNotification();
+}
+
+protocol.AvailableSuggestion _protocolAvailableSuggestion(
+    Declaration declaration) {
+  var label = declaration.name;
+  if (declaration.kind == DeclarationKind.ENUM_CONSTANT) {
+    label = '${declaration.name2}.${declaration.name}';
+  }
+
+  return protocol.AvailableSuggestion(
+    label,
+    _protocolElement(declaration),
+    docComplete: declaration.docComplete,
+    docSummary: declaration.docSummary,
+    parameterNames: declaration.parameterNames,
+    parameterTypes: declaration.parameterTypes,
+    requiredParameterCount: declaration.requiredParameterCount,
+    relevanceTags: declaration.relevanceTags,
+  );
+}
+
+protocol.Element _protocolElement(Declaration declaration) {
+  return protocol.Element(
+    _protocolElementKind(declaration.kind),
+    declaration.name,
+    _protocolElementFlags(declaration),
+    location: protocol.Location(
+      declaration.locationPath,
+      declaration.locationOffset,
+      0, // length
+      declaration.locationStartLine,
+      declaration.locationStartColumn,
+    ),
+    parameters: declaration.parameters,
+    returnType: declaration.returnType,
+    typeParameters: declaration.typeParameters,
+  );
+}
+
+int _protocolElementFlags(Declaration declaration) {
+  return protocol.Element.makeFlags(
+    isAbstract: declaration.isAbstract,
+    isConst: declaration.isConst,
+    isFinal: declaration.isFinal,
+    isDeprecated: declaration.isDeprecated,
+  );
+}
+
+protocol.ElementKind _protocolElementKind(DeclarationKind kind) {
+  switch (kind) {
+    case DeclarationKind.CLASS:
+      return protocol.ElementKind.CLASS;
+    case DeclarationKind.CLASS_TYPE_ALIAS:
+      return protocol.ElementKind.CLASS_TYPE_ALIAS;
+    case DeclarationKind.ENUM:
+      return protocol.ElementKind.ENUM;
+    case DeclarationKind.ENUM_CONSTANT:
+      return protocol.ElementKind.ENUM_CONSTANT;
+    case DeclarationKind.FUNCTION:
+      return protocol.ElementKind.FUNCTION;
+    case DeclarationKind.FUNCTION_TYPE_ALIAS:
+      return protocol.ElementKind.FUNCTION_TYPE_ALIAS;
+    case DeclarationKind.GETTER:
+      return protocol.ElementKind.GETTER;
+    case DeclarationKind.MIXIN:
+      return protocol.ElementKind.MIXIN;
+    case DeclarationKind.SETTER:
+      return protocol.ElementKind.SETTER;
+    case DeclarationKind.VARIABLE:
+      return protocol.ElementKind.TOP_LEVEL_VARIABLE;
+  }
+  return protocol.ElementKind.UNKNOWN;
+}
+
+class CompletionLibrariesWorker implements SchedulerWorker {
+  final DeclarationsTracker tracker;
+
+  CompletionLibrariesWorker(this.tracker);
+
+  @override
+  AnalysisDriverPriority get workPriority {
+    if (tracker.hasWork) {
+      return AnalysisDriverPriority.priority;
+    } else {
+      return AnalysisDriverPriority.nothing;
+    }
+  }
+
+  @override
+  Future<void> performWork() async {
+    tracker.doWork();
+  }
+}
diff --git a/pkg/analysis_server/lib/src/domains/execution/completion.dart b/pkg/analysis_server/lib/src/domains/execution/completion.dart
index dbba4ea..594580d 100644
--- a/pkg/analysis_server/lib/src/domains/execution/completion.dart
+++ b/pkg/analysis_server/lib/src/domains/execution/completion.dart
@@ -15,21 +15,19 @@
 import 'package:analysis_server/src/services/completion/completion_performance.dart';
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 
 class RuntimeCompletionComputer {
-  final ResourceProvider resourceProvider;
-  final FileContentOverlay fileContentOverlay;
+  final OverlayResourceProvider resourceProvider;
   final AnalysisDriver analysisDriver;
 
   final String code;
   final int offset;
 
-  final String contextFile;
+  final String contextPath;
   final int contextOffset;
 
   final List<RuntimeCompletionVariable> variables;
@@ -37,11 +35,10 @@
 
   RuntimeCompletionComputer(
       this.resourceProvider,
-      this.fileContentOverlay,
       this.analysisDriver,
       this.code,
       this.offset,
-      this.contextFile,
+      this.contextPath,
       this.contextOffset,
       this.variables,
       this.expressions);
@@ -49,7 +46,7 @@
   Future<RuntimeCompletionResult> compute() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
-    var contextResult = await analysisDriver.getResult(contextFile);
+    var contextResult = await analysisDriver.getResult(contextPath);
     var session = contextResult.session;
 
     const codeMarker = '__code_\_';
@@ -57,7 +54,7 @@
     // Insert the code being completed at the context offset.
     var changeBuilder = new DartChangeBuilder(session);
     int nextImportPrefixIndex = 0;
-    await changeBuilder.addFileEdit(contextFile, (builder) {
+    await changeBuilder.addFileEdit(contextPath, (builder) {
       builder.addInsertion(contextOffset, (builder) {
         builder.writeln('{');
 
@@ -83,15 +80,9 @@
     // Update the context file content to include the code being completed.
     // Then resolve it, and restore the file to its initial state.
     ResolvedUnitResult targetResult;
-    String contentFileOverlay = fileContentOverlay[contextFile];
-    try {
-      fileContentOverlay[contextFile] = targetCode;
-      analysisDriver.changeFile(contextFile);
-      targetResult = await analysisDriver.getResult(contextFile);
-    } finally {
-      fileContentOverlay[contextFile] = contentFileOverlay;
-      analysisDriver.changeFile(contextFile);
-    }
+    await _withContextFileContent(targetCode, () async {
+      targetResult = await analysisDriver.getResult(contextPath);
+    });
 
     CompletionContributor contributor = new DartCompletionManager();
     CompletionRequestImpl request = new CompletionRequestImpl(
@@ -108,6 +99,44 @@
     var expressions = <RuntimeCompletionExpression>[];
     return new RuntimeCompletionResult(expressions, suggestions);
   }
+
+  Future<void> _withContextFileContent(
+      String newContent, Future<void> Function() f) async {
+    if (resourceProvider.hasOverlay(contextPath)) {
+      var contextFile = resourceProvider.getFile(contextPath);
+      var prevOverlayContent = contextFile.readAsStringSync();
+      var prevOverlayStamp = contextFile.modificationStamp;
+      try {
+        resourceProvider.setOverlay(
+          contextPath,
+          content: newContent,
+          modificationStamp: 0,
+        );
+        analysisDriver.changeFile(contextPath);
+        await f();
+      } finally {
+        resourceProvider.setOverlay(
+          contextPath,
+          content: prevOverlayContent,
+          modificationStamp: prevOverlayStamp,
+        );
+        analysisDriver.changeFile(contextPath);
+      }
+    } else {
+      try {
+        resourceProvider.setOverlay(
+          contextPath,
+          content: newContent,
+          modificationStamp: 0,
+        );
+        analysisDriver.changeFile(contextPath);
+        await f();
+      } finally {
+        resourceProvider.removeOverlay(contextPath);
+        analysisDriver.changeFile(contextPath);
+      }
+    }
+  }
 }
 
 /// The result of performing runtime completion.
diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
index c9b2ff1..9b5c226 100644
--- a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart
@@ -2,74 +2,69 @@
 // for details. 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/plugin/edit/fix/fix_core.dart';
 import 'package:analysis_server/protocol/protocol.dart';
 import 'package:analysis_server/protocol/protocol_generated.dart';
 import 'package:analysis_server/src/analysis_server.dart';
-import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
-import 'package:analysis_server/src/edit/fix/prefer_int_literals_fix.dart';
-import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart';
-import 'package:analysis_server/src/services/correction/change_workspace.dart';
-import 'package:analysis_server/src/services/correction/fix.dart';
-import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_info.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
+import 'package:analysis_server/src/edit/fix/fix_error_task.dart';
+import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:analyzer/src/error/codes.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/lint/linter.dart';
-import 'package:analyzer/src/lint/linter_visitor.dart';
-import 'package:analyzer/src/lint/registry.dart';
-import 'package:analyzer/src/services/lint.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart'
-    show Location, SourceChange, SourceEdit, SourceFileEdit;
-import 'package:front_end/src/fasta/fasta_codes.dart';
-import 'package:front_end/src/scanner/token.dart';
-import 'package:source_span/src/span.dart';
 
-class EditDartFix {
+class EditDartFix
+    with FixCodeProcessor, FixErrorProcessor, FixLintProcessor
+    implements DartFixRegistrar {
   final AnalysisServer server;
+
   final Request request;
   final fixFolders = <Folder>[];
   final fixFiles = <File>[];
 
-  List<DartFixSuggestion> suggestions;
-  List<DartFixSuggestion> otherSuggestions;
-  SourceChange sourceChange;
+  DartFixListener listener;
 
-  EditDartFix(this.server, this.request);
-
-  void addSourceChange(
-      String description, Location location, SourceChange change) {
-    suggestions.add(new DartFixSuggestion(description, location: location));
-    for (SourceFileEdit fileEdit in change.edits) {
-      for (SourceEdit sourceEdit in fileEdit.edits) {
-        sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
-      }
-    }
-  }
-
-  void addSourceFileEdit(
-      String description, Location location, SourceFileEdit fileEdit) {
-    suggestions.add(new DartFixSuggestion(description, location: location));
-    for (SourceEdit sourceEdit in fileEdit.edits) {
-      sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
-    }
-  }
-
-  void addRecommendation(String description, [Location location]) {
-    otherSuggestions
-        .add(new DartFixSuggestion(description, location: location));
+  EditDartFix(this.server, this.request) {
+    listener = new DartFixListener(server);
   }
 
   Future<Response> compute() async {
     final params = new EditDartfixParams.fromRequest(request);
 
+    // Determine the fixes to be applied
+    final fixInfo = <DartFixInfo>[];
+    if (params.includeRequiredFixes == true) {
+      fixInfo.addAll(allFixes.where((i) => i.isRequired));
+    }
+    if (params.includedFixes != null) {
+      for (String key in params.includedFixes) {
+        var info = allFixes.firstWhere((i) => i.key == key, orElse: () => null);
+        if (info != null) {
+          fixInfo.add(info);
+        } else {
+          // TODO(danrubel): Report unknown fix to the user
+        }
+      }
+    }
+    if (fixInfo.isEmpty) {
+      fixInfo.addAll(allFixes.where((i) => i.isDefault));
+    }
+    if (params.excludedFixes != null) {
+      for (String key in params.excludedFixes) {
+        var info = allFixes.firstWhere((i) => i.key == key, orElse: () => null);
+        if (info != null) {
+          fixInfo.remove(info);
+        } else {
+          // TODO(danrubel): Report unknown fix to the user
+        }
+      }
+    }
+    for (DartFixInfo info in fixInfo) {
+      info.setup(this, listener);
+    }
+
     // Validate each included file and directory.
     final resourceProvider = server.resourceProvider;
     final contextManager = server.contextManager;
@@ -90,156 +85,52 @@
       }
     }
 
-    // Get the desired lints
-    final lintRules = Registry.ruleRegistry;
-
-    final preferMixin = lintRules['prefer_mixin'];
-    final preferMixinFix = new PreferMixinFix(this);
-    preferMixin.reporter = preferMixinFix;
-
-    final preferIntLiterals = lintRules['prefer_int_literals'];
-    final preferIntLiteralsFix = new PreferIntLiteralsFix(this);
-    final nonNullableFix = new NonNullableFix(this);
-    preferIntLiterals?.reporter = preferIntLiteralsFix;
-
-    // Setup
-    final linters = <Linter>[
-      preferMixin,
-      preferIntLiterals,
-    ];
-    final fixes = <LinterFix>[
-      preferMixinFix,
-      preferIntLiteralsFix,
-    ];
-    final lintVisitorsBySession = <AnalysisSession, _LintVisitors>{};
-
-    // TODO(danrubel): Determine if a lint is configured to run as part of
-    // standard analysis and use those results if available instead of
-    // running the lint again.
-
-    // Analyze each source file.
-    final resources = <Resource>[];
-    for (String rootPath in contextManager.includedPaths) {
-      resources.add(resourceProvider.getResource(rootPath));
-    }
-    suggestions = <DartFixSuggestion>[];
-    otherSuggestions = <DartFixSuggestion>[];
-    sourceChange = new SourceChange('dartfix');
+    // Process each source file.
     bool hasErrors = false;
-    while (resources.isNotEmpty) {
-      Resource res = resources.removeLast();
-      if (res is Folder) {
-        for (Resource child in res.getChildren()) {
-          if (!child.shortName.startsWith('.') &&
-              contextManager.isInAnalysisRoot(child.path) &&
-              !contextManager.isIgnored(child.path)) {
-            resources.add(child);
-          }
+    String changedPath;
+    server.contextManager.driverMap.values
+        .forEach((d) => d.onCurrentSessionAboutToBeDiscarded = (String path) {
+              // Remember the resource that changed during analysis
+              changedPath = path;
+            });
+
+    try {
+      await processResources((ResolvedUnitResult result) async {
+        if (await processErrors(result)) {
+          hasErrors = true;
         }
-        continue;
+        await processLints(result);
+        await processCodeTasks(result);
+      });
+      if (needsSecondPass) {
+        await processResources((ResolvedUnitResult result) async {
+          await processCodeTasks2(result);
+        });
       }
-
-      const maxAttempts = 3;
-      int attempt = 0;
-      while (attempt < maxAttempts) {
-        ResolvedUnitResult result = await server.getResolvedUnit(res.path);
-
-        // TODO(danrubel): Investigate why InconsistentAnalysisException occurs
-        // and whether this is an appropriate way to handle the situation
-        ++attempt;
-        try {
-          CompilationUnit unit = result?.unit;
-          if (unit != null) {
-            if (!hasErrors) {
-              for (AnalysisError error in result.errors) {
-                if (!(await fixError(result, error))) {
-                  if (error.errorCode.type == ErrorType.SYNTACTIC_ERROR) {
-                    hasErrors = true;
-                  }
-                }
-              }
-            }
-            Source source = result.unit.declaredElement.source;
-            for (Linter linter in linters) {
-              if (linter != null) {
-                linter.reporter.source = source;
-              }
-            }
-            var lintVisitors = lintVisitorsBySession[result.session] ??=
-                await _setupLintVisitors(result, linters);
-            if (lintVisitors.astVisitor != null) {
-              unit.accept(lintVisitors.astVisitor);
-            }
-            unit.accept(lintVisitors.linterVisitor);
-            for (LinterFix fix in fixes) {
-              await fix.applyLocalFixes(result);
-            }
-            if (isIncluded(source.fullName)) {
-              nonNullableFix.applyLocalFixes(result);
-            }
-          }
-          break;
-        } on InconsistentAnalysisException catch (_) {
-          if (attempt == maxAttempts) {
-            // TODO(danrubel): Consider improving the edit.dartfix protocol
-            // to gracefully report inconsistent results for a particular
-            // file rather than aborting the entire operation.
-            rethrow;
-          }
-          // try again
-        }
-      }
-    }
-
-    // Cleanup
-    for (Linter linter in linters) {
-      if (linter != null) {
-        linter.reporter.source = null;
-        linter.reporter = null;
-      }
-    }
-
-    // Apply distributed fixes
-    if (preferIntLiterals == null) {
-      // TODO(danrubel): Remove this once linter rolled into sdk/third_party.
-      addRecommendation('*** Convert double literal not available'
-          ' because prefer_int_literal not found. May need to roll linter');
-    }
-    for (LinterFix fix in fixes) {
-      await fix.applyRemainingFixes();
+      await finishLints();
+      await finishCodeTasks();
+    } on InconsistentAnalysisException catch (_) {
+      // If a resource changed, report the problem without suggesting fixes
+      var changedMessage = changedPath != null
+          ? 'resource changed during analysis: $changedPath'
+          : 'multiple resources changed during analysis.';
+      return new EditDartfixResult(
+        [new DartFixSuggestion('Analysis canceled because $changedMessage')],
+        listener.otherSuggestions,
+        hasErrors,
+        listener.sourceChange.edits,
+      ).toResponse(request.id);
+    } finally {
+      server.contextManager.driverMap.values
+          .forEach((d) => d.onCurrentSessionAboutToBeDiscarded = null);
     }
 
     return new EditDartfixResult(
-            suggestions, otherSuggestions, hasErrors, sourceChange.edits)
-        .toResponse(request.id);
-  }
-
-  Future<bool> fixError(ResolvedUnitResult result, AnalysisError error) async {
-    if (error.errorCode ==
-        StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR) {
-      // TODO(danrubel): Rather than comparing the error codes individually,
-      // it would be better if each error code could specify
-      // whether or not it could be fixed automatically.
-
-      // Fall through to calculate and apply the fix
-    } else {
-      // This error cannot be automatically fixed
-      return false;
-    }
-
-    final workspace = DartChangeWorkspace(server.currentSessions);
-    final dartContext = new DartFixContextImpl(workspace, result, error);
-    final processor = new FixProcessor(dartContext);
-    Fix fix = await processor.computeFix();
-    final location = locationFor(result, error.offset, error.length);
-    if (fix != null) {
-      addSourceChange(fix.change.message, location, fix.change);
-    } else {
-      // TODO(danrubel): Determine why the fix could not be applied
-      // and report that in the description.
-      addRecommendation('Could not fix "${error.message}"', location);
-    }
-    return true;
+      listener.suggestions,
+      listener.otherSuggestions,
+      hasErrors,
+      listener.sourceChange.edits,
+    ).toResponse(request.id);
   }
 
   /// Return `true` if the path in within the set of `included` files
@@ -260,122 +151,35 @@
     return false;
   }
 
-  Location locationFor(ResolvedUnitResult result, int offset, int length) {
-    final locInfo = result.unit.lineInfo.getLocation(offset);
-    final location = new Location(
-        result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber);
-    return location;
-  }
-
-  Future<_LintVisitors> _setupLintVisitors(
-      ResolvedUnitResult result, List<Linter> linters) async {
-    final visitors = <AstVisitor>[];
-    final registry = new NodeLintRegistry(false);
-    // TODO(paulberry): use an API that provides this information more readily
-    var unitElement = result.unit.declaredElement;
-    var session = result.session;
-    var currentUnit = LinterContextUnit(result.content, result.unit);
-    var allUnits = <LinterContextUnit>[];
-    for (var cu in unitElement.library.units) {
-      if (identical(cu, unitElement)) {
-        allUnits.add(currentUnit);
-      } else {
-        Source source = cu.source;
-        if (source != null) {
-          var result = await session.getResolvedUnit(source.fullName);
-          allUnits.add(LinterContextUnit(result.content, result.unit));
-        }
-      }
+  /// Call the supplied [process] function to process each compilation unit.
+  Future processResources(
+      Future<void> Function(ResolvedUnitResult result) process) async {
+    final contextManager = server.contextManager;
+    final resourceProvider = server.resourceProvider;
+    final resources = <Resource>[];
+    for (String rootPath in contextManager.includedPaths) {
+      resources.add(resourceProvider.getResource(rootPath));
     }
-    var context = LinterContextImpl(allUnits, currentUnit,
-        session.declaredVariables, result.typeProvider, result.typeSystem);
-    for (Linter linter in linters) {
-      if (linter != null) {
-        final visitor = linter.getVisitor();
-        if (visitor != null) {
-          visitors.add(visitor);
+    while (resources.isNotEmpty) {
+      Resource res = resources.removeLast();
+      if (res is Folder) {
+        for (Resource child in res.getChildren()) {
+          if (!child.shortName.startsWith('.') &&
+              contextManager.isInAnalysisRoot(child.path) &&
+              !contextManager.isIgnored(child.path)) {
+            resources.add(child);
+          }
         }
-        if (linter is NodeLintRule) {
-          (linter as NodeLintRule).registerNodeProcessors(registry, context);
-        }
+        continue;
       }
+      if (!isIncluded(res.path)) {
+        continue;
+      }
+      ResolvedUnitResult result = await server.getResolvedUnit(res.path);
+      if (result == null || result.unit == null) {
+        continue;
+      }
+      await process(result);
     }
-    final AstVisitor astVisitor = visitors.isNotEmpty
-        ? new ExceptionHandlingDelegatingAstVisitor(
-            visitors, ExceptionHandlingDelegatingAstVisitor.logException)
-        : null;
-    final AstVisitor linterVisitor = new LinterVisitor(
-        registry, ExceptionHandlingDelegatingAstVisitor.logException);
-    return _LintVisitors(astVisitor, linterVisitor);
   }
 }
-
-abstract class LinterFix implements ErrorReporter {
-  final EditDartFix dartFix;
-
-  @override
-  Source source;
-
-  LinterFix(this.dartFix);
-
-  /// Apply fixes for the current compilation unit.
-  Future<void> applyLocalFixes(ResolvedUnitResult result);
-
-  /// Apply any fixes remaining after analysis is complete.
-  Future<void> applyRemainingFixes();
-
-  @override
-  void reportError(AnalysisError error) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForElement(ErrorCode errorCode, Element element,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForNode(ErrorCode errorCode, AstNode node,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorForToken(ErrorCode errorCode, Token token,
-      [List<Object> arguments]) {
-    // ignored
-  }
-
-  @override
-  void reportErrorMessage(
-      ErrorCode errorCode, int offset, int length, Message message) {
-    // ignored
-  }
-
-  @override
-  void reportTypeErrorForNode(
-      ErrorCode errorCode, AstNode node, List<Object> arguments) {
-    // ignored
-  }
-}
-
-class _LintVisitors {
-  final AstVisitor astVisitor;
-
-  final AstVisitor linterVisitor;
-
-  _LintVisitors(this.astVisitor, this.linterVisitor);
-}
diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart
index f692c76..efccaeb 100644
--- a/pkg/analysis_server/lib/src/edit/edit_domain.dart
+++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart
@@ -11,7 +11,8 @@
 import 'package:analysis_server/src/collections.dart';
 import 'package:analysis_server/src/computer/import_elements_computer.dart';
 import 'package:analysis_server/src/domain_abstract.dart';
-import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/edit_dartfix.dart' show EditDartFix;
+import 'package:analysis_server/src/edit/fix/dartfix_info.dart' show allFixes;
 import 'package:analysis_server/src/plugin/plugin_manager.dart';
 import 'package:analysis_server/src/plugin/result_converter.dart';
 import 'package:analysis_server/src/protocol_server.dart' hide Element;
@@ -226,6 +227,10 @@
         .sendResponse(new EditGetAssistsResult(changes).toResponse(request.id));
   }
 
+  Response getDartfixInfo(Request request) =>
+      new EditGetDartfixInfoResult(allFixes.map((i) => i.asDartFix()).toList())
+          .toResponse(request.id);
+
   Future getFixes(Request request) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -356,6 +361,8 @@
         return Response.DELAYED_RESPONSE;
       } else if (requestName == EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS) {
         return _getAvailableRefactorings(request);
+      } else if (requestName == EDIT_REQUEST_GET_DARTFIX_INFO) {
+        return getDartfixInfo(request);
       } else if (requestName == EDIT_REQUEST_GET_FIXES) {
         getFixes(request);
         return Response.DELAYED_RESPONSE;
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.dart
new file mode 100644
index 0000000..3e6c9c8
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_info.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:analysis_server/protocol/protocol_generated.dart' show DartFix;
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/edit/fix/fix_error_task.dart';
+import 'package:analysis_server/src/edit/fix/non_nullable_fix.dart';
+import 'package:analysis_server/src/edit/fix/prefer_int_literals_fix.dart';
+import 'package:analysis_server/src/edit/fix/prefer_mixin_fix.dart';
+
+const allFixes = <DartFixInfo>[
+  //
+  // Required fixes
+  //
+  const DartFixInfo(
+    'fix-named-constructor-type-arguments',
+    'Move named constructor type arguments from the name to the type.',
+    FixErrorTask.fixNamedConstructorTypeArgs,
+    isRequired: true,
+  ),
+  const DartFixInfo(
+    'use-mixin',
+    'Convert classes used as a mixin to the new mixin syntax.',
+    PreferMixinFix.task,
+    isRequired: true,
+  ),
+  //
+  // Suggested fixes
+  //
+  const DartFixInfo(
+    'double-to-int',
+    'Find double literals ending in .0 and remove the .0\n'
+        'wherever double context can be inferred.',
+    PreferIntLiteralsFix.task,
+  ),
+  //
+  // Expermimental fixes
+  //
+  const DartFixInfo(
+    'non-nullable',
+    // TODO(danrubel) update description and make default/required
+    // when NNBD fix is ready
+    'Experimental: Update sources to be non-nullable by default.\n'
+        'Requires the experimental non-nullable flag to be enabled.\n'
+        'This is not applied unless explicitly included.',
+    NonNullableFix.task,
+    isDefault: false,
+  ),
+];
+
+/// [DartFixInfo] represents a fix that can be applied by [EditDartFix].
+class DartFixInfo {
+  final String key;
+  final String description;
+  final bool isDefault;
+  final bool isRequired;
+  final void Function(DartFixRegistrar dartfix, DartFixListener listener) setup;
+
+  const DartFixInfo(this.key, this.description, this.setup,
+      {this.isDefault = true, this.isRequired = false});
+
+  DartFix asDartFix() =>
+      new DartFix(key, description: description, isRequired: isRequired);
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
new file mode 100644
index 0000000..73805d4
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_listener.dart
@@ -0,0 +1,65 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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:analysis_server/src/analysis_server.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart'
+    show Location, SourceChange, SourceEdit, SourceFileEdit;
+
+/// Tasks use this API to report results.
+class DartFixListener {
+  final AnalysisServer server;
+
+  final List<DartFixSuggestion> suggestions = <DartFixSuggestion>[];
+  final List<DartFixSuggestion> otherSuggestions = <DartFixSuggestion>[];
+  final SourceChange sourceChange = new SourceChange('dartfix');
+
+  DartFixListener(this.server);
+
+  /// Record a source change to be sent to the client.
+  void addSourceChange(
+      String description, Location location, SourceChange change) {
+    suggestions.add(new DartFixSuggestion(description, location: location));
+    for (SourceFileEdit fileEdit in change.edits) {
+      for (SourceEdit sourceEdit in fileEdit.edits) {
+        sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
+      }
+    }
+  }
+
+  /// Record edits for a single source to be sent to the client.
+  void addSourceEdits(String description, Location location, Source source,
+      Iterable<SourceEdit> edits) {
+    suggestions.add(new DartFixSuggestion(description, location: location));
+    for (SourceEdit edit in edits) {
+      sourceChange.addEdit(source.fullName, -1, edit);
+    }
+  }
+
+  /// Record a source change to be sent to the client.
+  void addSourceFileEdit(
+      String description, Location location, SourceFileEdit fileEdit) {
+    suggestions.add(new DartFixSuggestion(description, location: location));
+    for (SourceEdit sourceEdit in fileEdit.edits) {
+      sourceChange.addEdit(fileEdit.file, fileEdit.fileStamp, sourceEdit);
+    }
+  }
+
+  /// Record a recommendation to be sent to the client.
+  void addRecommendation(String description, [Location location]) {
+    otherSuggestions
+        .add(new DartFixSuggestion(description, location: location));
+  }
+
+  /// Return the [Location] representing the specified offset and length
+  /// in the given compilation unit.
+  Location locationFor(ResolvedUnitResult result, int offset, int length) {
+    final locInfo = result.unit.lineInfo.getLocation(offset);
+    final location = new Location(
+        result.path, offset, length, locInfo.lineNumber, locInfo.columnNumber);
+    return location;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/dartfix_registrar.dart b/pkg/analysis_server/lib/src/edit/fix/dartfix_registrar.dart
new file mode 100644
index 0000000..07652c0
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/dartfix_registrar.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.
+
+import 'package:analysis_server/src/edit/fix/dartfix_info.dart';
+import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
+import 'package:analysis_server/src/edit/fix/fix_error_task.dart';
+import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/lint/linter.dart';
+
+/// Fixes use this API to register tasks. See [DartFixInfo.setup].
+abstract class DartFixRegistrar {
+  /// Register the specified task to analyze and fix problems.
+  void registerCodeTask(FixCodeTask task);
+
+  /// Register the specified task to fix the given error condition.
+  void registerErrorTask(ErrorCode errorCode, FixErrorTask task);
+
+  /// Register the specified task to fix the given lint.
+  void registerLintTask(LintRule ruleRegistry, FixLintTask task);
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
new file mode 100644
index 0000000..71d491b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_code_task.dart
@@ -0,0 +1,56 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+
+/// A general task for performing a fix.
+abstract class FixCodeTask {
+  /// [processUnit] is called for each compilation unit.
+  Future<void> processUnit(ResolvedUnitResult result);
+
+  /// [finish] is called after [processUnit] (and [processUnit2] if this
+  /// is a FixCodeTask2) has been called for each compilation unit.
+  Future<void> finish();
+}
+
+/// A general task for performing a fix which needs a 2nd pass.
+abstract class FixCodeTask2 extends FixCodeTask {
+  /// [processUnit2] is called for each compilation unit
+  /// after [processUnit] has been called for each compilation unit.
+  Future<void> processUnit2(ResolvedUnitResult result);
+}
+
+/// A processor used by [EditDartFix] to manage [FixCodeTask]s.
+mixin FixCodeProcessor {
+  final codeTasks = <FixCodeTask>[];
+  final codeTasks2 = <FixCodeTask2>[];
+
+  Future<void> finishCodeTasks() async {
+    for (FixCodeTask task in codeTasks) {
+      await task.finish();
+    }
+  }
+
+  bool get needsSecondPass => codeTasks2.isNotEmpty;
+
+  Future<void> processCodeTasks(ResolvedUnitResult result) async {
+    for (FixCodeTask task in codeTasks) {
+      await task.processUnit(result);
+    }
+  }
+
+  Future<void> processCodeTasks2(ResolvedUnitResult result) async {
+    for (FixCodeTask2 task in codeTasks) {
+      await task.processUnit2(result);
+    }
+  }
+
+  void registerCodeTask(FixCodeTask task) {
+    codeTasks.add(task);
+    if (task is FixCodeTask2) {
+      codeTasks2.add(task);
+    }
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.dart
new file mode 100644
index 0000000..e71fd1d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_error_task.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:analysis_server/plugin/edit/fix/fix_core.dart';
+import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/services/correction/change_workspace.dart';
+import 'package:analysis_server/src/services/correction/fix.dart';
+import 'package:analysis_server/src/services/correction/fix_internal.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/error/codes.dart';
+
+/// A task for fixing a particular error
+class FixErrorTask {
+  static void fixNamedConstructorTypeArgs(
+      DartFixRegistrar registrar, DartFixListener listener) {
+    registrar.registerErrorTask(
+        StaticTypeWarningCode.WRONG_NUMBER_OF_TYPE_ARGUMENTS_CONSTRUCTOR,
+        new FixErrorTask(listener));
+  }
+
+  final DartFixListener listener;
+
+  FixErrorTask(this.listener);
+
+  Future<void> fixError(ResolvedUnitResult result, AnalysisError error) async {
+    final workspace = DartChangeWorkspace(listener.server.currentSessions);
+    final dartContext = new DartFixContextImpl(workspace, result, error);
+    final processor = new FixProcessor(dartContext);
+    Fix fix = await processor.computeFix();
+    final location = listener.locationFor(result, error.offset, error.length);
+    if (fix != null) {
+      listener.addSourceChange(fix.change.message, location, fix.change);
+    } else {
+      // TODO(danrubel): Determine why the fix could not be applied
+      // and report that in the description.
+      listener.addRecommendation('Could not fix "${error.message}"', location);
+    }
+  }
+}
+
+/// A processor used by [EditDartFix] to manage [FixErrorTask]s.
+mixin FixErrorProcessor {
+  /// A mapping from [ErrorCode] to the fix that should be applied.
+  final errorTaskMap = <ErrorCode, FixErrorTask>{};
+
+  Future<bool> processErrors(ResolvedUnitResult result) async {
+    bool foundError = false;
+    for (AnalysisError error in result.errors) {
+      final task = errorTaskMap[error.errorCode];
+      if (task != null) {
+        await task.fixError(result, error);
+      } else if (error.errorCode.type == ErrorType.SYNTACTIC_ERROR) {
+        foundError = true;
+      }
+    }
+    return foundError;
+  }
+
+  Future<bool> fixError(ResolvedUnitResult result, AnalysisError error) async {
+    return true;
+  }
+
+  void registerErrorTask(ErrorCode errorCode, FixErrorTask task) {
+    errorTaskMap[errorCode] = task;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart b/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart
new file mode 100644
index 0000000..0885046
--- /dev/null
+++ b/pkg/analysis_server/lib/src/edit/fix/fix_lint_task.dart
@@ -0,0 +1,170 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.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/error/error.dart';
+import 'package:analyzer/error/listener.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:analyzer/src/lint/linter_visitor.dart';
+import 'package:analyzer/src/services/lint.dart';
+import 'package:front_end/src/fasta/fasta_codes.dart';
+import 'package:front_end/src/scanner/token.dart';
+import 'package:source_span/src/span.dart';
+
+/// A task for fixing a particular lint.
+/// Subclasses should implement [applyLocalFixes] and [applyRemainingFixes]
+/// and may override any of the reportSomething() methods as needed.
+abstract class FixLintTask implements ErrorReporter {
+  final DartFixListener listener;
+
+  @override
+  Source source;
+
+  FixLintTask(this.listener);
+
+  /// Apply fixes for the current compilation unit.
+  Future<void> applyLocalFixes(ResolvedUnitResult result);
+
+  /// Apply any fixes remaining after all local changes have been applied.
+  Future<void> applyRemainingFixes();
+
+  @override
+  void reportError(AnalysisError error) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForElement(ErrorCode errorCode, Element element,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForNode(ErrorCode errorCode, AstNode node,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForOffset(ErrorCode errorCode, int offset, int length,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForSpan(ErrorCode errorCode, SourceSpan span,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorForToken(ErrorCode errorCode, Token token,
+      [List<Object> arguments]) {
+    // ignored
+  }
+
+  @override
+  void reportErrorMessage(
+      ErrorCode errorCode, int offset, int length, Message message) {
+    // ignored
+  }
+
+  @override
+  void reportTypeErrorForNode(
+      ErrorCode errorCode, AstNode node, List<Object> arguments) {
+    // ignored
+  }
+}
+
+/// A processor used by [EditDartFix] to manage [FixLintTask]s.
+mixin FixLintProcessor {
+  final linters = <Linter>[];
+  final lintTasks = <FixLintTask>[];
+
+  Future<void> finishLints() async {
+    for (Linter linter in linters) {
+      linter.reporter = null;
+    }
+    for (FixLintTask fix in lintTasks) {
+      fix.source = null;
+      await fix.applyRemainingFixes();
+    }
+  }
+
+  Future<void> processLints(ResolvedUnitResult result) async {
+    // TODO(danrubel): Determine if a lint is configured to run as part of
+    // standard analysis and use those results if available instead of
+    // running the lint again.
+
+    Source source = result.unit.declaredElement.source;
+    for (Linter linter in linters) {
+      if (linter != null) {
+        linter.reporter.source = source;
+      }
+    }
+
+    // TODO(paulberry): use an API that provides this information more readily
+
+    var unitElement = result.unit.declaredElement;
+    var session = result.session;
+    var currentUnit = LinterContextUnit(result.content, result.unit);
+    var allUnits = <LinterContextUnit>[];
+    for (var cu in unitElement.library.units) {
+      if (identical(cu, unitElement)) {
+        allUnits.add(currentUnit);
+      } else {
+        Source source = cu.source;
+        if (source != null) {
+          var result = await session.getResolvedUnit(source.fullName);
+          allUnits.add(LinterContextUnit(result.content, result.unit));
+        }
+      }
+    }
+
+    final visitors = <AstVisitor>[];
+    final registry = new NodeLintRegistry(false);
+    var context = LinterContextImpl(
+        allUnits,
+        currentUnit,
+        session.declaredVariables,
+        result.typeProvider,
+        result.typeSystem,
+        result.session.analysisContext.analysisOptions);
+    for (Linter linter in linters) {
+      if (linter != null) {
+        final visitor = linter.getVisitor();
+        if (visitor != null) {
+          visitors.add(visitor);
+        }
+        if (linter is NodeLintRule) {
+          (linter as NodeLintRule).registerNodeProcessors(registry, context);
+        }
+      }
+    }
+
+    CompilationUnit unit = result.unit;
+    if (visitors.isNotEmpty) {
+      unit.accept(new ExceptionHandlingDelegatingAstVisitor(
+          visitors, ExceptionHandlingDelegatingAstVisitor.logException));
+    }
+    unit.accept(new LinterVisitor(
+        registry, ExceptionHandlingDelegatingAstVisitor.logException));
+
+    for (FixLintTask fix in lintTasks) {
+      await fix.applyLocalFixes(result);
+    }
+  }
+
+  void registerLintTask(LintRule lint, FixLintTask task) {
+    linters.add(lint);
+    lintTasks.add(task);
+    lint.reporter = task;
+  }
+}
diff --git a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
index fc623af..c80cf39 100644
--- a/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/non_nullable_fix.dart
@@ -2,118 +2,58 @@
 // for details. 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/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/edit/fix/fix_code_task.dart';
+import 'package:analysis_server/src/nullability/provisional_api.dart';
 import 'package:analyzer/dart/analysis/results.dart';
-import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/visitor.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer_plugin/protocol/protocol_common.dart';
 
 /// [NonNullableFix] visits each named type in a resolved compilation unit
 /// and determines whether the associated variable or parameter can be null
 /// then adds or removes a '?' trailing the named type as appropriate.
-class NonNullableFix {
-  final EditDartFix dartFix;
+class NonNullableFix extends FixCodeTask2 {
+  /// TODO(paulberry): stop using permissive mode once the migration logic is
+  /// mature enough.
+  static const bool _usePermissiveMode = true;
 
-  /// The current source being "fixed"
-  Source source;
-
-  /// The source file change or `null` if none
-  SourceFileEdit fileEdit;
-
-  int firstOffset;
-  int firstLength;
-
-  NonNullableFix(this.dartFix);
-
-  void addEdit(int offset, int length, String replacementText) {
-    fileEdit ??= new SourceFileEdit(source.fullName, 0);
-    fileEdit.edits.add(new SourceEdit(offset, length, replacementText));
+  static void task(DartFixRegistrar registrar, DartFixListener listener) {
+    registrar.registerCodeTask(new NonNullableFix(listener));
   }
 
-  /// Update the source to be non-nullable by
-  /// 1) adding trailing '?' to type references of nullable variables, and
-  /// 2) removing trailing '?' from type references of non-nullable variables.
-  void applyLocalFixes(ResolvedUnitResult result) {
-    final context = result.session.analysisContext;
-    AnalysisOptionsImpl options = context.analysisOptions;
-    if (!options.experimentStatus.non_nullable) {
-      return;
-    }
+  final DartFixListener listener;
 
-    final unit = result.unit;
-    source = unit.declaredElement.source;
+  final NullabilityMigration migration;
 
-    // find and fix types
-    unit.accept(new _NonNullableTypeVisitor(this));
+  NonNullableFix(this.listener)
+      : migration = new NullabilityMigration(
+            new NullabilityMigrationAdapter(listener),
+            permissive: _usePermissiveMode);
 
-    // add source changes to the collection of fixes
-    source = null;
-    if (fileEdit != null) {
-      dartFix.addSourceFileEdit('Update non-nullable type references',
-          dartFix.locationFor(result, firstOffset, firstLength), fileEdit);
-    }
+  @override
+  Future<void> finish() async {
+    migration.finish();
+  }
+
+  @override
+  Future<void> processUnit(ResolvedUnitResult result) async {
+    migration.prepareInput(result);
+  }
+
+  @override
+  Future<void> processUnit2(ResolvedUnitResult result) async {
+    migration.processInput(result);
   }
 }
 
-class _NonNullableTypeVisitor extends RecursiveAstVisitor<void> {
-  final NonNullableFix fix;
+class NullabilityMigrationAdapter implements NullabilityMigrationListener {
+  final DartFixListener listener;
 
-  _NonNullableTypeVisitor(this.fix);
+  NullabilityMigrationAdapter(this.listener);
 
   @override
-  void visitConstructorName(ConstructorName node) {
-    // skip the type name associated with the constructor
-    node.type?.typeArguments?.accept(this);
-  }
-
-  @override
-  void visitExtendsClause(ExtendsClause node) {
-    // skip the type name associated with the extends clause
-    node.superclass?.typeArguments?.accept(this);
-  }
-
-  @override
-  void visitImplementsClause(ImplementsClause node) {
-    // skip the type names in the implements clause
-    for (TypeName typeName in node.interfaces) {
-      typeName.typeArguments?.accept(this);
-    }
-  }
-
-  @override
-  void visitOnClause(OnClause node) {
-    // skip the type name in the clause
-    for (TypeName typeName in node.superclassConstraints) {
-      typeName.typeArguments?.accept(this);
-    }
-  }
-
-  @override
-  void visitTypeName(TypeName node) {
-    // TODO(danrubel): Replace this braindead implementation
-    // with something that determines whether or not the type should be nullable
-    // and adds or removes the trailing `?` to match.
-    if (node.question == null) {
-      final identifier = node.name;
-      if (identifier is SimpleIdentifier) {
-        if (identifier.name == 'void') {
-          return;
-        }
-      }
-      fix.addEdit(node.end, 0, '?');
-      fix.firstOffset ??= node.offset;
-      fix.firstLength ??= node.length;
-    }
-    super.visitTypeName(node);
-  }
-
-  @override
-  void visitWithClause(WithClause node) {
-    // skip the type names associated with this clause
-    for (TypeName typeName in node.mixinTypes) {
-      typeName.typeArguments?.accept(this);
-    }
+  void addFix(SingleNullabilityFix fix) {
+    // TODO(danrubel): Update the description based upon the [fix.kind]
+    listener.addSourceEdits(
+        fix.kind.appliedMessage, fix.location, fix.source, fix.sourceEdits);
   }
 }
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
index 871eb2b..e483d05 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_int_literals_fix.dart
@@ -3,18 +3,28 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/lint/registry.dart';
 
-class PreferIntLiteralsFix extends LinterFix {
+class PreferIntLiteralsFix extends FixLintTask {
+  static void task(DartFixRegistrar registrar, DartFixListener listener) {
+    registrar.registerLintTask(
+      Registry.ruleRegistry['prefer_int_literals'],
+      new PreferIntLiteralsFix(listener),
+    );
+  }
+
   final literalsToConvert = <DoubleLiteral>[];
 
-  PreferIntLiteralsFix(EditDartFix dartFix) : super(dartFix);
+  PreferIntLiteralsFix(DartFixListener listener) : super(listener);
 
   @override
   Future<void> applyLocalFixes(ResolvedUnitResult result) async {
@@ -22,7 +32,7 @@
       DoubleLiteral literal = literalsToConvert.removeLast();
       AssistProcessor processor = new AssistProcessor(
         new DartAssistContextImpl(
-          DartChangeWorkspace(dartFix.server.currentSessions),
+          DartChangeWorkspace(listener.server.currentSessions),
           result,
           literal.offset,
           0,
@@ -31,10 +41,10 @@
       List<Assist> assists =
           await processor.computeAssist(DartAssistKind.CONVERT_TO_INT_LITERAL);
       final location =
-          dartFix.locationFor(result, literal.offset, literal.length);
+          listener.locationFor(result, literal.offset, literal.length);
       if (assists.isNotEmpty) {
         for (Assist assist in assists) {
-          dartFix.addSourceChange(
+          listener.addSourceChange(
               'Replace a double literal with an int literal',
               location,
               assist.change);
@@ -42,7 +52,7 @@
       } else {
         // TODO(danrubel): If assists is empty, then determine why
         // assist could not be performed and report that in the description.
-        dartFix.addRecommendation(
+        listener.addRecommendation(
             'Could not replace a double literal with an int literal', location);
       }
     }
@@ -57,8 +67,7 @@
   @override
   void reportErrorForNode(ErrorCode errorCode, AstNode node,
       [List<Object> arguments]) {
-    String filePath = source.fullName;
-    if (filePath != null && dartFix.isIncluded(filePath)) {
+    if (source.fullName != null) {
       literalsToConvert.add(node);
     }
   }
diff --git a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
index 2972f49..2fec097 100644
--- a/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
+++ b/pkg/analysis_server/lib/src/edit/fix/prefer_mixin_fix.dart
@@ -3,7 +3,9 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analysis_server/plugin/edit/assist/assist_core.dart';
-import 'package:analysis_server/src/edit/edit_dartfix.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_listener.dart';
+import 'package:analysis_server/src/edit/fix/dartfix_registrar.dart';
+import 'package:analysis_server/src/edit/fix/fix_lint_task.dart';
 import 'package:analysis_server/src/services/correction/assist.dart';
 import 'package:analysis_server/src/services/correction/assist_internal.dart';
 import 'package:analysis_server/src/services/correction/change_workspace.dart';
@@ -11,11 +13,19 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/lint/registry.dart';
 
-class PreferMixinFix extends LinterFix {
+class PreferMixinFix extends FixLintTask {
+  static void task(DartFixRegistrar registrar, DartFixListener listener) {
+    registrar.registerLintTask(
+      Registry.ruleRegistry['prefer_mixin'],
+      new PreferMixinFix(listener),
+    );
+  }
+
   final classesToConvert = new Set<Element>();
 
-  PreferMixinFix(EditDartFix dartFix) : super(dartFix);
+  PreferMixinFix(DartFixListener listener) : super(listener);
 
   @override
   Future<void> applyLocalFixes(ResolvedUnitResult result) {
@@ -32,14 +42,14 @@
 
   Future<void> convertClassToMixin(Element elem) async {
     ResolvedUnitResult result =
-        await dartFix.server.getResolvedUnit(elem.source?.fullName);
+        await listener.server.getResolvedUnit(elem.source?.fullName);
 
     for (CompilationUnitMember declaration in result.unit.declarations) {
       if (declaration is ClassOrMixinDeclaration &&
           declaration.name.name == elem.name) {
         AssistProcessor processor = new AssistProcessor(
           new DartAssistContextImpl(
-              DartChangeWorkspace(dartFix.server.currentSessions),
+              DartChangeWorkspace(listener.server.currentSessions),
               result,
               declaration.name.offset,
               0),
@@ -47,16 +57,16 @@
         List<Assist> assists = await processor
             .computeAssist(DartAssistKind.CONVERT_CLASS_TO_MIXIN);
         final location =
-            dartFix.locationFor(result, elem.nameOffset, elem.nameLength);
+            listener.locationFor(result, elem.nameOffset, elem.nameLength);
         if (assists.isNotEmpty) {
           for (Assist assist in assists) {
-            dartFix.addSourceChange('Convert ${elem.displayName} to a mixin',
+            listener.addSourceChange('Convert ${elem.displayName} to a mixin',
                 location, assist.change);
           }
         } else {
           // TODO(danrubel): If assists is empty, then determine why
           // assist could not be performed and report that in the description.
-          dartFix.addRecommendation(
+          listener.addRecommendation(
               'Could not convert ${elem.displayName} to a mixin'
               ' because the class contains a constructor',
               location);
@@ -70,8 +80,7 @@
       [List<Object> arguments]) {
     TypeName type = node;
     Element element = type.name.staticElement;
-    String filePath = element.source?.fullName;
-    if (filePath != null && dartFix.isIncluded(filePath)) {
+    if (element.source?.fullName != null) {
       classesToConvert.add(element);
     }
   }
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
index 67ab08f..a67c282 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_initialize.dart
@@ -29,11 +29,11 @@
     }
     if (params.rootUri != null) {
       openWorkspacePaths.add(Uri.parse(params.rootUri).toFilePath());
-      // ignore: deprecated_member_use
+      // ignore: deprecated_member_use_from_same_package
     } else if (params.rootPath != null) {
       // This is deprecated according to LSP spec, but we still want to support
       // it in case older clients send us it.
-      // ignore: deprecated_member_use
+      // ignore: deprecated_member_use_from_same_package
       openWorkspacePaths.add(params.rootPath);
     }
 
@@ -92,7 +92,7 @@
         true, // referencesProvider
         true, // documentHighlightProvider
         true, // documentSymbolProvider
-        null,
+        true, // workspaceSymbolProvider
         // "The `CodeActionOptions` return type is only valid if the client
         // signals code action literal support via the property
         // `textDocument.codeAction.codeActionLiteralSupport`."
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
index 36eb607..7594631 100644
--- a/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_states.dart
@@ -25,6 +25,7 @@
 import 'package:analysis_server/src/lsp/handlers/handler_signature_help.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_text_document_changes.dart';
 import 'package:analysis_server/src/lsp/handlers/handler_change_workspace_folders.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_workspace_symbols.dart';
 import 'package:analysis_server/src/lsp/handlers/handlers.dart';
 import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
 
@@ -68,6 +69,7 @@
     registerHandler(new RenameHandler(server));
     registerHandler(new FoldingHandler(server));
     registerHandler(new DiagnosticServerHandler(server));
+    registerHandler(new WorkspaceSymbolHandler(server));
   }
 }
 
diff --git a/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
new file mode 100644
index 0000000..3d41c0e
--- /dev/null
+++ b/pkg/analysis_server/lib/src/lsp/handlers/handler_workspace_symbols.dart
@@ -0,0 +1,106 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+import 'dart:collection';
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:analysis_server/lsp_protocol/protocol_special.dart';
+import 'package:analysis_server/src/lsp/handlers/handler_document_symbols.dart'
+    show defaultSupportedSymbolKinds;
+import 'package:analysis_server/src/lsp/handlers/handlers.dart';
+import 'package:analysis_server/src/lsp/lsp_analysis_server.dart';
+import 'package:analysis_server/src/lsp/mapping.dart';
+import 'package:analyzer/src/dart/analysis/search.dart' as search;
+
+class WorkspaceSymbolHandler
+    extends MessageHandler<WorkspaceSymbolParams, List<SymbolInformation>> {
+  WorkspaceSymbolHandler(LspAnalysisServer server) : super(server);
+  Method get handlesMessage => Method.workspace_symbol;
+
+  @override
+  WorkspaceSymbolParams convertParams(Map<String, dynamic> json) =>
+      WorkspaceSymbolParams.fromJson(json);
+
+  Future<ErrorOr<List<SymbolInformation>>> handle(
+      WorkspaceSymbolParams params) async {
+    // Respond to empty queries with an empty list. The spec says this should
+    // be non-empty, however VS Code's client sends empty requests (but then
+    // appears to not render the results we supply anyway).
+    final query = params?.query ?? '';
+    if (query == '') {
+      return success([]);
+    }
+
+    final symbolCapabilities = server?.clientCapabilities?.workspace?.symbol;
+
+    final clientSupportedSymbolKinds =
+        symbolCapabilities?.symbolKind?.valueSet != null
+            ? new HashSet<SymbolKind>.of(symbolCapabilities.symbolKind.valueSet)
+            : defaultSupportedSymbolKinds;
+
+    // Convert the string input into a case-insensitive regex that has wildcards
+    // between every character and at start/end to allow for fuzzy matching.
+    final fuzzyQuery = query.split('').map(RegExp.escape).join('.*');
+    final partialFuzzyQuery = '.*$fuzzyQuery.*';
+    final regex = new RegExp(partialFuzzyQuery, caseSensitive: false);
+
+    // Cap the number of results we'll return because short queries may match
+    // huge numbers on large projects.
+    var remainingResults = 500;
+
+    final declarations = <search.Declaration>[];
+    final filePathsHashSet = new LinkedHashSet<String>();
+    for (var driver in server.driverMap.values) {
+      final driverResults = await driver.search
+          .declarations(regex, remainingResults, filePathsHashSet);
+      declarations.addAll(driverResults);
+      remainingResults -= driverResults.length;
+    }
+
+    // Convert the file paths to something we can quickly index into since
+    // we'll be looking things up by index a lot.
+    final filePaths = filePathsHashSet.toList();
+
+    // Map the results to SymbolInformations and flatten the list of lists.
+    final symbols = declarations
+        .map((declaration) => _asSymbolInformation(
+              declaration,
+              clientSupportedSymbolKinds,
+              filePaths,
+            ))
+        .toList();
+
+    return success(symbols);
+  }
+
+  SymbolInformation _asSymbolInformation(
+    search.Declaration declaration,
+    HashSet<SymbolKind> clientSupportedSymbolKinds,
+    List<String> filePaths,
+  ) {
+    final filePath = filePaths[declaration.fileIndex];
+
+    final kind = declarationKindToSymbolKind(
+      clientSupportedSymbolKinds,
+      declaration.kind,
+    );
+    final range = toRange(
+      declaration.lineInfo,
+      declaration.codeOffset,
+      declaration.codeLength,
+    );
+    final location = new Location(
+      Uri.file(filePath).toString(),
+      range,
+    );
+
+    return new SymbolInformation(
+        declaration.name,
+        kind,
+        null, // We don't have easy access to isDeprecated here.
+        location,
+        declaration.className ?? declaration.mixinName);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/lsp/mapping.dart b/pkg/analysis_server/lib/src/lsp/mapping.dart
index edf1327..2f9dd65 100644
--- a/pkg/analysis_server/lib/src/lsp/mapping.dart
+++ b/pkg/analysis_server/lib/src/lsp/mapping.dart
@@ -15,6 +15,8 @@
 import 'package:analyzer/dart/analysis/results.dart' as server;
 import 'package:analyzer/error/error.dart' as server;
 import 'package:analyzer/source/line_info.dart' as server;
+import 'package:analyzer/src/dart/analysis/search.dart' as server
+    show DeclarationKind;
 import 'package:analyzer/src/generated/source.dart' as server;
 import 'package:analyzer_plugin/utilities/fixes/fixes.dart' as server;
 
@@ -47,6 +49,48 @@
           .toList());
 }
 
+lsp.SymbolKind declarationKindToSymbolKind(
+  HashSet<lsp.SymbolKind> clientSupportedSymbolKinds,
+  server.DeclarationKind kind,
+) {
+  bool isSupported(lsp.SymbolKind kind) =>
+      clientSupportedSymbolKinds.contains(kind);
+
+  List<lsp.SymbolKind> getKindPreferences() {
+    switch (kind) {
+      case server.DeclarationKind.CLASS:
+      case server.DeclarationKind.CLASS_TYPE_ALIAS:
+        return const [lsp.SymbolKind.Class];
+      case server.DeclarationKind.CONSTRUCTOR:
+        return const [lsp.SymbolKind.Constructor];
+      case server.DeclarationKind.ENUM:
+      case server.DeclarationKind.ENUM_CONSTANT:
+        return const [lsp.SymbolKind.Enum];
+      case server.DeclarationKind.FIELD:
+        return const [lsp.SymbolKind.Field];
+      case server.DeclarationKind.FUNCTION:
+        return const [lsp.SymbolKind.Function];
+      case server.DeclarationKind.FUNCTION_TYPE_ALIAS:
+        return const [lsp.SymbolKind.Class];
+      case server.DeclarationKind.GETTER:
+        return const [lsp.SymbolKind.Property];
+      case server.DeclarationKind.METHOD:
+        return const [lsp.SymbolKind.Method];
+      case server.DeclarationKind.MIXIN:
+        return const [lsp.SymbolKind.Class];
+      case server.DeclarationKind.SETTER:
+        return const [lsp.SymbolKind.Property];
+      case server.DeclarationKind.VARIABLE:
+        return const [lsp.SymbolKind.Variable];
+      default:
+        assert(false, 'Unexpected declaration kind $kind');
+        return null;
+    }
+  }
+
+  return getKindPreferences().firstWhere(isSupported, orElse: () => null);
+}
+
 lsp.CompletionItemKind elementKindToCompletionItemKind(
   HashSet<lsp.CompletionItemKind> clientSupportedCompletionKinds,
   server.ElementKind kind,
diff --git a/pkg/analysis_server/lib/src/nullability/conditional_discard.dart b/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
new file mode 100644
index 0000000..4b47370
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/conditional_discard.dart
@@ -0,0 +1,37 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+
+/// Container for information gathered during nullability migration about a
+/// conditional check that might need to be discarded.
+///
+/// This information will be associated with an Expression in the input program
+/// whose boolean value influences control flow (e.g. the condition of an `if`
+/// statement).
+class ConditionalDiscard {
+  /// Constraint variable whose value will be `true` if the code path that
+  /// results from the condition evaluating to `true` will be reachable after
+  /// nullability migration, and therefore should be kept.
+  final ConstraintVariable keepTrue;
+
+  /// Constraint variable whose value will be `false` if the code path that
+  /// results from the condition evaluating to `false` will be reachable after
+  /// nullability migration, and therefore should be kept.
+  final ConstraintVariable keepFalse;
+
+  /// Indicates whether the condition is pure (free from side effects).
+  ///
+  /// For example, a condition like `x == null` is pure (assuming `x` is a local
+  /// variable or static variable), because evaluating it has no user-visible
+  /// effect other than returning a boolean value.
+  ///
+  /// If [pureCondition] is `false`, and either [keepTrue] or [keepFalse] is
+  /// `false`, that it is safe to delete the condition expression as well as the
+  /// dead code branch (e.g. it means that `if (x == null) f(); else g();` could
+  /// be changed to simply `g();`).
+  final bool pureCondition;
+
+  ConditionalDiscard(this.keepTrue, this.keepFalse, this.pureCondition);
+}
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
new file mode 100644
index 0000000..ec6f294
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/constraint_gatherer.dart
@@ -0,0 +1,548 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/conditional_discard.dart';
+import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
+import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/member.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+
+/// Visitor that gathers nullability migration constraints from code to be
+/// migrated.
+///
+/// The return type of each `visit...` method is a [DecoratedType] indicating
+/// the static type of the visited expression, along with the constraint
+/// variables that will determine its nullability.  For `visit...` methods that
+/// don't visit expressions, `null` will be returned.
+class ConstraintGatherer extends GeneralizingAstVisitor<DecoratedType> {
+  /// The repository of constraint variables and decorated types (from a
+  /// previous pass over the source code).
+  final VariableRepository _variables;
+
+  final bool _permissive;
+
+  final NullabilityMigrationAssumptions assumptions;
+
+  /// Constraints gathered by the visitor are stored here.
+  final Constraints _constraints;
+
+  /// The file being analyzed.
+  final Source _source;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `Object`.
+  final DecoratedType _notNullType;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `bool`.
+  final DecoratedType _nonNullableBoolType;
+
+  /// For convenience, a [DecoratedType] representing non-nullable `Type`.
+  final DecoratedType _nonNullableTypeType;
+
+  /// For convenience, a [DecoratedType] representing `Null`.
+  final DecoratedType _nullType;
+
+  /// The [DecoratedType] of the innermost function or method being visited, or
+  /// `null` if the visitor is not inside any function or method.
+  ///
+  /// This is needed to construct the appropriate nullability constraints for
+  /// return statements.
+  DecoratedType _currentFunctionType;
+
+  /// Information about the most recently visited binary expression whose
+  /// boolean value could possibly affect nullability analysis.
+  _ConditionInfo _conditionInfo;
+
+  /// The set of constraint variables that would have to be assigned the value
+  /// of `true` for the code currently being visited to be reachable.
+  ///
+  /// Guard variables are attached to the left hand side of any generated
+  /// constraints, so that constraints do not take effect if they come from
+  /// code that can be proven unreachable by the migration tool.
+  final _guards = <ConstraintVariable>[];
+
+  /// Indicates whether the statement or expression being visited is within
+  /// conditional control flow.  If `true`, this means that the enclosing
+  /// function might complete normally without executing the current statement
+  /// or expression.
+  bool _inConditionalControlFlow = false;
+
+  ConstraintGatherer(TypeProvider typeProvider, this._variables,
+      this._constraints, this._source, this._permissive, this.assumptions)
+      : _notNullType = DecoratedType(typeProvider.objectType, null),
+        _nonNullableBoolType = DecoratedType(typeProvider.boolType, null),
+        _nonNullableTypeType = DecoratedType(typeProvider.typeType, null),
+        _nullType =
+            DecoratedType(typeProvider.nullType, ConstraintVariable.always);
+
+  /// Gets the decorated type of [element] from [_variables], performing any
+  /// necessary substitutions.
+  DecoratedType getOrComputeElementType(Element element,
+      {DecoratedType targetType}) {
+    Map<TypeParameterElement, DecoratedType> substitution;
+    Element baseElement;
+    if (element is Member) {
+      assert(targetType != null);
+      baseElement = element.baseElement;
+      var targetTypeType = targetType.type;
+      if (targetTypeType is InterfaceType &&
+          baseElement is ClassMemberElement) {
+        var enclosingClass = baseElement.enclosingElement;
+        assert(targetTypeType.element == enclosingClass); // TODO(paulberry)
+        substitution = <TypeParameterElement, DecoratedType>{};
+        assert(enclosingClass.typeParameters.length ==
+            targetTypeType.typeArguments.length); // TODO(paulberry)
+        for (int i = 0; i < enclosingClass.typeParameters.length; i++) {
+          substitution[enclosingClass.typeParameters[i]] =
+              targetType.typeArguments[i];
+        }
+      }
+    } else {
+      baseElement = element;
+    }
+    var decoratedBaseType =
+        _variables.decoratedElementType(baseElement, create: true);
+    if (substitution != null) {
+      DartType elementType;
+      if (element is MethodElement) {
+        elementType = element.type;
+      } else {
+        throw element.runtimeType; // TODO(paulberry)
+      }
+      return decoratedBaseType.substitute(
+          _constraints, substitution, elementType);
+    } else {
+      return decoratedBaseType;
+    }
+  }
+
+  @override
+  DecoratedType visitAssertStatement(AssertStatement node) {
+    _handleAssignment(_notNullType, node.condition);
+    if (identical(_conditionInfo?.condition, node.condition)) {
+      if (!_inConditionalControlFlow &&
+          _conditionInfo.trueDemonstratesNonNullIntent != null) {
+        _recordFact(_conditionInfo.trueDemonstratesNonNullIntent);
+      }
+    }
+    node.message?.accept(this);
+    return null;
+  }
+
+  @override
+  DecoratedType visitBinaryExpression(BinaryExpression node) {
+    switch (node.operator.type) {
+      case TokenType.EQ_EQ:
+      case TokenType.BANG_EQ:
+        assert(node.leftOperand is! NullLiteral); // TODO(paulberry)
+        var leftType = node.leftOperand.accept(this);
+        node.rightOperand.accept(this);
+        if (node.rightOperand is NullLiteral) {
+          // TODO(paulberry): figure out what the rules for isPure should be.
+          // TODO(paulberry): only set falseChecksNonNull in unconditional
+          // control flow
+          bool isPure = node.leftOperand is SimpleIdentifier;
+          var conditionInfo = _ConditionInfo(node,
+              isPure: isPure,
+              trueGuard: leftType.nullable,
+              falseDemonstratesNonNullIntent: leftType.nonNullIntent);
+          _conditionInfo = node.operator.type == TokenType.EQ_EQ
+              ? conditionInfo
+              : conditionInfo.not(node);
+        }
+        return _nonNullableBoolType;
+      case TokenType.PLUS:
+        _handleAssignment(_notNullType, node.leftOperand);
+        var callee = node.staticElement;
+        assert(!(callee is ClassMemberElement &&
+            callee.enclosingElement.typeParameters
+                .isNotEmpty)); // TODO(paulberry)
+        assert(callee != null); // TODO(paulberry)
+        var calleeType = getOrComputeElementType(callee);
+        // TODO(paulberry): substitute if necessary
+        assert(calleeType.positionalParameters.length > 0); // TODO(paulberry)
+        _handleAssignment(
+            calleeType.positionalParameters[0], node.rightOperand);
+        return calleeType.returnType;
+      default:
+        assert(false); // TODO(paulberry)
+        return null;
+    }
+  }
+
+  @override
+  DecoratedType visitClassDeclaration(ClassDeclaration node) {
+    node.members.accept(this);
+    return null;
+  }
+
+  @override
+  DecoratedType visitConditionalExpression(ConditionalExpression node) {
+    _handleAssignment(_notNullType, node.condition);
+    // TODO(paulberry): guard anything inside the true and false branches
+    var thenType = node.thenExpression.accept(this);
+    assert(_isSimple(thenType)); // TODO(paulberry)
+    var elseType = node.elseExpression.accept(this);
+    assert(_isSimple(elseType)); // TODO(paulberry)
+    var overallType = DecoratedType(node.staticType,
+        _joinNullabilities(node, thenType.nullable, elseType.nullable));
+    _variables.recordDecoratedExpressionType(node, overallType);
+    return overallType;
+  }
+
+  @override
+  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var defaultValue = node.defaultValue;
+    if (defaultValue == null) {
+      if (node.declaredElement.hasRequired) {
+        // Nothing to do; the implicit default value of `null` will never be
+        // reached.
+      } else if (node.declaredElement.isOptionalPositional ||
+          assumptions.namedNoDefaultParameterHeuristic ==
+              NamedNoDefaultParameterHeuristic.assumeNullable) {
+        _recordFact(getOrComputeElementType(node.declaredElement).nullable);
+      } else {
+        assert(assumptions.namedNoDefaultParameterHeuristic ==
+            NamedNoDefaultParameterHeuristic.assumeRequired);
+      }
+    } else {
+      _handleAssignment(
+          getOrComputeElementType(node.declaredElement), defaultValue);
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitExpressionFunctionBody(ExpressionFunctionBody node) {
+    _handleAssignment(_currentFunctionType.returnType, node.expression);
+    return null;
+  }
+
+  @override
+  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
+    node.functionExpression.parameters.accept(this);
+    assert(_currentFunctionType == null);
+    _currentFunctionType =
+        _variables.decoratedElementType(node.declaredElement);
+    node.functionExpression.body.accept(this);
+    _currentFunctionType = null;
+    return null;
+  }
+
+  @override
+  DecoratedType visitIfStatement(IfStatement node) {
+    // TODO(paulberry): should the use of a boolean in an if-statement be
+    // treated like an implicit `assert(b != null)`?  Probably.
+    _handleAssignment(_notNullType, node.condition);
+    _inConditionalControlFlow = true;
+    ConstraintVariable trueGuard;
+    ConstraintVariable falseGuard;
+    if (identical(_conditionInfo?.condition, node.condition)) {
+      trueGuard = _conditionInfo.trueGuard;
+      falseGuard = _conditionInfo.falseGuard;
+      _variables.recordConditionalDiscard(
+          _source,
+          node,
+          ConditionalDiscard(trueGuard ?? ConstraintVariable.always,
+              falseGuard ?? ConstraintVariable.always, _conditionInfo.isPure));
+    }
+    if (trueGuard != null) {
+      _guards.add(trueGuard);
+    }
+    node.thenStatement.accept(this);
+    if (trueGuard != null) {
+      _guards.removeLast();
+    }
+    if (falseGuard != null) {
+      _guards.add(falseGuard);
+    }
+    node.elseStatement?.accept(this);
+    if (falseGuard != null) {
+      _guards.removeLast();
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitIntegerLiteral(IntegerLiteral node) {
+    return DecoratedType(node.staticType, null);
+  }
+
+  @override
+  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
+    node.parameters.accept(this);
+    assert(_currentFunctionType == null);
+    _currentFunctionType =
+        _variables.decoratedElementType(node.declaredElement);
+    node.body.accept(this);
+    _currentFunctionType = null;
+    return null;
+  }
+
+  @override
+  DecoratedType visitMethodInvocation(MethodInvocation node) {
+    DecoratedType targetType;
+    if (node.target != null) {
+      assert(node.operator.type == TokenType.PERIOD);
+      _checkNonObjectMember(node.methodName.name); // TODO(paulberry)
+      targetType = _handleAssignment(_notNullType, node.target);
+    }
+    var callee = node.methodName.staticElement;
+    assert(callee != null); // TODO(paulberry)
+    var calleeType = getOrComputeElementType(callee, targetType: targetType);
+    // TODO(paulberry): substitute if necessary
+    var arguments = node.argumentList.arguments;
+    int i = 0;
+    var suppliedNamedParameters = Set<String>();
+    for (var expression in arguments) {
+      if (expression is NamedExpression) {
+        var name = expression.name.label.name;
+        var parameterType = calleeType.namedParameters[name];
+        assert(parameterType != null); // TODO(paulberry)
+        _handleAssignment(parameterType, expression.expression);
+        suppliedNamedParameters.add(name);
+      } else {
+        assert(calleeType.positionalParameters.length > i); // TODO(paulberry)
+        _handleAssignment(calleeType.positionalParameters[i++], expression);
+      }
+    }
+    // Any parameters not supplied must be optional.
+    for (var entry in calleeType.namedParameterOptionalVariables.entries) {
+      assert(entry.value != null);
+      if (suppliedNamedParameters.contains(entry.key)) continue;
+      _recordFact(entry.value);
+    }
+    return calleeType.returnType;
+  }
+
+  @override
+  DecoratedType visitNode(AstNode node) {
+    if (_permissive) {
+      try {
+        return super.visitNode(node);
+      } catch (_) {
+        return null;
+      }
+    } else {
+      return super.visitNode(node);
+    }
+  }
+
+  @override
+  DecoratedType visitNullLiteral(NullLiteral node) {
+    return _nullType;
+  }
+
+  @override
+  DecoratedType visitParenthesizedExpression(ParenthesizedExpression node) {
+    return node.expression.accept(this);
+  }
+
+  @override
+  DecoratedType visitReturnStatement(ReturnStatement node) {
+    if (node.expression == null) {
+      _checkAssignment(_currentFunctionType.returnType, _nullType, null);
+    } else {
+      _handleAssignment(_currentFunctionType.returnType, node.expression);
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitSimpleIdentifier(SimpleIdentifier node) {
+    var staticElement = node.staticElement;
+    if (staticElement is ParameterElement) {
+      return getOrComputeElementType(staticElement);
+    } else if (staticElement is ClassElement) {
+      return _nonNullableTypeType;
+    } else {
+      // TODO(paulberry)
+      throw new UnimplementedError('${staticElement.runtimeType}');
+    }
+  }
+
+  @override
+  DecoratedType visitStringLiteral(StringLiteral node) {
+    return DecoratedType(node.staticType, null);
+  }
+
+  @override
+  DecoratedType visitThisExpression(ThisExpression node) {
+    return DecoratedType(node.staticType, null);
+  }
+
+  @override
+  DecoratedType visitThrowExpression(ThrowExpression node) {
+    node.expression.accept(this);
+    // TODO(paulberry): do we need to check the expression type?  I think not.
+    return DecoratedType(node.staticType, null);
+  }
+
+  @override
+  DecoratedType visitTypeName(TypeName typeName) {
+    return DecoratedType(typeName.type, null);
+  }
+
+  /// Creates the necessary constraint(s) for an assignment from [sourceType] to
+  /// [destinationType].  [expression] is the expression whose type is
+  /// [sourceType]; it is the expression we will have to null-check in the case
+  /// where a nullable source is assigned to a non-nullable destination.
+  void _checkAssignment(DecoratedType destinationType, DecoratedType sourceType,
+      Expression expression) {
+    if (sourceType.nullable != null) {
+      if (destinationType.nullable != null) {
+        _recordConstraint(sourceType.nullable, destinationType.nullable);
+      } else {
+        assert(expression != null); // TODO(paulberry)
+        var checkNotNull = CheckExpression(expression);
+        _recordConstraint(sourceType.nullable, checkNotNull);
+        _variables.recordExpressionChecks(
+            expression, ExpressionChecks(_source, checkNotNull));
+      }
+    }
+    // TODO(paulberry): it's a cheat to pass in expression=null for the
+    // recursive checks.  Really we want to unify all the checks in a single
+    // ExpressionChecks object.
+    expression = null;
+    // TODO(paulberry): generalize this.
+    if ((_isSimple(sourceType) || destinationType.type.isObject) &&
+        _isSimple(destinationType)) {
+      // Ok; nothing further to do.
+    } else if (sourceType.type is InterfaceType &&
+        destinationType.type is InterfaceType &&
+        sourceType.type.element == destinationType.type.element) {
+      assert(sourceType.typeArguments.length ==
+          destinationType.typeArguments.length);
+      for (int i = 0; i < sourceType.typeArguments.length; i++) {
+        _checkAssignment(destinationType.typeArguments[i],
+            sourceType.typeArguments[i], expression);
+      }
+    } else if (destinationType.type.isDynamic || sourceType.type.isDynamic) {
+      // ok; nothing further to do.
+    } else {
+      throw '$destinationType <= $sourceType'; // TODO(paulberry)
+    }
+  }
+
+  /// Double checks that [name] is not the name of a method or getter declared
+  /// on [Object].
+  ///
+  /// TODO(paulberry): get rid of this method and put the correct logic into the
+  /// call sites.
+  void _checkNonObjectMember(String name) {
+    assert(name != 'toString');
+    assert(name != 'hashCode');
+    assert(name != 'noSuchMethod');
+    assert(name != 'runtimeType');
+  }
+
+  /// Creates the necessary constraint(s) for an assignment of the given
+  /// [expression] to a destination whose type is [destinationType].
+  DecoratedType _handleAssignment(
+      DecoratedType destinationType, Expression expression) {
+    var sourceType = expression.accept(this);
+    _checkAssignment(destinationType, sourceType, expression);
+    return sourceType;
+  }
+
+  /// Double checks that [type] is sufficiently simple for this naive prototype
+  /// implementation.
+  ///
+  /// TODO(paulberry): get rid of this method and put the correct logic into the
+  /// call sites.
+  bool _isSimple(DecoratedType type) {
+    if (type.type.isBottom) return true;
+    if (type.type.isVoid) return true;
+    if (type.type is! InterfaceType) return false;
+    if ((type.type as InterfaceType).typeParameters.isNotEmpty) return false;
+    return true;
+  }
+
+  /// Creates a constraint variable (if necessary) representing the nullability
+  /// of [node], which is the disjunction of the nullabilities [a] and [b].
+  ConstraintVariable _joinNullabilities(
+      ConditionalExpression node, ConstraintVariable a, ConstraintVariable b) {
+    if (a == null) return b;
+    if (b == null) return a;
+    if (identical(a, ConstraintVariable.always) ||
+        identical(b, ConstraintVariable.always)) {
+      return ConstraintVariable.always;
+    }
+    var result = TypeIsNullable(node.offset);
+    _recordConstraint(a, result);
+    _recordConstraint(b, result);
+    _recordConstraint(result, ConstraintVariable.or(_constraints, a, b));
+    return result;
+  }
+
+  /// Records a constraint having [condition] as its left hand side and
+  /// [consequence] as its right hand side.  Any [_guards] are included in the
+  /// left hand side.
+  void _recordConstraint(
+      ConstraintVariable condition, ConstraintVariable consequence) {
+    _guards.add(condition);
+    _recordFact(consequence);
+    _guards.removeLast();
+  }
+
+  /// Records a constraint having [consequence] as its right hand side.  Any
+  /// [_guards] are used as the right hand side.
+  void _recordFact(ConstraintVariable consequence) {
+    _constraints.record(_guards, consequence);
+  }
+}
+
+/// Information about a binary expression whose boolean value could possibly
+/// affect nullability analysis.
+class _ConditionInfo {
+  /// The [expression] of interest.
+  final Expression condition;
+
+  /// Indicates whether [condition] is pure (free from side effects).
+  ///
+  /// For example, a condition like `x == null` is pure (assuming `x` is a local
+  /// variable or static variable), because evaluating it has no user-visible
+  /// effect other than returning a boolean value.
+  final bool isPure;
+
+  /// If not `null`, the [ConstraintVariable] whose value must be `true` in
+  /// order for [condition] to evaluate to `true`.
+  final ConstraintVariable trueGuard;
+
+  /// If not `null`, the [ConstraintVariable] whose value must be `true` in
+  /// order for [condition] to evaluate to `false`.
+  final ConstraintVariable falseGuard;
+
+  /// If not `null`, the [ConstraintVariable] whose value should be set to
+  /// `true` if [condition] is asserted to be `true`.
+  final ConstraintVariable trueDemonstratesNonNullIntent;
+
+  /// If not `null`, the [ConstraintVariable] whose value should be set to
+  /// `true` if [condition] is asserted to be `false`.
+  final ConstraintVariable falseDemonstratesNonNullIntent;
+
+  _ConditionInfo(this.condition,
+      {@required this.isPure,
+      this.trueGuard,
+      this.falseGuard,
+      this.trueDemonstratesNonNullIntent,
+      this.falseDemonstratesNonNullIntent});
+
+  /// Returns a new [_ConditionInfo] describing the boolean "not" of `this`.
+  _ConditionInfo not(Expression condition) => _ConditionInfo(condition,
+      isPure: isPure,
+      trueGuard: falseGuard,
+      falseGuard: trueGuard,
+      trueDemonstratesNonNullIntent: falseDemonstratesNonNullIntent,
+      falseDemonstratesNonNullIntent: trueDemonstratesNonNullIntent);
+}
diff --git a/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
new file mode 100644
index 0000000..d3a89538
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/constraint_variable_gatherer.dart
@@ -0,0 +1,233 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/conditional_discard.dart';
+import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/source.dart';
+
+/// Visitor that gathers constraint variables for nullability migration from
+/// code to be migrated.
+///
+/// The return type of each `visit...` method is a [DecoratedType] indicating
+/// the static type of the element declared by the visited node, along with the
+/// constraint variables that will determine its nullability.  For `visit...`
+/// methods that don't visit declarations, `null` will be returned.
+class ConstraintVariableGatherer extends GeneralizingAstVisitor<DecoratedType> {
+  /// Constraint variables and decorated types are stored here.
+  final VariableRecorder _variables;
+
+  /// The file being analyzed.
+  final Source _source;
+
+  /// If the parameters of a function or method are being visited, the
+  /// [DecoratedType] of the corresponding function or method type.
+  ///
+  /// TODO(paulberry): should this be updated when we visit generic function
+  /// type syntax?  How about when we visit old-style function-typed formal
+  /// parameters?
+  DecoratedType _currentFunctionType;
+
+  final bool _permissive;
+
+  final NullabilityMigrationAssumptions assumptions;
+
+  ConstraintVariableGatherer(
+      this._variables, this._source, this._permissive, this.assumptions);
+
+  /// Creates and stores a [DecoratedType] object corresponding to the given
+  /// [type] AST, and returns it.
+  DecoratedType decorateType(TypeAnnotation type) {
+    return type == null
+        // TODO(danrubel): Return something other than this
+        // to indicate that we should insert a type for the declaration
+        // that is missing a type reference.
+        ? new DecoratedType(DynamicTypeImpl.instance, ConstraintVariable.always)
+        : type.accept(this);
+  }
+
+  @override
+  DecoratedType visitDefaultFormalParameter(DefaultFormalParameter node) {
+    var decoratedType = node.parameter.accept(this);
+    ConstraintVariable optional;
+    if (node.declaredElement.hasRequired) {
+      optional = null;
+    } else if (node.defaultValue != null) {
+      optional = ConstraintVariable.always;
+    } else {
+      optional = decoratedType.nullable;
+      _variables.recordPossiblyOptional(_source, node, optional);
+    }
+    if (optional != null) {
+      _currentFunctionType
+              .namedParameterOptionalVariables[node.declaredElement.name] =
+          optional;
+    }
+    return null;
+  }
+
+  @override
+  DecoratedType visitFormalParameter(FormalParameter node) {
+    // Do not visit children
+    // TODO(paulberry): handle all types of formal parameters
+    // - NormalFormalParameter
+    // - SimpleFormalParameter
+    // - FieldFormalParameter
+    // - FunctionTypedFormalParameter
+    // - DefaultFormalParameter
+    return null;
+  }
+
+  @override
+  DecoratedType visitFunctionDeclaration(FunctionDeclaration node) {
+    _handleExecutableDeclaration(node.declaredElement, node.returnType,
+        node.functionExpression.parameters);
+    return null;
+  }
+
+  @override
+  DecoratedType visitMethodDeclaration(MethodDeclaration node) {
+    _handleExecutableDeclaration(
+        node.declaredElement, node.returnType, node.parameters);
+    return null;
+  }
+
+  @override
+  DecoratedType visitNode(AstNode node) {
+    if (_permissive) {
+      try {
+        return super.visitNode(node);
+      } catch (_) {
+        return null;
+      }
+    } else {
+      return super.visitNode(node);
+    }
+  }
+
+  @override
+  DecoratedType visitSimpleFormalParameter(SimpleFormalParameter node) {
+    var type = decorateType(node.type);
+    var declaredElement = node.declaredElement;
+    assert(type.nonNullIntent == null);
+    type.nonNullIntent = NonNullIntent(node.offset);
+    _variables.recordDecoratedElementType(declaredElement, type);
+    if (declaredElement.isNamed) {
+      _currentFunctionType.namedParameters[declaredElement.name] = type;
+    } else {
+      _currentFunctionType.positionalParameters.add(type);
+    }
+    return type;
+  }
+
+  @override
+  DecoratedType visitTypeAnnotation(TypeAnnotation node) {
+    assert(node != null); // TODO(paulberry)
+    assert(node is NamedType); // TODO(paulberry)
+    var type = node.type;
+    if (type.isVoid) return DecoratedType(type, ConstraintVariable.always);
+    assert(
+        type is InterfaceType || type is TypeParameterType); // TODO(paulberry)
+    var typeArguments = const <DecoratedType>[];
+    if (type is InterfaceType && type.typeParameters.isNotEmpty) {
+      if (node is TypeName) {
+        assert(node.typeArguments != null);
+        typeArguments =
+            node.typeArguments.arguments.map((t) => t.accept(this)).toList();
+      } else {
+        assert(false); // TODO(paulberry): is this possible?
+      }
+    }
+    var nullable = node.question == null
+        ? TypeIsNullable(node.end)
+        : ConstraintVariable.always;
+    var decoratedType = DecoratedTypeAnnotation(
+        type, nullable, _source, node.end,
+        typeArguments: typeArguments);
+    _variables.recordDecoratedTypeAnnotation(node, decoratedType);
+    return decoratedType;
+  }
+
+  @override
+  DecoratedType visitTypeName(TypeName node) => visitTypeAnnotation(node);
+
+  /// Common handling of function and method declarations.
+  void _handleExecutableDeclaration(ExecutableElement declaredElement,
+      TypeAnnotation returnType, FormalParameterList parameters) {
+    var decoratedReturnType = decorateType(returnType);
+    var previousFunctionType = _currentFunctionType;
+    // TODO(paulberry): test that it's correct to use `null` for the nullability
+    // of the function type
+    var functionType = DecoratedType(declaredElement.type, null,
+        returnType: decoratedReturnType,
+        positionalParameters: [],
+        namedParameters: {},
+        namedParameterOptionalVariables: {});
+    _currentFunctionType = functionType;
+    parameters.accept(this);
+    _currentFunctionType = previousFunctionType;
+    _variables.recordDecoratedElementType(declaredElement, functionType);
+  }
+}
+
+/// Repository of constraint variables and decorated types corresponding to the
+/// code being migrated.
+///
+/// This data structure records the results of the first pass of migration
+/// ([ConstraintVariableGatherer], which finds all the variables that need to be
+/// constrained).
+abstract class VariableRecorder {
+  /// Associates decorated type information with the given [element].
+  void recordDecoratedElementType(Element element, DecoratedType type);
+
+  /// Associates decorated type information with the given [type] node.
+  void recordDecoratedTypeAnnotation(
+      TypeAnnotation node, DecoratedTypeAnnotation type);
+
+  /// Associates a constraint variable with the question of whether the given
+  /// named parameter should be optional (should not have a `required`
+  /// annotation added to it).
+  void recordPossiblyOptional(Source source, DefaultFormalParameter parameter,
+      ConstraintVariable variable);
+}
+
+/// Repository of constraint variables and decorated types corresponding to the
+/// code being migrated.
+///
+/// This data structure allows the second pass of migration
+/// ([ConstraintGatherer], which builds all the constraints) to access the
+/// results of the first ([ConstraintVariableGatherer], which finds all the
+/// variables that need to be constrained).
+abstract class VariableRepository {
+  /// Retrieves the [DecoratedType] associated with the static type of the given
+  /// [element].
+  ///
+  /// If [create] is `true`, and no decorated type is found for the given
+  /// element, one is synthesized using [DecoratedType.forElement].
+  DecoratedType decoratedElementType(Element element, {bool create: false});
+
+  /// Records conditional discard information for the given AST node (which is
+  /// an `if` statement or a conditional (`?:`) expression).
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard);
+
+  /// Associates decorated type information with the given [element].
+  ///
+  /// TODO(paulberry): why is this in both [VariableRecorder] and
+  /// [VariableRepository]?
+  void recordDecoratedElementType(Element element, DecoratedType type);
+
+  /// Associates decorated type information with the given expression [node].
+  void recordDecoratedExpressionType(Expression node, DecoratedType type);
+
+  /// Associates a set of nullability checks with the given expression [node].
+  void recordExpressionChecks(Expression expression, ExpressionChecks checks);
+}
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type.dart b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
new file mode 100644
index 0000000..53c023b
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type.dart
@@ -0,0 +1,220 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/dart/element/type.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+
+/// Representation of a type in the code to be migrated.  In addition to
+/// tracking the (unmigrated) [DartType], we track the [ConstraintVariable]s
+/// indicating whether the type, and the types that compose it, are nullable.
+class DecoratedType {
+  final DartType type;
+
+  /// [ConstraintVariable] whose value will be set to `true` if this type needs
+  /// to be nullable.
+  ///
+  /// If `null`, that means that an external constraint (outside the code being
+  /// migrated) forces this type to be non-nullable.
+  final ConstraintVariable nullable;
+
+  /// [ConstraintVariable] whose value will be set to `true` if the usage of
+  /// this type suggests that it is intended to be non-null (because of the
+  /// presence of a statement or expression that would unconditionally lead to
+  /// an exception being thrown in the case of a `null` value at runtime).
+  ConstraintVariable nonNullIntent;
+
+  /// If `this` is a function type, the [DecoratedType] of its return type.
+  final DecoratedType returnType;
+
+  /// If `this` is a function type, the [DecoratedType] of each of its
+  /// positional parameters (including both required and optional positional
+  /// parameters).
+  final List<DecoratedType> positionalParameters;
+
+  /// If `this` is a function type, the [DecoratedType] of each of its named
+  /// parameters.
+  final Map<String, DecoratedType> namedParameters;
+
+  /// If `this` is a function type, [ConstraintVariable] for each of its named
+  /// parameters indicating whether the given named parameter needs to be
+  /// optional (no `required` annotation).
+  ///
+  /// If there is no entry in this map corresponding to a given named parameter,
+  /// that means that it has already been decided (prior to migration) that the
+  /// given named parameter is required.  TODO(paulberry): test that this works
+  /// for already-migrated code.
+  final Map<String, ConstraintVariable> namedParameterOptionalVariables;
+
+  /// If `this` is a parameterized type, the [DecoratedType] of each of its
+  /// type parameters.
+  ///
+  /// TODO(paulberry): how should we handle generic typedefs?
+  final List<DecoratedType> typeArguments;
+
+  DecoratedType(this.type, this.nullable,
+      {this.returnType,
+      this.positionalParameters = const [],
+      this.namedParameters = const {},
+      this.namedParameterOptionalVariables = const {},
+      this.typeArguments = const []}) {
+    // The type system doesn't have a non-nullable version of `dynamic`.  So if
+    // the type is `dynamic`, verify that `nullable` is `always`.
+    assert(!type.isDynamic || identical(nullable, ConstraintVariable.always));
+  }
+
+  /// Creates a [DecoratedType] corresponding to the given [element], which is
+  /// presumed to have come from code that is already migrated.
+  factory DecoratedType.forElement(Element element) {
+    DecoratedType decorate(DartType type) {
+      assert((type as TypeImpl).nullability ==
+          Nullability.indeterminate); // TODO(paulberry)
+      if (type is FunctionType) {
+        var decoratedType = DecoratedType(type, null,
+            returnType: decorate(type.returnType), positionalParameters: []);
+        for (var parameter in type.parameters) {
+          assert(parameter.isPositional); // TODO(paulberry)
+          decoratedType.positionalParameters.add(decorate(parameter.type));
+        }
+        return decoratedType;
+      } else if (type is InterfaceType) {
+        assert(type.typeParameters.isEmpty); // TODO(paulberry)
+        return DecoratedType(type, null);
+      } else {
+        throw type.runtimeType; // TODO(paulberry)
+      }
+    }
+
+    DecoratedType decoratedType;
+    if (element is MethodElement) {
+      decoratedType = decorate(element.type);
+    } else {
+      throw element.runtimeType; // TODO(paulberry)
+    }
+    return decoratedType;
+  }
+
+  /// Apply the given [substitution] to this type.
+  ///
+  /// [undecoratedResult] is the result of the substitution, as determined by
+  /// the normal type system.
+  DecoratedType substitute(
+      Constraints constraints,
+      Map<TypeParameterElement, DecoratedType> substitution,
+      DartType undecoratedResult) {
+    if (substitution.isEmpty) return this;
+    return _substitute(constraints, substitution, undecoratedResult);
+  }
+
+  @override
+  String toString() {
+    var trailing = nullable == null ? '' : '?($nullable)';
+    var type = this.type;
+    if (type is TypeParameterType || type is VoidType) {
+      return '$type$trailing';
+    } else if (type is InterfaceType) {
+      var name = type.element.name;
+      var args = '';
+      if (type.typeArguments.isNotEmpty) {
+        args = '<${type.typeArguments.join(', ')}>';
+      }
+      return '$name$args$trailing';
+    } else if (type is FunctionType) {
+      assert(type.typeFormals.isEmpty); // TODO(paulberry)
+      assert(type.namedParameterTypes.isEmpty &&
+          namedParameters.isEmpty); // TODO(paulberry)
+      var args = positionalParameters.map((p) => p.toString()).join(', ');
+      return '$returnType Function($args)$trailing';
+    } else if (type is DynamicTypeImpl) {
+      return 'dynamic';
+    } else {
+      throw '$type'; // TODO(paulberry)
+    }
+  }
+
+  /// Internal implementation of [_substitute], used as a recursion target.
+  DecoratedType _substitute(
+      Constraints constraints,
+      Map<TypeParameterElement, DecoratedType> substitution,
+      DartType undecoratedResult) {
+    var type = this.type;
+    if (type is FunctionType && undecoratedResult is FunctionType) {
+      assert(type.typeFormals.isEmpty); // TODO(paulberry)
+      var newPositionalParameters = <DecoratedType>[];
+      for (int i = 0; i < positionalParameters.length; i++) {
+        var numRequiredParameters =
+            undecoratedResult.normalParameterTypes.length;
+        var undecoratedParameterType = i < numRequiredParameters
+            ? undecoratedResult.normalParameterTypes[i]
+            : undecoratedResult
+                .optionalParameterTypes[i - numRequiredParameters];
+        newPositionalParameters.add(positionalParameters[i]
+            ._substitute(constraints, substitution, undecoratedParameterType));
+      }
+      return DecoratedType(undecoratedResult, nullable,
+          returnType: returnType._substitute(
+              constraints, substitution, undecoratedResult.returnType),
+          positionalParameters: newPositionalParameters);
+    } else if (type is TypeParameterType) {
+      var inner = substitution[type.element];
+      return DecoratedType(undecoratedResult,
+          ConstraintVariable.or(constraints, inner?.nullable, nullable));
+    } else if (type is VoidType) {
+      return this;
+    }
+    throw '$type.substitute($substitution)'; // TODO(paulberry)
+  }
+}
+
+/// A [DecoratedType] based on a type annotation appearing explicitly in the
+/// source code.
+///
+/// This class implements [PotentialModification] because it knows how to update
+/// the source code to reflect its nullability.
+class DecoratedTypeAnnotation extends DecoratedType
+    implements PotentialModification {
+  @override
+  final Source source;
+
+  final int _offset;
+
+  DecoratedTypeAnnotation(
+      DartType type, ConstraintVariable nullable, this.source, this._offset,
+      {List<DecoratedType> typeArguments = const []})
+      : super(type, nullable, typeArguments: typeArguments);
+
+  @override
+  bool get isEmpty =>
+      identical(nullable, ConstraintVariable.always) || !nullable.value;
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? [] : [SourceEdit(_offset, 0, '?')];
+}
+
+/// Type of a [ConstraintVariable] representing the fact that a type is intended
+/// to be non-null.
+class NonNullIntent extends ConstraintVariable {
+  final int _offset;
+
+  NonNullIntent(this._offset);
+
+  @override
+  toString() => 'nonNullIntent($_offset)';
+}
+
+/// Type of a [ConstraintVariable] representing the fact that a type is
+/// nullable.
+class TypeIsNullable extends ConstraintVariable {
+  final int _offset;
+
+  TypeIsNullable(this._offset);
+
+  @override
+  toString() => 'nullable($_offset)';
+}
diff --git a/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
new file mode 100644
index 0000000..59164ce
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/decorated_type_operations.dart
@@ -0,0 +1,27 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
+import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/type_system.dart';
+import 'package:analyzer/src/dart/resolver/flow_analysis.dart';
+
+/// [TypeOperations] that works with [DecoratedType]s.
+class DecoratedTypeOperations implements TypeOperations<DecoratedType> {
+  final TypeSystem _typeSystem;
+  final VariableRepository _variableRepository;
+
+  DecoratedTypeOperations(this._typeSystem, this._variableRepository);
+
+  @override
+  DecoratedType elementType(VariableElement element) {
+    return _variableRepository.decoratedElementType(element);
+  }
+
+  @override
+  bool isSubtypeOf(DecoratedType leftType, DecoratedType rightType) {
+    return _typeSystem.isSubtypeOf(leftType.type, rightType.type);
+  }
+}
diff --git a/pkg/analysis_server/lib/src/nullability/expression_checks.dart b/pkg/analysis_server/lib/src/nullability/expression_checks.dart
new file mode 100644
index 0000000..3c4af10
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/expression_checks.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+
+/// Container for information gathered during nullability migration about the
+/// set of runtime checks that might need to be performed on the value of an
+/// expression.
+///
+/// TODO(paulberry): the only check we support now is [nullCheck], which checks
+/// that the expression is not null.  We need to add other checks, e.g. to check
+/// that a List<int?> is actually a List<int>.
+class ExpressionChecks extends PotentialModification {
+  @override
+  final Source source;
+
+  /// Constraint variable whose value will be `true` if this expression requires
+  /// a null check.
+  final CheckExpression nullCheck;
+
+  ExpressionChecks(this.source, this.nullCheck);
+
+  @override
+  bool get isEmpty => !nullCheck.value;
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      nullCheck.value ? [SourceEdit(nullCheck.offset, 0, '!')] : [];
+}
diff --git a/pkg/analysis_server/lib/src/nullability/provisional_api.dart b/pkg/analysis_server/lib/src/nullability/provisional_api.dart
new file mode 100644
index 0000000..6352b4d
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/provisional_api.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:analysis_server/src/nullability/decorated_type.dart'
+    as analyzer;
+import 'package:analysis_server/src/nullability/expression_checks.dart'
+    as analyzer;
+import 'package:analysis_server/src/nullability/transitional_api.dart'
+    as analyzer;
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:analyzer/dart/analysis/results.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:meta/meta.dart';
+
+export 'package:analysis_server/src/nullability/transitional_api.dart'
+    show NamedNoDefaultParameterHeuristic, NullabilityMigrationAssumptions;
+
+/// Kinds of fixes that might be performed by nullability migration.
+class NullabilityFixKind {
+  /// A formal parameter needs to have a required annotation added.
+  static const addRequired =
+      const NullabilityFixKind._(appliedMessage: 'Add a required annotation');
+
+  /// An expression's value needs to be null-checked.
+  static const checkExpression = const NullabilityFixKind._(
+    appliedMessage: 'Added a null check to an expression',
+  );
+
+  /// An explicit type mentioned in the source program needs to be made
+  /// nullable.
+  static const makeTypeNullable = const NullabilityFixKind._(
+    appliedMessage: 'Changed a type to be nullable',
+  );
+
+  /// An if-test or conditional expression needs to have its "then" branch
+  /// discarded.
+  static const discardThen = const NullabilityFixKind._(
+    appliedMessage: 'Discarded an unreachable conditional then branch',
+  );
+
+  /// An if-test or conditional expression needs to have its "else" branch
+  /// discarded.
+  static const discardElse = const NullabilityFixKind._(
+    appliedMessage: 'Discarded an unreachable conditional else branch',
+  );
+
+  /// A message used by dartfix to indicate a fix has been applied.
+  final String appliedMessage;
+
+  const NullabilityFixKind._({@required this.appliedMessage});
+}
+
+/// Provisional API for DartFix to perform nullability migration.
+///
+/// Usage: pass each input source file to [prepareInput].  Then pass each input
+/// source file to [processInput].  Then call [finish] to obtain the
+/// modifications that need to be made to each source file.
+///
+/// TODO(paulberry): figure out whether this API is what we want, and figure out
+/// what file/folder it belongs in.
+class NullabilityMigration {
+  final analyzer.NullabilityMigration _analyzerMigration;
+  final NullabilityMigrationListener listener;
+
+  /// Prepares to perform nullability migration.
+  ///
+  /// If [permissive] is `true`, exception handling logic will try to proceed
+  /// as far as possible even though the migration algorithm is not yet
+  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
+  /// is fully implemented.
+  NullabilityMigration(this.listener,
+      {bool permissive: false,
+      analyzer.NullabilityMigrationAssumptions assumptions:
+          const analyzer.NullabilityMigrationAssumptions()})
+      : _analyzerMigration = analyzer.NullabilityMigration(
+            permissive: permissive, assumptions: assumptions);
+
+  void finish() {
+    _analyzerMigration.finish().forEach((pm) {
+      listener.addFix(_SingleNullabilityFix(pm));
+    });
+  }
+
+  void prepareInput(ResolvedUnitResult result) {
+    _analyzerMigration.prepareInput(result.unit);
+  }
+
+  void processInput(ResolvedUnitResult result) {
+    _analyzerMigration.processInput(result.unit, result.typeProvider);
+  }
+}
+
+/// [NullabilityMigrationListener] is used by [NullabilityMigration]
+/// to communicate source changes or "fixes" to the client.
+abstract class NullabilityMigrationListener {
+  /// [addFix] is called once for each source change.
+  void addFix(SingleNullabilityFix fix);
+}
+
+/// Representation of a single conceptual change made by the nullability
+/// migration algorithm.  This change might require multiple source edits to
+/// achieve.
+abstract class SingleNullabilityFix {
+  /// What kind of fix this is.
+  NullabilityFixKind get kind;
+
+  /// Location of the change, for reporting to the user.
+  Location get location;
+
+  /// File to change.
+  Source get source;
+
+  /// Individual source edits to achieve the change.  May be returned in any
+  /// order.
+  Iterable<SourceEdit> get sourceEdits;
+}
+
+/// Implementation of [SingleNullabilityFix] used internally by
+/// [NullabilityMigration].
+class _SingleNullabilityFix extends SingleNullabilityFix {
+  @override
+  final List<SourceEdit> sourceEdits;
+
+  @override
+  final Source source;
+
+  @override
+  final NullabilityFixKind kind;
+
+  factory _SingleNullabilityFix(
+      analyzer.PotentialModification potentialModification) {
+    // TODO(paulberry): once everything is migrated into the analysis server,
+    // the migration engine can just create SingleNullabilityFix objects
+    // directly and set their kind appropriately; we won't need to translate the
+    // kinds using a bunch of `is` checks.
+    NullabilityFixKind kind;
+    if (potentialModification is analyzer.ExpressionChecks) {
+      kind = NullabilityFixKind.checkExpression;
+    } else if (potentialModification is analyzer.DecoratedTypeAnnotation) {
+      kind = NullabilityFixKind.makeTypeNullable;
+    } else if (potentialModification is analyzer.ConditionalModification) {
+      kind = potentialModification.discard.keepFalse.value
+          ? NullabilityFixKind.discardThen
+          : NullabilityFixKind.discardElse;
+    } else if (potentialModification is analyzer.PotentiallyAddRequired) {
+      kind = NullabilityFixKind.addRequired;
+    } else {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+    return _SingleNullabilityFix._(potentialModification.modifications.toList(),
+        potentialModification.source, kind);
+  }
+
+  _SingleNullabilityFix._(this.sourceEdits, this.source, this.kind);
+
+  /// TODO(paulberry): do something better
+  Location get location => null;
+}
diff --git a/pkg/analysis_server/lib/src/nullability/transitional_api.dart b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
new file mode 100644
index 0000000..4f0c81a
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/transitional_api.dart
@@ -0,0 +1,310 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/conditional_discard.dart';
+import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
+import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
+import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart' show SourceEdit;
+
+/// Type of a [ConstraintVariable] representing the addition of a null check.
+class CheckExpression extends ConstraintVariable {
+  final int offset;
+
+  CheckExpression(Expression expression) : offset = expression.end;
+
+  @override
+  toString() => 'checkNotNull($offset)';
+}
+
+/// Records information about how a conditional expression or statement might
+/// need to be modified.
+class ConditionalModification extends PotentialModification {
+  final int offset;
+
+  final int end;
+
+  final bool isStatement;
+
+  final ConditionalDiscard discard;
+
+  final _KeepNode condition;
+
+  final _KeepNode thenStatement;
+
+  final _KeepNode elseStatement;
+
+  @override
+  final Source source;
+
+  factory ConditionalModification(
+      Source source, AstNode node, ConditionalDiscard discard) {
+    if (node is IfStatement) {
+      return ConditionalModification._(
+          node.offset,
+          node.end,
+          node is Statement,
+          discard,
+          _KeepNode(node.condition),
+          _KeepNode(node.thenStatement),
+          _KeepNode(node.elseStatement),
+          source);
+    } else {
+      throw new UnimplementedError('TODO(paulberry)');
+    }
+  }
+
+  ConditionalModification._(
+      this.offset,
+      this.end,
+      this.isStatement,
+      this.discard,
+      this.condition,
+      this.thenStatement,
+      this.elseStatement,
+      this.source);
+
+  @override
+  bool get isEmpty => discard.keepTrue.value && discard.keepFalse.value;
+
+  @override
+  Iterable<SourceEdit> get modifications {
+    if (isEmpty) return const [];
+    // TODO(paulberry): move the following logic into DartEditBuilder (see
+    // dartbug.com/35872).
+    var result = <SourceEdit>[];
+    var keepNodes = <_KeepNode>[];
+    if (!discard.pureCondition) {
+      keepNodes.add(condition); // TODO(paulberry): test
+    }
+    if (discard.keepTrue.value) {
+      keepNodes.add(thenStatement); // TODO(paulberry): test
+    }
+    if (discard.keepFalse.value) {
+      keepNodes.add(elseStatement); // TODO(paulberry): test
+    }
+    // TODO(paulberry): test thoroughly
+    for (int i = 0; i < keepNodes.length; i++) {
+      var keepNode = keepNodes[i];
+      if (i == 0 && keepNode.offset != offset) {
+        result.add(SourceEdit(offset, 0, '/* '));
+      }
+      if (i != 0 || keepNode.offset != offset) {
+        result.add(SourceEdit(keepNode.offset, 0, '*/ '));
+      }
+      if (i != keepNodes.length - 1 || keepNode.end != end) {
+        result.add(SourceEdit(keepNode.end, 0,
+            keepNode.isExpression && isStatement ? '; /*' : ' /*'));
+      }
+      if (i == keepNodes.length - 1 && keepNode.end != end) {
+        result.add(SourceEdit(end, 0, ' */'));
+      }
+    }
+    return result;
+  }
+}
+
+/// Enum encapsulating the various options proposed at
+/// https://github.com/dart-lang/language/issues/156#issuecomment-460525075
+enum DefaultParameterHandling {
+  /// Option 2: Add required named parameters
+  ///
+  /// - `{int x}` implicitly means `x` is required
+  ///   - required-ness goes into the function type:
+  ///     `int Function({required int x})`
+  /// - `{required int? x}` is allowed
+  ///   - means that something must be passed
+  ///   - passing null is allowed
+  /// - `{int x = 3}` is allowed
+  ///   - `x` is optional
+  ///   - passing null to it is an error
+  ///   - passing nothing to it results in it getting the default value
+  /// - `[int x]` is an error
+  /// - `[int x = 3]` is allowed
+  option2_addRequiredNamedParameters,
+}
+
+/// Enum representing the possible heuristics for handling named parameters with
+/// no default value.
+enum NamedNoDefaultParameterHeuristic {
+  /// Assume that the parameter should be considered nullable, unless the user
+  /// has explicitly marked it as `@required`.
+  assumeNullable,
+
+  /// Assume that the parameter should be considered required, unless the user
+  /// has explicitly marked it as nullable.
+  assumeRequired,
+}
+
+/// Transitional migration API.
+///
+/// Usage: pass each input source file to [prepareInput].  Then pass each input
+/// source file to [processInput].  Then call [finish] to obtain the
+/// modifications that need to be made to each source file.
+///
+/// TODO(paulberry): this implementation keeps a lot of CompilationUnit objects
+/// around.  Can we do better?
+class NullabilityMigration {
+  final bool _permissive;
+
+  final NullabilityMigrationAssumptions assumptions;
+
+  final _variables = Variables();
+
+  final _constraints = Solver();
+
+  /// Prepares to perform nullability migration.
+  ///
+  /// If [permissive] is `true`, exception handling logic will try to proceed
+  /// as far as possible even though the migration algorithm is not yet
+  /// complete.  TODO(paulberry): remove this mode once the migration algorithm
+  /// is fully implemented.
+  NullabilityMigration(
+      {bool permissive: false,
+      this.assumptions: const NullabilityMigrationAssumptions()})
+      : _permissive = permissive;
+
+  List<PotentialModification> finish() {
+    _constraints.applyHeuristics();
+    return _variables.getPotentialModifications();
+  }
+
+  void prepareInput(CompilationUnit unit) {
+    unit.accept(ConstraintVariableGatherer(
+        _variables, unit.declaredElement.source, _permissive, assumptions));
+  }
+
+  void processInput(CompilationUnit unit, TypeProvider typeProvider) {
+    unit.accept(ConstraintGatherer(typeProvider, _variables, _constraints,
+        unit.declaredElement.source, _permissive, assumptions));
+  }
+}
+
+/// Assumptions affecting the behavior of the nullability migration tool.
+///
+/// These options generally reflect design decisions that have not yet been
+/// made.  They don't reflect behavioral differences we would want to expose to
+/// the user.
+///
+/// TODO(paulberry): hardcode these assumptions once decisions have been made.
+class NullabilityMigrationAssumptions {
+  /// Handling of default parameters.
+  final DefaultParameterHandling defaultParameterHandling;
+
+  /// Heuristic for handling named parameters with no default value.
+  final NamedNoDefaultParameterHeuristic namedNoDefaultParameterHeuristic;
+
+  const NullabilityMigrationAssumptions(
+      {this.defaultParameterHandling:
+          DefaultParameterHandling.option2_addRequiredNamedParameters,
+      this.namedNoDefaultParameterHeuristic:
+          NamedNoDefaultParameterHeuristic.assumeRequired});
+}
+
+/// Records information about the possible addition of a `@required` annotation
+/// to the source code.
+class PotentiallyAddRequired extends PotentialModification {
+  @override
+  final Source source;
+
+  final ConstraintVariable _optionalVariable;
+
+  final int _offset;
+
+  PotentiallyAddRequired(
+      this.source, DefaultFormalParameter parameter, this._optionalVariable)
+      : _offset = parameter.offset;
+
+  @override
+  bool get isEmpty => _optionalVariable.value;
+
+  @override
+  Iterable<SourceEdit> get modifications =>
+      isEmpty ? const [] : [SourceEdit(_offset, 0, '@required ')];
+}
+
+/// Interface used by data structures representing potential modifications to
+/// the code being migrated.
+abstract class PotentialModification {
+  bool get isEmpty;
+
+  /// Gets the individual migrations that need to be done, considering the
+  /// solution to the constraint equations.
+  Iterable<SourceEdit> get modifications;
+
+  Source get source;
+}
+
+class Variables implements VariableRecorder, VariableRepository {
+  final _decoratedElementTypes = <Element, DecoratedType>{};
+
+  final _potentialModifications = <PotentialModification>[];
+
+  @override
+  DecoratedType decoratedElementType(Element element, {bool create: false}) =>
+      _decoratedElementTypes[element] ??= create
+          ? DecoratedType.forElement(element)
+          : throw StateError('No element found');
+
+  List<PotentialModification> getPotentialModifications() =>
+      _potentialModifications.where((m) => !m.isEmpty).toList();
+
+  @override
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
+    _potentialModifications
+        .add(ConditionalModification(source, node, conditionalDiscard));
+  }
+
+  void recordDecoratedElementType(Element element, DecoratedType type) {
+    _decoratedElementTypes[element] = type;
+  }
+
+  void recordDecoratedExpressionType(Expression node, DecoratedType type) {}
+
+  void recordDecoratedTypeAnnotation(
+      TypeAnnotation node, DecoratedTypeAnnotation type) {
+    _potentialModifications.add(type);
+  }
+
+  @override
+  void recordExpressionChecks(Expression expression, ExpressionChecks checks) {
+    _potentialModifications.add(checks);
+  }
+
+  @override
+  void recordPossiblyOptional(Source source, DefaultFormalParameter parameter,
+      ConstraintVariable variable) {
+    _potentialModifications
+        .add(PotentiallyAddRequired(source, parameter, variable));
+  }
+}
+
+/// Helper object used by [ConditionalModification] to keep track of AST nodes
+/// within the conditional expression.
+class _KeepNode {
+  final int offset;
+
+  final int end;
+
+  final bool isExpression;
+
+  factory _KeepNode(AstNode node) {
+    int offset = node.offset;
+    int end = node.end;
+    if (node is Block && node.statements.isNotEmpty) {
+      offset = node.statements.beginToken.offset;
+      end = node.statements.endToken.end;
+    }
+    return _KeepNode._(offset, end, node is Expression);
+  }
+
+  _KeepNode._(this.offset, this.end, this.isExpression);
+}
diff --git a/pkg/analysis_server/lib/src/nullability/unit_propagation.dart b/pkg/analysis_server/lib/src/nullability/unit_propagation.dart
new file mode 100644
index 0000000..1add712
--- /dev/null
+++ b/pkg/analysis_server/lib/src/nullability/unit_propagation.dart
@@ -0,0 +1,187 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Repository of constraints corresponding to the code being migrated.
+///
+/// This data structure carries information from the second pass of migration
+/// ([ConstraintGatherer]) to the third (which creates individual code
+/// modifications from each constraint).
+abstract class Constraints {
+  /// Records a new constraint equation.
+  void record(
+      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence);
+}
+
+/// Representation of a single boolean variable in the constraint solver.
+class ConstraintVariable {
+  /// A special boolean variable whose value is known to be `true`.
+  static final ConstraintVariable always = _Always();
+
+  /// A list of all constraints containing this variable on their left hand side
+  /// that may not have been satisfied yet.
+  final _dependencies = <_Clause>[];
+
+  /// The value assigned to this constraint variable by the solution currently
+  /// being computed.
+  bool _value = false;
+
+  /// If this variable represents a disjunction ("or") of several other
+  /// variables, the variables in the disjunction.  Otherwise a singleton list
+  /// containing `this`.
+  final List<ConstraintVariable> _disjunctionParts;
+
+  ConstraintVariable() : _disjunctionParts = List.filled(1, null) {
+    _disjunctionParts[0] = this;
+  }
+
+  /// Creates a [ConstraintVariable] representing a disjunction ("or") of
+  /// several other variables.
+  ///
+  /// Additional constraints will be recorded in [constraints] to ensure that
+  /// the solution will be consistent.
+  factory ConstraintVariable.or(
+      Constraints constraints, ConstraintVariable a, ConstraintVariable b) {
+    if (a == null) return b;
+    if (b == null) return a;
+    var parts = a.disjunctionParts.toList();
+    parts.addAll(b.disjunctionParts);
+    assert(parts.length > 1);
+    var result = ConstraintVariable._(parts);
+    constraints.record([a], result);
+    constraints.record([b], result);
+    return result;
+  }
+
+  ConstraintVariable._(this._disjunctionParts);
+
+  /// If this variable represents a disjunction ("or") of several other
+  /// variables, the variables in the disjunction.  Otherwise a singleton list
+  /// containing `this`.
+  Iterable<ConstraintVariable> get disjunctionParts => _disjunctionParts;
+
+  /// Indicates whether this variable represents a disjunction ("or") of several
+  /// other variables.
+  bool get isDisjunction => _disjunctionParts.length > 1;
+
+  /// The value assigned to this constraint variable by the solution currently
+  /// being computed.
+  get value => _value;
+
+  @override
+  String toString() =>
+      isDisjunction ? '(${_disjunctionParts.join(' | ')})' : super.toString();
+}
+
+/// The core of the migration tool's constraint solver.  This class implements
+/// unit propagation (see https://en.wikipedia.org/wiki/Unit_propagation),
+/// extended to support disjunctions.
+///
+/// The extension works approximately as follows: first we perform ordinary unit
+/// propagation, accumulating a list of any disjunction variables that need to
+/// be assigned a value of `true`.  Once this finishes, we heuristically choose
+/// one of these disjunction variables and ensure that it is assigned a value of
+/// `true` by setting one of its constituent variables to `true` and propagating
+/// again.  Once all disjunctions have been resolved, we have a final solution.
+class Solver extends Constraints {
+  /// Clauses that should be evaluated as part of ordinary unit propagation.
+  final _pending = <_Clause>[];
+
+  /// Disjunction variables that have been determined by unit propagation to be
+  /// `true`, but for which we have not yet propagated the `true` value to one
+  /// of the constituent variables.
+  final _pendingDisjunctions = <ConstraintVariable>[];
+
+  /// Heuristically resolves any pending disjunctions.
+  void applyHeuristics() {
+    while (_pendingDisjunctions.isNotEmpty) {
+      var disjunction = _pendingDisjunctions.removeLast();
+      if (disjunction.disjunctionParts.any((v) => v.value)) continue;
+      // TODO(paulberry): smarter heuristics
+      var choice = disjunction.disjunctionParts.first;
+      record([], choice);
+    }
+  }
+
+  @override
+  void record(Iterable<ConstraintVariable> conditions,
+      covariant ConstraintVariable consequence) {
+    var _conditions = List<ConstraintVariable>.from(conditions);
+    var clause = _Clause(_conditions, consequence);
+    int i = 0;
+    while (i < _conditions.length) {
+      ConstraintVariable variable = _conditions[i];
+      if (variable._value) {
+        int j = _conditions.length - 1;
+        _conditions[i] = _conditions[j];
+        _conditions.removeLast();
+        continue;
+      }
+      variable._dependencies.add(clause);
+      i++;
+    }
+    if (i == 0) {
+      if (!consequence._value) {
+        consequence._value = true;
+        if (consequence.isDisjunction) {
+          _pendingDisjunctions.add(consequence);
+        }
+        _pending.addAll(consequence._dependencies);
+        _propagate();
+      }
+    } else {
+      consequence._dependencies.add(clause);
+    }
+  }
+
+  /// Performs ordinary unit propagation, recording any disjunctions encountered
+  /// in [_pendingDisjunctions].
+  void _propagate() {
+    while (_pending.isNotEmpty) {
+      var clause = _pending.removeLast();
+      var conditions = clause.conditions;
+      int i = 0;
+      while (i < conditions.length) {
+        ConstraintVariable variable = conditions[i];
+        if (variable._value) {
+          int j = conditions.length - 1;
+          conditions[i] = conditions[j];
+          conditions.removeLast();
+          continue;
+        }
+        i++;
+      }
+      if (i == 0) {
+        var consequence = clause.consequence;
+        if (!consequence._value) {
+          consequence._value = true;
+          if (consequence.isDisjunction) {
+            _pendingDisjunctions.add(consequence);
+          }
+          _pending.addAll(consequence._dependencies);
+        }
+      }
+    }
+  }
+}
+
+/// The special singleton [ConstraintVariable] whose value is always `true`.
+class _Always extends ConstraintVariable {
+  _Always() {
+    _value = true;
+  }
+
+  @override
+  String toString() => 'always';
+}
+
+/// A single equation in a system of constraints.
+class _Clause {
+  /// The conditions on the left hand side of the equation.
+  final List<ConstraintVariable> conditions;
+
+  /// The single variable on the right hand side of the equation.
+  final ConstraintVariable consequence;
+
+  _Clause(this.conditions, this.consequence);
+}
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/arglist_contributor.dart
index 85c9fa6..4c4b692 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
@@ -8,11 +8,11 @@
     hide Element, ElementKind;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
-import 'package:analysis_server/src/utilities/documentation.dart';
 import 'package:analysis_server/src/utilities/flutter.dart' as flutter;
 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/util/comment.dart';
 
 /**
  * Determine the number of arguments.
@@ -32,52 +32,6 @@
 }
 
 /**
- * If the containing [node] is an argument list
- * or named expression in an argument list
- * then return the simple identifier for the method, constructor, or annotation
- * to which the argument list is associated
- */
-SimpleIdentifier _getTargetId(AstNode node) {
-  if (node is NamedExpression) {
-    return _getTargetId(node.parent);
-  }
-  if (node is ArgumentList) {
-    AstNode parent = node.parent;
-    if (parent is MethodInvocation) {
-      return parent.methodName;
-    }
-    if (parent is InstanceCreationExpression) {
-      ConstructorName constructorName = parent.constructorName;
-      if (constructorName != null) {
-        if (constructorName.name != null) {
-          return constructorName.name;
-        }
-        Identifier typeName = constructorName.type.name;
-        if (typeName is SimpleIdentifier) {
-          return typeName;
-        }
-        if (typeName is PrefixedIdentifier) {
-          return typeName.identifier;
-        }
-      }
-    }
-    if (parent is Annotation) {
-      SimpleIdentifier name = parent.constructorName;
-      if (name == null) {
-        Identifier parentName = parent.name;
-        if (parentName is SimpleIdentifier) {
-          return parentName;
-        } else if (parentName is PrefixedIdentifier) {
-          return parentName.identifier;
-        }
-      }
-      return name;
-    }
-  }
-  return null;
-}
-
-/**
  * Determine if the completion target is at the end of the list of arguments.
  */
 bool _isAppendingToArgList(DartCompletionRequest request) {
@@ -193,35 +147,13 @@
     this.request = request;
     this.suggestions = <CompletionSuggestion>[];
 
-    // Determine if the target is in an argument list
-    // for a method or a constructor or an annotation
-    SimpleIdentifier targetId = _getTargetId(request.target.containingNode);
-    if (targetId == null) {
-      return const <CompletionSuggestion>[];
-    }
-    Element elem = targetId.staticElement;
-    if (elem == null) {
+    var executable = request.target.executableElement;
+    if (executable == null) {
       return const <CompletionSuggestion>[];
     }
 
-    // Generate argument list suggestion based upon the type of element
-    if (elem is ClassElement) {
-      _addSuggestions(elem.unnamedConstructor?.parameters);
-      return suggestions;
-    }
-    if (elem is ConstructorElement) {
-      _addSuggestions(elem.parameters);
-      return suggestions;
-    }
-    if (elem is FunctionElement) {
-      _addSuggestions(elem.parameters);
-      return suggestions;
-    }
-    if (elem is MethodElement) {
-      _addSuggestions(elem.parameters);
-      return suggestions;
-    }
-    return const <CompletionSuggestion>[];
+    _addSuggestions(executable.parameters);
+    return suggestions;
   }
 
   void _addDefaultParamSuggestions(Iterable<ParameterElement> parameters,
@@ -342,7 +274,7 @@
   static void _setDocumentation(
       CompletionSuggestion suggestion, String comment) {
     if (comment != null) {
-      String doc = removeDartDocDelimiters(comment);
+      String doc = getDartDocPlainText(comment);
       suggestion.docComplete = doc;
       suggestion.docSummary = getDartDocSummary(doc);
     }
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 0989365..7661185 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
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/completion_core.dart'
     show AbortCompletion, CompletionContributor, CompletionRequest;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
@@ -32,13 +33,13 @@
 import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
 import 'package:analyzer/src/generated/engine.dart' hide AnalysisResult;
 import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/model.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol;
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
@@ -55,6 +56,22 @@
    */
   static DartContributionSorter contributionSorter = new CommonUsageSorter();
 
+  /// If not `null`, then instead of using [ImportedReferenceContributor],
+  /// fill this set with kinds of elements that are applicable at the
+  /// completion location, so should be suggested from available suggestion
+  /// sets.
+  final Set<protocol.ElementKind> includedSuggestionKinds;
+
+  /// If [includedSuggestionKinds] is not null, must be also not `null`, and
+  /// will be filled with tags for suggestions that should be given higher
+  /// relevance than other included suggestions.
+  final List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+
+  DartCompletionManager({
+    this.includedSuggestionKinds,
+    this.includedSuggestionRelevanceTags,
+  });
+
   @override
   Future<List<CompletionSuggestion>> computeSuggestions(
       CompletionRequest request) async {
@@ -88,7 +105,6 @@
       new ArgListContributor(),
       new CombinatorContributor(),
       new FieldFormalContributor(),
-      new ImportedReferenceContributor(),
       new InheritedReferenceContributor(),
       new KeywordContributor(),
       new LabelContributor(),
@@ -104,6 +120,14 @@
       new UriContributor(),
       new VariableNameContributor()
     ];
+
+    if (includedSuggestionKinds != null) {
+      _addIncludedSuggestionKinds(dartRequest);
+      _addIncludedSuggestionRelevanceTags(dartRequest);
+    } else {
+      contributors.add(new ImportedReferenceContributor());
+    }
+
     try {
       for (DartCompletionContributor contributor in contributors) {
         String contributorTag =
@@ -153,6 +177,79 @@
     return suggestions;
   }
 
+  void _addIncludedSuggestionKinds(DartCompletionRequestImpl request) {
+    var opType = request.opType;
+
+    if (!opType.includeIdentifiers) return;
+
+    var kinds = includedSuggestionKinds;
+    if (kinds != null) {
+      if (opType.includeTypeNameSuggestions) {
+        kinds.add(protocol.ElementKind.CLASS);
+        kinds.add(protocol.ElementKind.CLASS_TYPE_ALIAS);
+        kinds.add(protocol.ElementKind.ENUM);
+        kinds.add(protocol.ElementKind.FUNCTION_TYPE_ALIAS);
+        kinds.add(protocol.ElementKind.MIXIN);
+      }
+      if (opType.includeReturnValueSuggestions) {
+        kinds.add(protocol.ElementKind.ENUM_CONSTANT);
+        kinds.add(protocol.ElementKind.FUNCTION);
+        kinds.add(protocol.ElementKind.TOP_LEVEL_VARIABLE);
+      }
+    }
+  }
+
+  void _addIncludedSuggestionRelevanceTags(DartCompletionRequestImpl request) {
+    var target = request.target;
+
+    void addTypeTag(DartType type) {
+      if (type is InterfaceType) {
+        var element = type.element;
+        var tag = '${element.librarySource.uri}::${element.name}';
+        if (element.isEnum) {
+          includedSuggestionRelevanceTags.add(
+            IncludedSuggestionRelevanceTag(
+              tag,
+              DART_RELEVANCE_BOOST_AVAILABLE_ENUM,
+            ),
+          );
+        } else {
+          includedSuggestionRelevanceTags.add(
+            IncludedSuggestionRelevanceTag(
+              tag,
+              DART_RELEVANCE_BOOST_AVAILABLE_DECLARATION,
+            ),
+          );
+        }
+      }
+    }
+
+    var parameter = target.parameterElement;
+    if (parameter != null) {
+      addTypeTag(parameter.type);
+    }
+
+    var containingNode = target.containingNode;
+
+    if (containingNode is AssignmentExpression &&
+        containingNode.operator.type == TokenType.EQ &&
+        target.offset >= containingNode.operator.end) {
+      addTypeTag(containingNode.leftHandSide.staticType);
+    }
+
+    if (containingNode is ListLiteral &&
+        target.offset >= containingNode.leftBracket.end &&
+        target.offset <= containingNode.rightBracket.offset) {
+      var type = containingNode.staticType;
+      if (type is InterfaceType) {
+        var typeArguments = type.typeArguments;
+        if (typeArguments.isNotEmpty) {
+          addTypeTag(typeArguments[0]);
+        }
+      }
+    }
+  }
+
   static List<String> _ensureList(Map<String, List<String>> map, String key) {
     List<String> list = map[key];
     if (list == null) {
@@ -303,8 +400,7 @@
    * based on the given [request]. This method will throw [AbortCompletion]
    * if the completion request has been aborted.
    */
-  static Future<DartCompletionRequest> from(CompletionRequest request,
-      {ResultDescriptor resultDescriptor}) async {
+  static Future<DartCompletionRequest> from(CompletionRequest request) async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
     request.checkAborted();
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 c335b79..b1d8459 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
@@ -11,12 +11,12 @@
     show DartCompletionRequestImpl;
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
 import 'package:analysis_server/src/services/correction/strings.dart';
-import 'package:analysis_server/src/utilities/documentation.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/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
+import 'package:analyzer/src/util/comment.dart';
 import 'package:analyzer_plugin/protocol/protocol_common.dart' as protocol
     show Element, ElementKind;
 import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
@@ -317,14 +317,30 @@
     }
   }
 
+  @override
+  void declaredTypeParameter(TypeParameter node) {
+    if (optype.includeTypeNameSuggestions) {
+      _addLocalSuggestion(
+        null,
+        node.name,
+        null,
+        protocol.ElementKind.TYPE_PARAMETER,
+        isDeprecated: isDeprecated(node),
+        kind: CompletionSuggestionKind.IDENTIFIER,
+        relevance: DART_RELEVANCE_TYPE_PARAMETER,
+      );
+    }
+  }
+
   void _addLocalSuggestion(Comment documentationComment, SimpleIdentifier id,
       TypeAnnotation typeName, protocol.ElementKind elemKind,
       {bool isAbstract: false,
       bool isDeprecated: false,
       ClassOrMixinDeclaration classDecl,
+      CompletionSuggestionKind kind,
       FormalParameterList param,
       int relevance: DART_RELEVANCE_DEFAULT}) {
-    CompletionSuggestionKind kind = targetIsFunctionalArgument
+    kind ??= targetIsFunctionalArgument
         ? CompletionSuggestionKind.IDENTIFIER
         : optype.suggestKind;
     CompletionSuggestion suggestion = createLocalSuggestion(
@@ -526,7 +542,7 @@
           .map((Token t) => t.toString())
           .join('\n')
           .replaceAll('\r\n', '\n');
-      String doc = removeDartDocDelimiters(text);
+      String doc = getDartDocPlainText(text);
       suggestion.docComplete = doc;
       suggestion.docSummary = getDartDocSummary(doc);
     }
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
index 22692c1..e2d567d 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/override_contributor.dart
@@ -83,7 +83,13 @@
       });
     });
 
-    String replacement = builder.sourceChange.edits[0].edits[0].replacement;
+    var fileEdits = builder.sourceChange.edits;
+    if (fileEdits.length != 1) return null;
+
+    var sourceEdits = fileEdits[0].edits;
+    if (sourceEdits.length != 1) return null;
+
+    String replacement = sourceEdits[0].replacement;
     String completion = replacement.trim();
     String overrideAnnotation = '@override';
     if (_hasOverride(request.target.containingNode) &&
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 5f66d87..c7186e2 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
@@ -7,11 +7,11 @@
     hide Element, ElementKind;
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/utilities.dart';
-import 'package:analysis_server/src/utilities/documentation.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/src/generated/source.dart';
+import 'package:analyzer/src/util/comment.dart';
 import 'package:path/path.dart' as path;
 
 /**
@@ -46,7 +46,7 @@
       false);
 
   // Attach docs.
-  String doc = removeDartDocDelimiters(element.documentationComment);
+  String doc = getDartDocPlainText(element.documentationComment);
   suggestion.docComplete = doc;
   suggestion.docSummary = getDartDocSummary(doc);
 
diff --git a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
index f3974ce..63faf71 100644
--- a/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
+++ b/pkg/analysis_server/lib/src/services/completion/dart/type_member_contributor.dart
@@ -423,6 +423,7 @@
       if (nextType.superclass != null) {
         typesToVisit.add(nextType.superclass);
       }
+      typesToVisit.addAll(nextType.superclassConstraints);
       typesToVisit.addAll(nextType.mixins);
     }
     return result;
diff --git a/pkg/analysis_server/lib/src/services/correction/assist.dart b/pkg/analysis_server/lib/src/services/correction/assist.dart
index 9f3595e..7bc89e0 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist.dart
@@ -32,7 +32,11 @@
  */
 class DartAssistKind {
   static const ADD_TYPE_ANNOTATION = const AssistKind(
-      'dart.assist.addTypeAnnotation', 30, "Add type annotation");
+      'dart.assist.addTypeAnnotation', 30, "Add type annotation",
+      associatedErrorCodes: <String>[
+        'always_specify_types',
+        'type_annotate_public_apis'
+      ]);
   static const ASSIGN_TO_LOCAL_VARIABLE = const AssistKind(
       'dart.assist.assignToVariable', 30, "Assign value to new local variable");
   static const CONVERT_CLASS_TO_MIXIN = const AssistKind(
@@ -44,15 +48,18 @@
   static const CONVERT_DOCUMENTATION_INTO_LINE = const AssistKind(
       'dart.assist.convert.lineComment',
       30,
-      "Convert to line documentation comment");
+      "Convert to line documentation comment",
+      associatedErrorCodes: <String>['slash_for_doc_comments']);
   static const CONVERT_INTO_ASYNC_BODY = const AssistKind(
       'dart.assist.convert.bodyToAsync', 30, "Convert to async function body");
   static const CONVERT_INTO_BLOCK_BODY = const AssistKind(
       'dart.assist.convert.bodyToBlock', 30, "Convert to block body");
   static const CONVERT_INTO_EXPRESSION_BODY = const AssistKind(
-      'dart.assist.convert.bodyToExpression', 30, "Convert to expression body");
+      'dart.assist.convert.bodyToExpression', 30, "Convert to expression body",
+      associatedErrorCodes: <String>['prefer_expression_function_bodies']);
   static const CONVERT_INTO_FINAL_FIELD = const AssistKind(
-      'dart.assist.convert.getterToFinalField', 30, "Convert to final field");
+      'dart.assist.convert.getterToFinalField', 30, "Convert to final field",
+      associatedErrorCodes: <String>['prefer_final_fields']);
   static const CONVERT_INTO_FOR_INDEX = const AssistKind(
       'dart.assist.convert.forEachToForIndex', 30, "Convert to for-index loop");
   static const CONVERT_INTO_GENERIC_FUNCTION_SYNTAX = const AssistKind(
@@ -64,7 +71,8 @@
   static const CONVERT_INTO_IS_NOT =
       const AssistKind('dart.assist.convert.isNot', 30, "Convert to is!");
   static const CONVERT_INTO_IS_NOT_EMPTY = const AssistKind(
-      'dart.assist.convert.isNotEmpty', 30, "Convert to 'isNotEmpty'");
+      'dart.assist.convert.isNotEmpty', 30, "Convert to 'isNotEmpty'",
+      associatedErrorCodes: <String>['prefer_is_not_empty']);
   static const CONVERT_PART_OF_TO_URI = const AssistKind(
       'dart.assist.convert.partOfToPartUri', 30, "Convert to use a URI");
   static const CONVERT_TO_DOUBLE_QUOTED_STRING = const AssistKind(
@@ -75,8 +83,19 @@
       'dart.assist.convert.toConstructorFieldParameter',
       30,
       "Convert to field formal parameter");
+  static const CONVERT_TO_IF_ELEMENT = const AssistKind(
+      'dart.assist.convertToIfElement', 30, "Convert to an 'if' element");
   static const CONVERT_TO_INT_LITERAL = const AssistKind(
-      'dart.assist.convert.toIntLiteral', 30, "Convert to an int literal");
+      'dart.assist.convert.toIntLiteral', 30, "Convert to an int literal",
+      associatedErrorCodes: <String>['prefer_int_literals']);
+  static const CONVERT_TO_LIST_LITERAL = const AssistKind(
+      'dart.assist.convert.toListLiteral', 30, "Convert to list literal",
+      // todo (brianwilkerson): unify w/ fix
+      associatedErrorCodes: <String>['prefer_collection_literals']);
+  static const CONVERT_TO_MAP_LITERAL = const AssistKind(
+      'dart.assist.convert.toMapLiteral', 30, "Convert to map literal",
+      // todo (brianwilkerson): unify w/ fix
+      associatedErrorCodes: <String>['prefer_collection_literals']);
   static const CONVERT_TO_MULTILINE_STRING = const AssistKind(
       'dart.assist.convert.toMultilineString',
       30,
@@ -85,10 +104,17 @@
       'dart.assist.convert.toConstructorNormalParameter',
       30,
       "Convert to normal parameter");
+  static const CONVERT_TO_SET_LITERAL = const AssistKind(
+      'dart.assist.convert.toSetLiteral', 30, "Convert to set literal",
+      // todo (brianwilkerson): unify w/ fix
+      associatedErrorCodes: <String>['prefer_collection_literals']);
   static const CONVERT_TO_SINGLE_QUOTED_STRING = const AssistKind(
       'dart.assist.convert.toSingleQuotedString',
       30,
-      "Convert to single quoted string");
+      "Convert to single quoted string",
+      associatedErrorCodes: <String>['prefer_single_quotes']);
+  static const CONVERT_TO_SPREAD = const AssistKind(
+      'dart.assist.convertToSpread', 30, "Convert to a spread");
   static const ENCAPSULATE_FIELD =
       const AssistKind('dart.assist.encapsulateField', 30, "Encapsulate field");
   static const EXCHANGE_OPERANDS =
@@ -144,7 +170,11 @@
   static const JOIN_VARIABLE_DECLARATION = const AssistKind(
       'dart.assist.joinVariableDeclaration', 30, "Join variable declaration");
   static const REMOVE_TYPE_ANNOTATION = const AssistKind(
-      'dart.assist.removeTypeAnnotation', 29, "Remove type annotation");
+      'dart.assist.removeTypeAnnotation', 29, "Remove type annotation",
+      associatedErrorCodes: <String>[
+        'avoid_return_types_on_setters',
+        'type_init_formals'
+      ]);
   static const REPLACE_CONDITIONAL_WITH_IF_ELSE = const AssistKind(
       'dart.assist.convert.conditionalToIfElse',
       30,
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 001180e..18b210c 100644
--- a/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/assist_internal.dart
@@ -20,9 +20,11 @@
 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/experiments.dart';
 import 'package:analyzer/src/dart/analysis/session_helper.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
+import 'package:analyzer/src/generated/engine.dart' show AnalysisOptionsImpl;
 import 'package:analyzer/src/generated/java_core.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart';
@@ -71,6 +73,13 @@
    */
   String get eol => utils.endOfLine;
 
+  /**
+   * Return the status of the known experiments.
+   */
+  ExperimentStatus get experimentStatus =>
+      (session.analysisContext.analysisOptions as AnalysisOptionsImpl)
+          .experimentStatus;
+
   Future<List<Assist>> compute() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -83,22 +92,26 @@
     await _addProposal_addTypeAnnotation_VariableDeclaration();
     await _addProposal_assignToLocalVariable();
     await _addProposal_convertClassToMixin();
-    await _addProposal_convertIntoFinalField();
-    await _addProposal_convertIntoGetter();
     await _addProposal_convertDocumentationIntoBlock();
     await _addProposal_convertDocumentationIntoLine();
+    await _addProposal_convertIntoFinalField();
+    await _addProposal_convertIntoGetter();
+    await _addProposal_convertListConstructorToListLiteral();
+    await _addProposal_convertListToSetToSetLiteral();
+    await _addProposal_convertMapConstructorToMapLiteral();
+    await _addProposal_convertPartOfToUri();
+    await _addProposal_convertSetConstructorToSetLiteral();
     await _addProposal_convertToAsyncFunctionBody();
     await _addProposal_convertToBlockFunctionBody();
     await _addProposal_convertToDoubleQuotedString();
     await _addProposal_convertToExpressionFunctionBody();
-    await _addProposal_convertPartOfToUri();
+    await _addProposal_convertToFieldParameter();
     await _addProposal_convertToForIndexLoop();
     await _addProposal_convertToGenericFunctionSyntax();
     await _addProposal_convertToIntLiteral();
     await _addProposal_convertToIsNot_onIs();
     await _addProposal_convertToIsNot_onNot();
     await _addProposal_convertToIsNotEmpty();
-    await _addProposal_convertToFieldParameter();
     await _addProposal_convertToMultilineString();
     await _addProposal_convertToNormalParameter();
     await _addProposal_convertToSingleQuotedString();
@@ -130,6 +143,14 @@
     await _addProposal_splitVariableDeclaration();
     await _addProposal_surroundWith();
 
+    if (experimentStatus.control_flow_collections) {
+      await _addProposal_convertConditionalExpressionToIfElement();
+      await _addProposal_convertMapFromIterableToIfLiteral();
+    }
+    if (experimentStatus.spread_collections) {
+      await _addProposal_convertAddAllToSpread();
+    }
+
     return assists;
   }
 
@@ -403,6 +424,63 @@
     }
   }
 
+  Future<void> _addProposal_convertAddAllToSpread() async {
+    AstNode node = this.node;
+    if (node is! SimpleIdentifier || node.parent is! MethodInvocation) {
+      _coverageMarker();
+      return;
+    }
+    SimpleIdentifier name = node;
+    MethodInvocation invocation = node.parent;
+    if (name != invocation.methodName ||
+        name.name != 'addAll' ||
+        !invocation.isCascaded ||
+        invocation.argumentList.arguments.length != 1) {
+      _coverageMarker();
+      return;
+    }
+    CascadeExpression cascade = invocation.thisOrAncestorOfType();
+    NodeList<Expression> sections = cascade.cascadeSections;
+    Expression target = cascade.target;
+    if (target is! ListLiteral2 || sections[0] != invocation) {
+      _coverageMarker();
+      return;
+    }
+
+    bool isEmptyListLiteral(Expression expression) =>
+        expression is ListLiteral2 && expression.elements.isEmpty;
+
+    ListLiteral2 list = target;
+    Expression argument = invocation.argumentList.arguments[0];
+    String elementText;
+    if (argument is BinaryExpression &&
+        argument.operator.type == TokenType.QUESTION_QUESTION) {
+      Expression right = argument.rightOperand;
+      if (isEmptyListLiteral(right)) {
+        // ..addAll(things ?? const [])
+        // ..addAll(things ?? [])
+        elementText = '...?${utils.getNodeText(argument.leftOperand)}';
+      }
+    } else if (experimentStatus.control_flow_collections &&
+        argument is ConditionalExpression) {
+      Expression elseExpression = argument.elseExpression;
+      if (isEmptyListLiteral(elseExpression)) {
+        // ..addAll(condition ? things : const [])
+        // ..addAll(condition ? things : [])
+        String conditionText = utils.getNodeText(argument.condition);
+        String thenText = utils.getNodeText(argument.thenExpression);
+        elementText = 'if ($conditionText) ...$thenText';
+      }
+    }
+    elementText ??= '...${utils.getNodeText(argument)}';
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addSimpleInsertion(list.elements.last.end, ', $elementText');
+      builder.addDeletion(range.node(invocation));
+    });
+    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_SPREAD);
+  }
+
   Future<void> _addProposal_convertClassToMixin() async {
     ClassDeclaration classDeclaration =
         node.thisOrAncestorOfType<ClassDeclaration>();
@@ -459,6 +537,42 @@
     _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_CLASS_TO_MIXIN);
   }
 
+  Future<void> _addProposal_convertConditionalExpressionToIfElement() async {
+    AstNode node = this.node;
+    if (node is! ConditionalExpression) {
+      _coverageMarker();
+      return;
+    }
+    AstNode nodeToReplace = node;
+    AstNode parent = node.parent;
+    while (parent is ParenthesizedExpression) {
+      nodeToReplace = parent;
+      parent = parent.parent;
+    }
+    // TODO(brianwilkerson) Consider adding support for map literals.
+    if (parent is ListLiteral2 || parent is SetLiteral2) {
+      ConditionalExpression conditional = node;
+      Expression condition = conditional.condition.unParenthesized;
+      Expression thenExpression = conditional.thenExpression.unParenthesized;
+      Expression elseExpression = conditional.elseExpression.unParenthesized;
+
+      DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+      await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+        builder.addReplacement(range.node(nodeToReplace),
+            (DartEditBuilder builder) {
+          builder.write('if (');
+          builder.write(utils.getNodeText(condition));
+          builder.write(') ');
+          builder.write(utils.getNodeText(thenExpression));
+          builder.write(' else ');
+          builder.write(utils.getNodeText(elseExpression));
+        });
+      });
+      _addAssistFromBuilder(
+          changeBuilder, DartAssistKind.CONVERT_TO_IF_ELEMENT);
+    }
+  }
+
   Future<void> _addProposal_convertDocumentationIntoBlock() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -535,11 +649,11 @@
           _coverageMarker();
           return;
         }
-        line = line.substring(expectedPrefix.length).trim();
+        line = line.substring(expectedPrefix.length);
         if (line.isEmpty) {
           newLines.add('$linePrefix///');
         } else {
-          newLines.add('$linePrefix/// $line');
+          newLines.add('$linePrefix///$line');
         }
         linePrefix = eol + prefix;
       }
@@ -679,6 +793,289 @@
     _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_INTO_GETTER);
   }
 
+  Future<void> _addProposal_convertListConstructorToListLiteral() async {
+    //
+    // Ensure that this is the default constructor defined on `List`.
+    //
+    InstanceCreationExpression creation = node.thisOrAncestorOfType();
+    if (creation == null ||
+        node.offset > creation.argumentList.offset ||
+        creation.staticType.element != typeProvider.listType.element ||
+        creation.constructorName.name != null ||
+        creation.argumentList.arguments.length > 0) {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    TypeArgumentList constructorTypeArguments =
+        creation.constructorName.type.typeArguments;
+    //
+    // Build the change and return the assist.
+    //
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(creation), (DartEditBuilder builder) {
+        if (constructorTypeArguments != null) {
+          builder.write(_getNodeText(constructorTypeArguments));
+        }
+        builder.write('[]');
+      });
+    });
+    _addAssistFromBuilder(
+        changeBuilder, DartAssistKind.CONVERT_TO_LIST_LITERAL);
+  }
+
+  Future<void> _addProposal_convertListToSetToSetLiteral() async {
+    //
+    // Ensure that this is an invocation of `toSet` on a list literal.
+    //
+    if (node is! SimpleIdentifier) {
+      _coverageMarker();
+      return;
+    }
+    AstNode parent = node.parent;
+    if (parent is! MethodInvocation) {
+      _coverageMarker();
+      return;
+    }
+    MethodInvocation invocation = parent as MethodInvocation;
+    if (invocation.methodName != node ||
+        invocation.methodName.name != 'toSet') {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    Expression target = invocation.target;
+    bool hasTypeArgs;
+    SourceRange openRange;
+    SourceRange closeRange;
+    if (target is ListLiteral) {
+      hasTypeArgs = target.typeArguments != null;
+      openRange = range.token(target.leftBracket);
+      closeRange = range.startEnd(target.rightBracket, invocation);
+    } else if (target is ListLiteral2) {
+      hasTypeArgs = target.typeArguments != null;
+      openRange = range.token(target.leftBracket);
+      closeRange = range.startEnd(target.rightBracket, invocation);
+    } else {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Build the change and return the assist.
+    //
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      if (hasTypeArgs || _listHasUnambiguousElement(target)) {
+        builder.addSimpleReplacement(openRange, '{');
+      } else {
+        builder.addSimpleReplacement(openRange, '<dynamic>{');
+      }
+      builder.addSimpleReplacement(closeRange, '}');
+    });
+    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_SET_LITERAL);
+  }
+
+  Future<void> _addProposal_convertMapConstructorToMapLiteral() async {
+    bool isMapClass(Element element) =>
+        element is ClassElement &&
+        (element == typeProvider.mapType.element ||
+            (element.name == 'LinkedHashMap' &&
+                element.library.name == 'dart.collection'));
+    //
+    // Ensure that this is the default constructor defined on either `Map` or
+    // `LinkedHashMap`.
+    //
+    InstanceCreationExpression creation = node.thisOrAncestorOfType();
+    if (creation == null ||
+        node.offset > creation.argumentList.offset ||
+        creation.constructorName.name != null ||
+        creation.argumentList.arguments.isNotEmpty ||
+        !isMapClass(creation.staticType.element)) {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    TypeArgumentList constructorTypeArguments =
+        creation.constructorName.type.typeArguments;
+    //
+    // Build the change and return the assist.
+    //
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(creation), (DartEditBuilder builder) {
+        if (constructorTypeArguments != null) {
+          builder.write(_getNodeText(constructorTypeArguments));
+        }
+        builder.write('{}');
+      });
+    });
+    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_MAP_LITERAL);
+  }
+
+  Future<void> _addProposal_convertMapFromIterableToIfLiteral() async {
+    //
+    // Ensure that the selection is inside an invocation of Map.fromIterable.
+    //
+    InstanceCreationExpression creation =
+        node.thisOrAncestorOfType<InstanceCreationExpression>();
+    if (creation == null) {
+      _coverageMarker();
+      return;
+    }
+    ConstructorElement element = creation.staticElement;
+    if (element.name != 'fromIterable' ||
+        element.enclosingElement != typeProvider.mapType.element) {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Ensure that the arguments have the right form.
+    //
+    NodeList<Expression> arguments = creation.argumentList.arguments;
+    if (arguments.length != 3) {
+      _coverageMarker();
+      return;
+    }
+    Expression iterator = arguments[0].unParenthesized;
+    Expression secondArg = arguments[1];
+    Expression thirdArg = arguments[2];
+
+    Expression extractBody(FunctionExpression expression) {
+      FunctionBody body = expression.body;
+      if (body is ExpressionFunctionBody) {
+        return body.expression;
+      } else if (body is BlockFunctionBody) {
+        NodeList<Statement> statements = body.block.statements;
+        if (statements.length == 1) {
+          Statement statement = statements[0];
+          if (statement is ReturnStatement) {
+            return statement.expression;
+          }
+        }
+      }
+      return null;
+    }
+
+    FunctionExpression extractClosure(String name, Expression argument) {
+      if (argument is NamedExpression && argument.name.label.name == name) {
+        Expression expression = argument.expression.unParenthesized;
+        if (expression is FunctionExpression) {
+          NodeList<FormalParameter> parameters =
+              expression.parameters.parameters;
+          if (parameters.length == 1 && parameters[0].isRequired) {
+            if (extractBody(expression) != null) {
+              return expression;
+            }
+          }
+        }
+      }
+      return null;
+    }
+
+    FunctionExpression keyClosure =
+        extractClosure('key', secondArg) ?? extractClosure('key', thirdArg);
+    FunctionExpression valueClosure =
+        extractClosure('value', thirdArg) ?? extractClosure('value', secondArg);
+    if (keyClosure == null || valueClosure == null) {
+      _coverageMarker();
+      return;
+    }
+    //
+    // Compute the loop variable name and convert the key and value closures if
+    // necessary.
+    //
+    SimpleFormalParameter keyParameter = keyClosure.parameters.parameters[0];
+    String keyParameterName = keyParameter.identifier.name;
+    SimpleFormalParameter valueParameter =
+        valueClosure.parameters.parameters[0];
+    String valueParameterName = valueParameter.identifier.name;
+    Expression keyBody = extractBody(keyClosure);
+    String keyExpressionText = utils.getNodeText(keyBody);
+    Expression valueBody = extractBody(valueClosure);
+    String valueExpressionText = utils.getNodeText(valueBody);
+
+    String loopVariableName;
+    if (keyParameterName == valueParameterName) {
+      loopVariableName = keyParameterName;
+    } else {
+      _ParameterReferenceFinder keyFinder =
+          new _ParameterReferenceFinder(keyParameter.declaredElement);
+      keyBody.accept(keyFinder);
+
+      _ParameterReferenceFinder valueFinder =
+          new _ParameterReferenceFinder(valueParameter.declaredElement);
+      valueBody.accept(valueFinder);
+
+      String computeUnusedVariableName() {
+        String candidate = 'e';
+        var index = 1;
+        while (keyFinder.referencesName(candidate) ||
+            valueFinder.referencesName(candidate)) {
+          candidate = 'e${index++}';
+        }
+        return candidate;
+      }
+
+      if (valueFinder.isParameterUnreferenced) {
+        if (valueFinder.referencesName(keyParameterName)) {
+          // The name of the value parameter is not used, but we can't use the
+          // name of the key parameter because doing so would hide a variable
+          // referenced in the value expression.
+          loopVariableName = computeUnusedVariableName();
+          keyExpressionText = keyFinder.replaceName(
+              keyExpressionText, loopVariableName, keyBody.offset);
+        } else {
+          loopVariableName = keyParameterName;
+        }
+      } else if (keyFinder.isParameterUnreferenced) {
+        if (keyFinder.referencesName(valueParameterName)) {
+          // The name of the key parameter is not used, but we can't use the
+          // name of the value parameter because doing so would hide a variable
+          // referenced in the key expression.
+          loopVariableName = computeUnusedVariableName();
+          valueExpressionText = valueFinder.replaceName(
+              valueExpressionText, loopVariableName, valueBody.offset);
+        } else {
+          loopVariableName = valueParameterName;
+        }
+      } else {
+        // The names are different and both are used. We need to find a name
+        // that would not change the resolution of any other identifiers in
+        // either the key or value expressions.
+        loopVariableName = computeUnusedVariableName();
+        keyExpressionText = keyFinder.replaceName(
+            keyExpressionText, loopVariableName, keyBody.offset);
+        valueExpressionText = valueFinder.replaceName(
+            valueExpressionText, loopVariableName, valueBody.offset);
+      }
+    }
+    //
+    // Construct the edit.
+    //
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(creation), (DartEditBuilder builder) {
+        builder.write('{ for (var ');
+        builder.write(loopVariableName);
+        builder.write(' in ');
+        builder.write(utils.getNodeText(iterator));
+        builder.write(') ');
+        builder.write(keyExpressionText);
+        builder.write(' : ');
+        builder.write(valueExpressionText);
+        builder.write(' }');
+      });
+    });
+    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_IF_ELEMENT);
+  }
+
   Future<void> _addProposal_convertPartOfToUri() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -698,11 +1095,111 @@
     _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_PART_OF_TO_URI);
   }
 
+  Future<void> _addProposal_convertSetConstructorToSetLiteral() async {
+    //
+    // Ensure that this is one of the constructors defined on `Set`.
+    //
+    InstanceCreationExpression creation = node.thisOrAncestorOfType();
+    if (creation == null ||
+        node.offset > creation.argumentList.offset ||
+        creation.staticType.element != typeProvider.setType.element) {
+      // TODO(brianwilkerson) Consider also accepting uses of LinkedHashSet.
+      _coverageMarker();
+      return;
+    }
+    //
+    // Extract the information needed to build the edit.
+    //
+    SimpleIdentifier name = creation.constructorName.name;
+    TypeArgumentList constructorTypeArguments =
+        creation.constructorName.type.typeArguments;
+    TypeArgumentList elementTypeArguments;
+    SourceRange elementsRange;
+    if (name == null) {
+      // Handle an invocation of the default constructor `Set()`.
+    } else if (name.name == 'from' || name.name == 'of') {
+      // Handle an invocation of the constructor `Set.from()` or `Set.of()`.
+      NodeList<Expression> arguments = creation.argumentList.arguments;
+      if (arguments.length != 1) {
+        _coverageMarker();
+        return;
+      }
+      if (arguments[0] is ListLiteral) {
+        ListLiteral elements = arguments[0] as ListLiteral;
+        elementTypeArguments = elements.typeArguments;
+        elementsRange =
+            range.endStart(elements.leftBracket, elements.rightBracket);
+      } else if (arguments[0] is ListLiteral2) {
+        ListLiteral2 elements = arguments[0] as ListLiteral2;
+        elementTypeArguments = elements.typeArguments;
+        elementsRange =
+            range.endStart(elements.leftBracket, elements.rightBracket);
+      } else {
+        // TODO(brianwilkerson) Consider handling other iterables. Literal sets
+        //  could be treated like lists, and arbitrary iterables by using a
+        //  spread.
+        _coverageMarker();
+        return;
+      }
+    } else {
+      // Invocation of an unhandled constructor.
+      _coverageMarker();
+      return;
+    }
+    new Map();
+    //
+    // Determine whether type arguments are strictly required in cases where no
+    // type arguments were explicitly provided.
+    //
+    bool hasUnambiguousElement() {
+      NodeList<Expression> arguments = creation.argumentList.arguments;
+      if (arguments == null || arguments.isEmpty) {
+        return false;
+      }
+      return _listHasUnambiguousElement(arguments[0]);
+    }
+
+    bool setWouldBeInferred() {
+      AstNode parent = creation.parent;
+      if (parent is VariableDeclaration) {
+        AstNode parent2 = parent.parent;
+        if (parent2 is VariableDeclarationList &&
+            parent2.type?.type?.element == typeProvider.setType.element) {
+          return true;
+        }
+      }
+      return hasUnambiguousElement();
+    }
+
+    //
+    // Build the change and return the assist.
+    //
+    DartChangeBuilder changeBuilder = _newDartChangeBuilder();
+    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
+      builder.addReplacement(range.node(creation), (DartEditBuilder builder) {
+        if (constructorTypeArguments != null) {
+          builder.write(_getNodeText(constructorTypeArguments));
+        } else if (elementTypeArguments != null) {
+          builder.write(_getNodeText(elementTypeArguments));
+        } else if (!setWouldBeInferred()) {
+          builder.write('<dynamic>');
+        }
+        builder.write('{');
+        if (elementsRange != null) {
+          builder.write(_getRangeText(elementsRange));
+        }
+        builder.write('}');
+      });
+    });
+    _addAssistFromBuilder(changeBuilder, DartAssistKind.CONVERT_TO_SET_LITERAL);
+  }
+
   Future<void> _addProposal_convertToAsyncFunctionBody() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
     FunctionBody body = getEnclosingFunctionBody();
-    if (body == null || body.isAsynchronous || body.isGenerator) {
+    if (body == null ||
+        body is EmptyFunctionBody ||
+        body.isAsynchronous ||
+        body.isGenerator) {
       _coverageMarker();
       return;
     }
@@ -1226,6 +1723,36 @@
         changeBuilder, DartAssistKind.CONVERT_INTO_IS_NOT_EMPTY);
   }
 
+  Future<void> _addProposal_convertToMultilineString() async {
+    var node = this.node;
+    if (node is InterpolationElement) {
+      node = (node as InterpolationElement).parent;
+    }
+    if (node is SingleStringLiteral) {
+      SingleStringLiteral literal = node;
+      if (!literal.isMultiline) {
+        var changeBuilder = _newDartChangeBuilder();
+        await changeBuilder.addFileEdit(file, (builder) {
+          var newQuote = literal.isSingleQuoted ? "'''" : '"""';
+          builder.addReplacement(
+            SourceRange(literal.offset + (literal.isRaw ? 1 : 0), 1),
+            (builder) {
+              builder.writeln(newQuote);
+            },
+          );
+          builder.addSimpleReplacement(
+            SourceRange(literal.end - 1, 1),
+            newQuote,
+          );
+        });
+        _addAssistFromBuilder(
+          changeBuilder,
+          DartAssistKind.CONVERT_TO_MULTILINE_STRING,
+        );
+      }
+    }
+  }
+
   Future<void> _addProposal_convertToNormalParameter() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -1267,36 +1794,6 @@
     }
   }
 
-  Future<void> _addProposal_convertToMultilineString() async {
-    var node = this.node;
-    if (node is InterpolationElement) {
-      node = (node as InterpolationElement).parent;
-    }
-    if (node is SingleStringLiteral) {
-      SingleStringLiteral literal = node;
-      if (!literal.isMultiline) {
-        var changeBuilder = _newDartChangeBuilder();
-        await changeBuilder.addFileEdit(file, (builder) {
-          var newQuote = literal.isSingleQuoted ? "'''" : '"""';
-          builder.addReplacement(
-            SourceRange(literal.offset + (literal.isRaw ? 1 : 0), 1),
-            (builder) {
-              builder.writeln(newQuote);
-            },
-          );
-          builder.addSimpleReplacement(
-            SourceRange(literal.end - 1, 1),
-            newQuote,
-          );
-        });
-        _addAssistFromBuilder(
-          changeBuilder,
-          DartAssistKind.CONVERT_TO_MULTILINE_STRING,
-        );
-      }
-    }
-  }
-
   Future<void> _addProposal_convertToSingleQuotedString() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
@@ -1532,7 +2029,7 @@
     }
 
     String widgetName = widgetClassElement.displayName;
-    String stateName = widgetName + 'State';
+    String stateName = '_${widgetName}State';
 
     // Find fields assigned in constructors.
     var fieldsAssignedInConstructors = new Set<FieldElement>();
@@ -1655,9 +2152,7 @@
                 builder.writeln();
               }
               builder.writeln('  @override');
-              builder.writeln('  $stateName createState() {');
-              builder.writeln('    return $stateName();');
-              builder.writeln('  }');
+              builder.writeln('  $stateName createState() => $stateName();');
               if (hasEmptyLineAfterCreateState) {
                 builder.writeln();
               }
@@ -3391,6 +3886,36 @@
     return utils.getRangeText(range);
   }
 
+  /// Return `true` if the [element] is sufficient to lexically make the
+  /// enclosing literal a set literal rather than a map.
+  bool _isUnambiguousElement(CollectionElement element) {
+    if (element is ForElement) {
+      return _isUnambiguousElement(element.body);
+    } else if (element is IfElement) {
+      return _isUnambiguousElement(element.thenElement) ||
+          _isUnambiguousElement(element.elseElement);
+    } else if (element is Expression) {
+      return true;
+    }
+    return false;
+  }
+
+  /// Return `true` if the given [node] is a list literal whose elements, if
+  /// placed inside curly braces, would lexically make the resulting literal a
+  /// set literal rather than a map literal.
+  bool _listHasUnambiguousElement(AstNode node) {
+    if (node is ListLiteral && node.elements.length > 0) {
+      return true;
+    } else if (node is ListLiteral2) {
+      for (CollectionElement element in node.elements) {
+        if (_isUnambiguousElement(element)) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
   DartChangeBuilder _newDartChangeBuilder() {
     return new DartChangeBuilderImpl.forWorkspace(context.workspace);
   }
@@ -3539,6 +4064,70 @@
   }
 }
 
+/**
+ * A visitor that can be used to find references to a parameter.
+ */
+class _ParameterReferenceFinder extends RecursiveAstVisitor<void> {
+  /**
+   * The parameter for which references are being sought, or `null` if we are
+   * just accumulating a list of referenced names.
+   */
+  final ParameterElement parameter;
+
+  /**
+   * A list of the simple identifiers that reference the [parameter].
+   */
+  final List<SimpleIdentifier> references = <SimpleIdentifier>[];
+
+  /**
+   * A collection of the names of other simple identifiers that were found. We
+   * need to know these in order to ensure that the selected loop variable does
+   * not hide a name from an enclosing scope that is already being referenced.
+   */
+  final Set<String> otherNames = new Set<String>();
+
+  /**
+   * Initialize a newly created finder to find references to the [parameter].
+   */
+  _ParameterReferenceFinder(this.parameter) : assert(parameter != null);
+
+  /**
+   * Return `true` if the parameter is unreferenced in the nodes that have been
+   * visited.
+   */
+  bool get isParameterUnreferenced => references.isEmpty;
+
+  /**
+   * Return `true` is the given name (assumed to be different than the name of
+   * the parameter) is references in the nodes that have been visited.
+   */
+  bool referencesName(String name) => otherNames.contains(name);
+
+  /**
+   * Replace all of the references to the parameter in the given [source] with
+   * the [newName]. The [offset] is the offset of the first character of the
+   * [source] relative to the start of the file.
+   */
+  String replaceName(String source, String newName, int offset) {
+    int oldLength = parameter.name.length;
+    for (int i = references.length - 1; i >= 0; i--) {
+      int oldOffset = references[i].offset - offset;
+      source = source.replaceRange(oldOffset, oldOffset + oldLength, newName);
+    }
+    return source;
+  }
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    if (node.staticElement == parameter) {
+      references.add(node);
+    } else if (!node.isQualified) {
+      // Only non-prefixed identifiers can be hidden.
+      otherNames.add(node.name);
+    }
+  }
+}
+
 class _SimpleIdentifierRecursiveAstVisitor extends RecursiveAstVisitor {
   final _SimpleIdentifierVisitor visitor;
 
diff --git a/pkg/analysis_server/lib/src/services/correction/fix.dart b/pkg/analysis_server/lib/src/services/correction/fix.dart
index 2f872621..f193dd1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix.dart
@@ -267,8 +267,6 @@
       'REPLACE_WITH_CONDITIONAL_ASSIGNMENT', 50, "Replace with ??=");
   static const REPLACE_WITH_IDENTIFIER =
       const FixKind('REPLACE_WITH_IDENTIFIER', 50, "Replace with identifier");
-  static const REPLACE_WITH_LITERAL =
-      const FixKind('REPLACE_WITH_LITERAL', 50, "Replace with literal");
   static const REPLACE_WITH_NULL_AWARE = const FixKind(
       'REPLACE_WITH_NULL_AWARE',
       50,
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 2d8e769..c6600c1 100644
--- a/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
+++ b/pkg/analysis_server/lib/src/services/correction/fix_internal.dart
@@ -584,9 +584,6 @@
       if (name == LintNames.non_constant_identifier_names) {
         await _addFix_renameToCamelCase();
       }
-      if (name == LintNames.prefer_collection_literals) {
-        await _addFix_replaceWithLiteral();
-      }
       if (name == LintNames.prefer_conditional_assignment) {
         await _addFix_replaceWithConditionalAssignment();
       }
@@ -931,9 +928,12 @@
           if (arguments.isNotEmpty) {
             builder.write(', ');
           }
-          String defaultValue =
-              getDefaultStringParameterValue(missingParameter);
-          builder.write('$missingParameterName: $defaultValue');
+
+          builder.write('$missingParameterName: ');
+
+          var defaultValue = getDefaultStringParameterValue(missingParameter);
+          builder.addSimpleLinkedEdit('VALUE', defaultValue);
+
           // Insert a trailing comma after Flutter instance creation params.
           if (!hasTrailingComma && flutter.isWidgetExpression(creation)) {
             builder.write(',');
@@ -3159,30 +3159,6 @@
     }
   }
 
-  Future<void> _addFix_replaceWithLiteral() async {
-    // TODO(brianwilkerson) Determine whether this await is necessary.
-    await null;
-    final InstanceCreationExpression instanceCreation =
-        node.thisOrAncestorOfType<InstanceCreationExpression>();
-    final InterfaceType type = instanceCreation.staticType;
-    final generics = instanceCreation.constructorName.type.typeArguments;
-    var changeBuilder = _newDartChangeBuilder();
-    await changeBuilder.addFileEdit(file, (DartFileEditBuilder builder) {
-      builder.addReplacement(range.node(instanceCreation),
-          (DartEditBuilder builder) {
-        if (generics != null) {
-          builder.write(utils.getNodeText(generics));
-        }
-        if (type.name == 'List') {
-          builder.write('[]');
-        } else {
-          builder.write('{}');
-        }
-      });
-    });
-    _addFixFromBuilder(changeBuilder, DartFixKind.REPLACE_WITH_LITERAL);
-  }
-
   Future<void> _addFix_replaceWithTearOff() async {
     // TODO(brianwilkerson) Determine whether this await is necessary.
     await null;
diff --git a/pkg/analysis_server/lib/src/utilities/documentation.dart b/pkg/analysis_server/lib/src/utilities/documentation.dart
deleted file mode 100644
index b47bb2f..0000000
--- a/pkg/analysis_server/lib/src/utilities/documentation.dart
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2015, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-String getDartDocSummary(String str) {
-  if (str == null) {
-    return null;
-  }
-  List<String> lines = str.split('\n');
-  StringBuffer sb = new StringBuffer();
-  bool firstLine = true;
-  for (String line in lines) {
-    if (sb.length != 0 && line.isEmpty) {
-      return sb.toString();
-    }
-    if (!firstLine) {
-      sb.write('\n');
-    }
-    firstLine = false;
-    sb.write(line);
-  }
-  return sb.toString();
-}
-
-/**
- * Converts [str] from a Dart Doc string with slashes and stars to a plain text
- * representation of the comment.
- */
-String removeDartDocDelimiters(String str) {
-  if (str == null) {
-    return null;
-  }
-  // remove /** */
-  if (str.startsWith('/**')) {
-    str = str.substring(3);
-  }
-  if (str.endsWith("*/")) {
-    str = str.substring(0, str.length - 2);
-  }
-  str = str.trim();
-  // remove leading '* ' and '/// '
-  List<String> lines = str.split('\n');
-  StringBuffer sb = new StringBuffer();
-  bool firstLine = true;
-  for (String line in lines) {
-    line = line.trim();
-    if (line.startsWith("*")) {
-      line = line.substring(1);
-      if (line.startsWith(" ")) {
-        line = line.substring(1);
-      }
-    } else if (line.startsWith("///")) {
-      line = line.substring(3);
-      if (line.startsWith(" ")) {
-        line = line.substring(1);
-      }
-    }
-    if (!firstLine) {
-      sb.write('\n');
-    }
-    firstLine = false;
-    sb.write(line);
-  }
-  str = sb.toString();
-  // done
-  return str;
-}
diff --git a/pkg/analysis_server/pubspec.yaml b/pkg/analysis_server/pubspec.yaml
new file mode 100644
index 0000000..d9f2c93
--- /dev/null
+++ b/pkg/analysis_server/pubspec.yaml
@@ -0,0 +1,29 @@
+name: analysis_server
+publish_to: none
+
+environment:
+  sdk: '>=2.1.0-dev.5.0 <3.0.0'
+
+dependencies:
+  analyzer: any
+  analyzer_plugin: any
+  args: any
+  convert: any
+  crypto: any
+  dart_style: any
+  front_end: any
+  linter: any
+  logging: any
+  meta: any
+  source_span: any
+  package_config: any
+  path: any
+  watcher: any
+  yaml: any
+
+dev_dependencies:
+  analysis_tool: any
+  html: any
+  http: any
+  test_reflective_loader: any
+  test: any
diff --git a/pkg/analysis_server/test/abstract_context.dart b/pkg/analysis_server/test/abstract_context.dart
index d9ffdb2..578053b 100644
--- a/pkg/analysis_server/test/abstract_context.dart
+++ b/pkg/analysis_server/test/abstract_context.dart
@@ -11,10 +11,10 @@
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/file_system/overlay_file_system.dart';
 import 'package:analyzer/src/dart/analysis/analysis_context_collection.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/driver_based_analysis_context.dart';
-import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/generated/engine.dart' show AnalysisEngine;
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/test_utilities/mock_sdk.dart';
@@ -45,11 +45,15 @@
 typedef void _ElementVisitorFunction(Element element);
 
 class AbstractContextTest with ResourceProviderMixin {
-  FileContentOverlay fileContentOverlay = new FileContentOverlay();
+  OverlayResourceProvider overlayResourceProvider;
 
   AnalysisContextCollection _analysisContextCollection;
   AnalysisDriver _driver;
 
+  /// The file system specific `/home/test/analysis_options.yaml` path.
+  String get analysisOptionsPath =>
+      convertPath('/home/test/analysis_options.yaml');
+
   AnalysisDriver get driver => _driver;
 
   AnalysisSession get session => driver.currentSession;
@@ -210,8 +214,7 @@
     _analysisContextCollection = AnalysisContextCollectionImpl(
       includedPaths: [convertPath('/home')],
       enableIndex: true,
-      fileContentOverlay: fileContentOverlay,
-      resourceProvider: resourceProvider,
+      resourceProvider: overlayResourceProvider,
       sdkPath: convertPath('/sdk'),
     );
 
@@ -219,6 +222,22 @@
     _driver = getDriver(testPath);
   }
 
+  /// Create an analysis options file based on the given arguments.
+  void createAnalysisOptionsFile({List<String> experiments}) {
+    StringBuffer buffer = new StringBuffer();
+    if (experiments != null) {
+      buffer.writeln('analyzer:');
+      buffer.writeln('  enable-experiment:');
+      for (String experiment in experiments) {
+        buffer.writeln('    - $experiment');
+      }
+    }
+    newFile(analysisOptionsPath, content: buffer.toString());
+    if (_driver != null) {
+      createAnalysisContexts();
+    }
+  }
+
   /// Return the existing analysis context that should be used to analyze the
   /// given [path], or throw [StateError] if the [path] is not analyzed in any
   /// of the created analysis contexts.
@@ -242,6 +261,7 @@
 
   void setUp() {
     setupResourceProvider();
+    overlayResourceProvider = OverlayResourceProvider(resourceProvider);
 
     new MockSdk(resourceProvider: resourceProvider);
 
diff --git a/pkg/analysis_server/test/abstract_single_unit.dart b/pkg/analysis_server/test/abstract_single_unit.dart
index b0901725..798bedb 100644
--- a/pkg/analysis_server/test/abstract_single_unit.dart
+++ b/pkg/analysis_server/test/abstract_single_unit.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
diff --git a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
index bd83a7d..9073af2 100644
--- a/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_analyzedFiles_test.dart
@@ -119,7 +119,7 @@
     expect(analyzedFilesReceived, isTrue);
 
     analyzedFilesReceived = false;
-    modifyTestFile('import "${convertAbsolutePathToUri('/foo.dart')}";');
+    modifyTestFile('import "${toUriStr('/foo.dart')}";');
     await prepareAnalyzedFiles();
     assertHasFile(convertPath('/foo.dart'));
   }
diff --git a/pkg/analysis_server/test/analysis/notification_implemented_test.dart b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
index 4401087..539354b 100644
--- a/pkg/analysis_server/test/analysis/notification_implemented_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_implemented_test.dart
@@ -71,7 +71,7 @@
   }
 
   /**
-   * Validates that there is no an [ImplementedClass] at the offset of [search].
+   * Validates that there is no [ImplementedMember] at the offset of [search].
    *
    * If [length] is not specified explicitly, then length of an identifier
    * from [search] is used.
@@ -167,6 +167,21 @@
     assertHasImplementedClass('A {');
   }
 
+  test_class_inMixin() async {
+    addTestFile('''
+class A {} // ref
+class B {} // ref
+class C {} // ref
+class D {} // ref
+mixin M on A, B implements C, D {}
+''');
+    await prepareImplementedElements();
+    assertHasImplementedClass('A {} // ref');
+    assertHasImplementedClass('B {} // ref');
+    assertHasImplementedClass('C {} // ref');
+    assertHasImplementedClass('D {} // ref');
+  }
+
   test_class_mixed() async {
     addTestFile('''
 class A {}
@@ -313,6 +328,40 @@
     assertHasImplementedMember('m(); // A');
   }
 
+  test_mixin_implemented() async {
+    addTestFile('''
+mixin M { // ref
+  void foo() {} // ref
+  void bar() {} // ref
+}
+
+class A implements M {
+  void foo() {}
+}
+''');
+    await prepareImplementedElements();
+    assertHasImplementedClass('M { // ref');
+    assertHasImplementedMember('foo() {} // ref');
+    assertNoImplementedMember('bar() {} // ref');
+  }
+
+  test_mixin_mixed() async {
+    addTestFile('''
+mixin M { // ref
+  void foo() {} // ref
+  void bar() {} // ref
+}
+
+class A extends Object with M {
+  void foo() {}
+}
+''');
+    await prepareImplementedElements();
+    assertHasImplementedClass('M { // ref');
+    assertHasImplementedMember('foo() {} // ref');
+    assertNoImplementedMember('bar() {} // ref');
+  }
+
   test_setter_withField() async {
     addTestFile('''
 class A {
diff --git a/pkg/analysis_server/test/analysis/notification_overrides_test.dart b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
index dfaec37..c840005 100644
--- a/pkg/analysis_server/test/analysis/notification_overrides_test.dart
+++ b/pkg/analysis_server/test/analysis/notification_overrides_test.dart
@@ -305,6 +305,38 @@
     assertHasInterfaceMember('m() {} // in A');
   }
 
+  test_inMixin_interface_method_direct_single() async {
+    addTestFile('''
+class A {
+  m() {} // in A
+}
+
+mixin M implements A {
+  m() {} // in M
+}
+''');
+    await prepareOverrides();
+    assertHasOverride('m() {} // in M');
+    assertNoSuperMember();
+    assertHasInterfaceMember('m() {} // in A');
+  }
+
+  test_inMixin_superclassConstraint_method_direct() async {
+    addTestFile('''
+class A {
+  m() {} // in A
+}
+
+mixin M on A {
+  m() {} // in M
+}
+''');
+    await prepareOverrides();
+    assertHasOverride('m() {} // in M');
+    assertHasSuperElement('m() {} // in A');
+    assertNoInterfaceMembers();
+  }
+
   test_interface_method_direct_multiple() async {
     addTestFile('''
 class IA {
diff --git a/pkg/analysis_server/test/completion_test.dart b/pkg/analysis_server/test/completion_test.dart
index d0cd508..692cbb4 100644
--- a/pkg/analysis_server/test/completion_test.dart
+++ b/pkg/analysis_server/test/completion_test.dart
@@ -163,19 +163,13 @@
         <String>["1+DateTime", "2+List"],
         failingTests: '12');
 
-    buildTests(
-        'testCommentSnippets030',
-        '''
+    buildTests('testCommentSnippets030', '''
 class Bar<T extends Foo> {const Bar(!1T!2 k);T!3 m(T!4 a, T!5 b){}final T!6 f = null;}''',
-        <String>["1+T", "2+T", "3+T", "4+T", "5+T", "6+T"],
-        failingTests: '123456');
+        <String>["1+T", "2+T", "3+T", "4+T", "5+T", "6+T"]);
 
-    buildTests(
-        'testCommentSnippets031',
-        '''
+    buildTests('testCommentSnippets031', '''
 class Bar<T extends Foo> {m(x){if (x is !1) return;if (x is!!!2)}}''',
-        <String>["1+Bar", "1+T", "2+T", "2+Bar"],
-        failingTests: '12');
+        <String>["1+Bar", "1+T", "2+T", "2+Bar"]);
 
     buildTests(
         'testCommentSnippets032',
diff --git a/pkg/analysis_server/test/domain_completion_test.dart b/pkg/analysis_server/test/domain_completion_test.dart
index 4749ab7..fa74e67 100644
--- a/pkg/analysis_server/test/domain_completion_test.dart
+++ b/pkg/analysis_server/test/domain_completion_test.dart
@@ -252,7 +252,7 @@
 
   test_import_uri_with_trailing() {
     final filePath = '/project/bin/testA.dart';
-    final incompleteImportText = convertAbsolutePathToUri('/project/bin/t');
+    final incompleteImportText = toUriStr('/project/bin/t');
     newFile(filePath, content: 'library libA;');
     addTestFile('''
     import "$incompleteImportText^.dart";
@@ -261,8 +261,7 @@
       expect(replacementOffset,
           equals(completionOffset - incompleteImportText.length));
       expect(replacementLength, equals(5 + incompleteImportText.length));
-      assertHasResult(
-          CompletionSuggestionKind.IMPORT, convertAbsolutePathToUri(filePath));
+      assertHasResult(CompletionSuggestionKind.IMPORT, toUriStr(filePath));
       assertNoResult('test');
     });
   }
@@ -510,7 +509,7 @@
   foo(bar) => 0;''');
     addTestFile('''
   library libA;
-  part "${convertAbsolutePathToUri('/testA.dart')}";
+  part "${toUriStr('/testA.dart')}";
   import "dart:math";
   /// The [^]
   main(aaa, bbb) {}
diff --git a/pkg/analysis_server/test/domain_edit_dartfix_test.dart b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
index 8e568e4..3f322e6 100644
--- a/pkg/analysis_server/test/domain_edit_dartfix_test.dart
+++ b/pkg/analysis_server/test/domain_edit_dartfix_test.dart
@@ -37,15 +37,20 @@
   }
 
   void expectSuggestion(DartFixSuggestion suggestion, String partialText,
-      int offset, int length) {
+      [int offset, int length]) {
     expect(suggestion.description, contains(partialText));
-    expect(suggestion.location.offset, offset);
-    expect(suggestion.location.length, length);
+    if (offset == null) {
+      expect(suggestion.location, isNull);
+    } else {
+      expect(suggestion.location.offset, offset);
+      expect(suggestion.location.length, length);
+    }
   }
 
-  Future<EditDartfixResult> performFix() async {
+  Future<EditDartfixResult> performFix({List<String> includedFixes}) async {
     final id = nextRequestId;
     final params = new EditDartfixParams([projectPath]);
+    params.includedFixes = includedFixes;
     final request = new Request(id, 'edit.dartfix', params.toJson());
 
     final response = await new EditDartFix(server, request).compute();
@@ -63,12 +68,12 @@
   }
 
   test_dartfix_convertClassToMixin() async {
-    createProject();
     addTestFile('''
 class A {}
 class B extends A {}
 class C with B {}
     ''');
+    createProject();
     EditDartfixResult result = await performFix();
     expect(result.suggestions, hasLength(1));
     expectSuggestion(result.suggestions[0], 'mixin', 17, 1);
@@ -80,10 +85,10 @@
   }
 
   test_dartfix_convertToIntLiteral() async {
-    createProject();
     addTestFile('''
 const double myDouble = 42.0;
     ''');
+    createProject();
     EditDartfixResult result = await performFix();
     expect(result.suggestions, hasLength(1));
     expectSuggestion(result.suggestions[0], 'int literal', 24, 4);
@@ -93,13 +98,13 @@
   }
 
   test_dartfix_moveTypeArgumentToClass() async {
-    createProject();
     addTestFile('''
 class A<T> { A.from(Object obj) { } }
 main() {
   print(new A.from<String>([]));
 }
     ''');
+    createProject();
     EditDartfixResult result = await performFix();
     expect(result.suggestions, hasLength(1));
     expectSuggestion(result.suggestions[0], 'type arguments', 65, 8);
@@ -118,58 +123,23 @@
   enable-experiment:
     - non-nullable
 ''');
-
-    createProject();
     addTestFile('''
-main() {
-  functionWithNullableParam(new List<String>(1));
-  functionWithNullableParam(null);
-}
-
-class C1 {}
-class C2 {}
-class C extends C1 with M1 implements C2 {}
-
-mixin M1 {}
-mixin M on M1 implements C1 {}
-
-void functionWithNullableParam(String object) {
-  if (object == null) {
-    print('object is null');
-  } else {
-    print('object is not-null');
-  }
-  List<Object> list = null;
-  list = <Object>[];
-  list.add(object);
+int f(int i) => 0;
+int g(int i) => f(i);
+void test() {
+  g(null);
 }
 ''');
-    EditDartfixResult result = await performFix();
-    expect(result.suggestions, hasLength(1));
+    createProject();
+    EditDartfixResult result =
+        await performFix(includedFixes: ['non-nullable']);
+    expect(result.suggestions.length, greaterThanOrEqualTo(1));
     expect(result.hasErrors, isFalse);
-    expectSuggestion(result.suggestions[0], 'non-nullable', 46, 6);
     expectEdits(result.edits, '''
-main() {
-  functionWithNullableParam(new List<String?>(1));
-  functionWithNullableParam(null);
-}
-
-class C1 {}
-class C2 {}
-class C extends C1 with M1 implements C2 {}
-
-mixin M1 {}
-mixin M on M1 implements C1 {}
-
-void functionWithNullableParam(String? object) {
-  if (object == null) {
-    print('object is null');
-  } else {
-    print('object is not-null');
-  }
-  List<Object?>? list = null;
-  list = <Object?>[];
-  list.add(object);
+int f(int? i) => 0;
+int g(int? i) => f(i);
+void test() {
+  g(null);
 }
 ''');
   }
@@ -182,10 +152,10 @@
     - lib/**
 ''');
 
-    createProject();
     addTestFile('''
 const double myDouble = 42.0;
     ''');
+    createProject();
 
     // Assert no suggestions now that source has been excluded
     final result = await performFix();
@@ -194,7 +164,6 @@
   }
 
   test_dartfix_partFile() async {
-    createProject();
     newFile('/project/lib/lib.dart', content: '''
 library lib2;
 part 'fileToBeFixed.dart';
@@ -203,6 +172,7 @@
 part of lib2;
 const double myDouble = 42.0;
     ''');
+    createProject();
 
     // Assert dartfix suggestions
     EditDartfixResult result = await performFix();
@@ -215,11 +185,11 @@
   }
 
   test_dartfix_partFile_loose() async {
-    createProject();
     addTestFile('''
 part of lib2;
 const double myDouble = 42.0;
     ''');
+    createProject();
 
     // Assert dartfix suggestions
     EditDartfixResult result = await performFix();
diff --git a/pkg/analysis_server/test/integration/analysis/error_test.dart b/pkg/analysis_server/test/integration/analysis/error_test.dart
index 4da91dc..0a7948b 100644
--- a/pkg/analysis_server/test/integration/analysis/error_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/error_test.dart
@@ -88,7 +88,7 @@
   }
 }
 ''');
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     await sendAnalysisUpdateOptions(
         new AnalysisOptions()..enableSuperMixins = true);
     standardAnalysisSetup();
diff --git a/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart b/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
index 286a24e..dee7a87 100644
--- a/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/get_reachable_sources_test.dart
@@ -35,7 +35,7 @@
     await analysisFinished;
 
     AnalysisGetReachableSourcesResult result =
-        // ignore: deprecated_member_use
+        // ignore: deprecated_member_use_from_same_package
         await sendAnalysisGetReachableSources(pathname);
     Map<String, List<String>> sources = result.sources;
     List<String> keys = sources.keys.toList();
diff --git a/pkg/analysis_server/test/integration/analysis/update_options_test.dart b/pkg/analysis_server/test/integration/analysis/update_options_test.dart
index b61db22..871e4fe 100644
--- a/pkg/analysis_server/test/integration/analysis/update_options_test.dart
+++ b/pkg/analysis_server/test/integration/analysis/update_options_test.dart
@@ -30,14 +30,14 @@
 ''');
     standardAnalysisSetup();
 
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     await sendAnalysisUpdateOptions(
         new AnalysisOptions()..generateHints = false);
     await sendAnalysisReanalyze();
     await analysisFinished;
     expect(getErrors(pathname), isEmpty);
 
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     await sendAnalysisUpdateOptions(
         new AnalysisOptions()..generateHints = true);
     await sendAnalysisReanalyze();
diff --git a/pkg/analysis_server/test/integration/coverage.md b/pkg/analysis_server/test/integration/coverage.md
index dcec50a..6f13a5e 100644
--- a/pkg/analysis_server/test/integration/coverage.md
+++ b/pkg/analysis_server/test/integration/coverage.md
@@ -30,18 +30,23 @@
 - [x] analysis.overrides
 
 ## completion domain
+- [ ] completion.availableSuggestions
+- [ ] completion.getSuggestionDetails
 - [x] completion.getSuggestions
+- [ ] completion.registerLibraryPaths
 - [ ] completion.results
+- [ ] completion.setSubscriptions
 
 ## diagnostic domain
 - [x] diagnostic.getDiagnostics
 - [x] diagnostic.getServerPort
 
 ## edit domain
-- [ ] edit.dartfix
+- [x] edit.dartfix
 - [x] edit.format
 - [x] edit.getAssists
 - [x] edit.getAvailableRefactorings
+- [x] edit.getDartfixInfo
 - [x] edit.getFixes
 - [x] edit.getPostfixCompletion
 - [x] edit.getRefactoring
diff --git a/pkg/analysis_server/test/integration/edit/dartfix_test.dart b/pkg/analysis_server/test/integration/edit/dartfix_test.dart
new file mode 100644
index 0000000..d389950
--- /dev/null
+++ b/pkg/analysis_server/test/integration/edit/dartfix_test.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../support/integration_tests.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(DartfixTest);
+  });
+}
+
+@reflectiveTest
+class DartfixTest extends AbstractAnalysisServerIntegrationTest {
+  void setupTarget() {
+    writeFile(sourcePath('test.dart'), '''
+class A {}
+class B extends A {}
+class C with B {}
+    ''');
+    standardAnalysisSetup();
+  }
+
+  test_dartfix() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)]);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, greaterThanOrEqualTo(1));
+    expect(result.edits.length, greaterThanOrEqualTo(1));
+  }
+
+  test_dartfix_exclude() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)],
+        excludedFixes: ['use-mixin']);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, 0);
+    expect(result.edits.length, 0);
+  }
+
+  test_dartfix_exclude_other() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)],
+        excludedFixes: ['double-to-int']);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, greaterThanOrEqualTo(1));
+    expect(result.edits.length, greaterThanOrEqualTo(1));
+  }
+
+  test_dartfix_include() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)],
+        includedFixes: ['use-mixin']);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, greaterThanOrEqualTo(1));
+    expect(result.edits.length, greaterThanOrEqualTo(1));
+  }
+
+  test_dartfix_include_other() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)],
+        includedFixes: ['double-to-int']);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, 0);
+    expect(result.edits.length, 0);
+  }
+
+  test_dartfix_required() async {
+    setupTarget();
+    EditDartfixResult result = await sendEditDartfix([(sourceDirectory.path)],
+        includeRequiredFixes: true);
+    expect(result.hasErrors, isFalse);
+    expect(result.suggestions.length, greaterThanOrEqualTo(1));
+    expect(result.edits.length, greaterThanOrEqualTo(1));
+  }
+}
diff --git a/pkg/analysis_server/test/integration/edit/get_dartfix_info_test.dart b/pkg/analysis_server/test/integration/edit/get_dartfix_info_test.dart
new file mode 100644
index 0000000..2d92b6a
--- /dev/null
+++ b/pkg/analysis_server/test/integration/edit/get_dartfix_info_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.
+
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../support/integration_tests.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GetDartfixInfoTest);
+  });
+}
+
+@reflectiveTest
+class GetDartfixInfoTest extends AbstractAnalysisServerIntegrationTest {
+  test_getDartfixInfo() async {
+    standardAnalysisSetup();
+    EditGetDartfixInfoResult info = await sendEditGetDartfixInfo();
+    expect(info.fixes.length, greaterThanOrEqualTo(3));
+    var fix = info.fixes.firstWhere((f) => f.name == 'use-mixin');
+    expect(fix.isRequired, isTrue);
+  }
+}
diff --git a/pkg/analysis_server/test/integration/edit/test_all.dart b/pkg/analysis_server/test/integration/edit/test_all.dart
index 6706806..3a71a95 100644
--- a/pkg/analysis_server/test/integration/edit/test_all.dart
+++ b/pkg/analysis_server/test/integration/edit/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'dartfix_test.dart' as dartfix_test;
 import 'format_test.dart' as format_test;
 import 'get_assists_test.dart' as get_assists_test;
 import 'get_available_refactorings_test.dart'
     as get_available_refactorings_test;
+import 'get_dartfix_info_test.dart' as get_dartfix_info_test;
 import 'get_fixes_test.dart' as get_fixes_test;
 import 'get_postfix_completion_test.dart' as get_postfix_completion_test;
 import 'get_refactoring_test.dart' as get_refactoring_test;
@@ -22,9 +24,11 @@
 
 main() {
   defineReflectiveSuite(() {
+    dartfix_test.main();
     format_test.main();
     get_assists_test.main();
     get_available_refactorings_test.main();
+    get_dartfix_info_test.main();
     get_fixes_test.main();
     get_refactoring_test.main();
     get_postfix_completion_test.main();
diff --git a/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart b/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
index a95fc27..82c3739 100644
--- a/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
+++ b/pkg/analysis_server/test/integration/execution/set_subscriptions_test.dart
@@ -17,7 +17,7 @@
 class SetSubscriptionsTest extends AbstractAnalysisServerIntegrationTest {
   test_subscribe() async {
     standardAnalysisSetup();
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     await sendExecutionSetSubscriptions([ExecutionService.LAUNCH_DATA]);
   }
 }
diff --git a/pkg/analysis_server/test/integration/support/integration_test_methods.dart b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
index 65b4cec..c536416 100644
--- a/pkg/analysis_server/test/integration/support/integration_test_methods.dart
+++ b/pkg/analysis_server/test/integration/support/integration_test_methods.dart
@@ -1056,6 +1056,105 @@
   }
 
   /**
+   * Subscribe for completion services. All previous subscriptions are replaced
+   * by the given set of services.
+   *
+   * It is an error if any of the elements in the list are not valid services.
+   * If there is an error, then the current subscriptions will remain
+   * unchanged.
+   *
+   * Parameters
+   *
+   * subscriptions: List<CompletionService>
+   *
+   *   A list of the services being subscribed to.
+   */
+  Future sendCompletionSetSubscriptions(
+      List<CompletionService> subscriptions) async {
+    var params = new CompletionSetSubscriptionsParams(subscriptions).toJson();
+    var result = await server.send("completion.setSubscriptions", params);
+    outOfTestExpect(result, isNull);
+    return null;
+  }
+
+  /**
+   * The client can make this request to express interest in certain libraries
+   * to receive completion suggestions from based on the client path. If this
+   * request is received before the client has used
+   * 'completion.setSubscriptions' to subscribe to the
+   * AVAILABLE_SUGGESTION_SETS service, then an error of type
+   * NOT_SUBSCRIBED_TO_AVAILABLE_SUGGESTION_SETS will be generated. All
+   * previous paths are replaced by the given set of paths.
+   *
+   * Parameters
+   *
+   * paths: List<LibraryPathSet>
+   *
+   *   A list of objects each containing a path and the additional libraries
+   *   from which the client is interested in receiving completion suggestions.
+   *   If one configured path is beneath another, the descendent will override
+   *   the ancestors' configured libraries of interest.
+   */
+  Future sendCompletionRegisterLibraryPaths(List<LibraryPathSet> paths) async {
+    var params = new CompletionRegisterLibraryPathsParams(paths).toJson();
+    var result = await server.send("completion.registerLibraryPaths", params);
+    outOfTestExpect(result, isNull);
+    return null;
+  }
+
+  /**
+   * Clients must make this request when the user has selected a completion
+   * suggestion from an AvailableSuggestionSet. Analysis server will respond
+   * with the text to insert as well as any SourceChange that needs to be
+   * applied in case the completion requires an additional import to be added.
+   * It is an error if the id is no longer valid, for instance if the library
+   * has been removed after the completion suggestion is accepted.
+   *
+   * Parameters
+   *
+   * file: FilePath
+   *
+   *   The path of the file into which this completion is being inserted.
+   *
+   * id: int
+   *
+   *   The identifier of the AvailableSuggestionSet containing the selected
+   *   label.
+   *
+   * label: String
+   *
+   *   The label from the AvailableSuggestionSet with the `id` for which
+   *   insertion information is requested.
+   *
+   * offset: int
+   *
+   *   The offset in the file where the completion will be inserted.
+   *
+   * Returns
+   *
+   * completion: String
+   *
+   *   The full text to insert, including any optional import prefix.
+   *
+   * change: SourceChange (optional)
+   *
+   *   A change for the client to apply in case the library containing the
+   *   accepted completion suggestion needs to be imported. The field will be
+   *   omitted if there are no additional changes that need to be made.
+   */
+  Future<CompletionGetSuggestionDetailsResult>
+      sendCompletionGetSuggestionDetails(
+          String file, int id, String label, int offset) async {
+    var params =
+        new CompletionGetSuggestionDetailsParams(file, id, label, offset)
+            .toJson();
+    var result = await server.send("completion.getSuggestionDetails", params);
+    ResponseDecoder decoder = new ResponseDecoder(null);
+    return new CompletionGetSuggestionDetailsResult.fromJson(
+        decoder, 'result', result);
+  }
+
+  /**
    * Reports the completion suggestions that should be presented to the user.
    * The set of suggestions included in the notification is always a complete
    * list that supersedes any previously reported suggestions.
@@ -1092,6 +1191,36 @@
    *
    *   True if this is that last set of results that will be returned for the
    *   indicated completion.
+   *
+   * includedSuggestionSets: List<IncludedSuggestionSet> (optional)
+   *
+   *   This field is experimental.
+   *
+   *   References to AvailableSuggestionSet objects previously sent to the
+   *   client. The client can include applicable names from the referenced
+   *   library in code completion suggestions.
+   *
+   * includedSuggestionKinds: List<ElementKind> (optional)
+   *
+   *   This field is experimental.
+   *
+   *   The client is expected to check this list against the ElementKind sent
+   *   in IncludedSuggestionSet to decide whether or not these symbols should
+   *   should be presented to the user.
+   *
+   * includedSuggestionRelevanceTags: List<IncludedSuggestionRelevanceTag>
+   * (optional)
+   *
+   *   This field is experimental.
+   *
+   *   The client is expected to check this list against the values of the
+   *   field relevanceTags of AvailableSuggestion to decide if the suggestion
+   *   should be given a different relevance than the IncludedSuggestionSet
+   *   that contains it. This might be used for example to give higher
+   *   relevance to suggestions of matching types.
+   *
+   *   If an AvailableSuggestion has relevance tags that match more than one
+   *   IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
    */
   Stream<CompletionResultsParams> onCompletionResults;
 
@@ -1101,6 +1230,34 @@
   StreamController<CompletionResultsParams> _onCompletionResults;
 
   /**
+   * Reports the pre-computed, candidate completions from symbols defined in a
+   * corresponding library. This notification may be sent multiple times. When
+   * a notification is processed, clients should replace any previous
+   * information about the libraries in the list of changedLibraries, discard
+   * any information about the libraries in the list of removedLibraries, and
+   * preserve any previously received information about any libraries that are
+   * not included in either list.
+   *
+   * Parameters
+   *
+   * changedLibraries: List<AvailableSuggestionSet> (optional)
+   *
+   *   A list of pre-computed, potential completions coming from this set of
+   *   completion suggestions.
+   *
+   * removedLibraries: List<int> (optional)
+   *
+   *   A list of library ids that no longer apply.
+   */
+  Stream<CompletionAvailableSuggestionsParams> onCompletionAvailableSuggestions;
+
+  /**
+   * Stream controller for [onCompletionAvailableSuggestions].
+   */
+  StreamController<CompletionAvailableSuggestionsParams>
+      _onCompletionAvailableSuggestions;
+
+  /**
    * Perform a search for references to the element defined or referenced at
    * the given offset in the given file.
    *
@@ -1482,11 +1639,38 @@
   }
 
   /**
+   * Request information about edit.dartfix such as the list of known fixes
+   * that can be specified in an edit.dartfix request.
+   *
+   * Parameters
+   *
+   * Returns
+   *
+   * fixes: List<DartFix>
+   *
+   *   A list of fixes that can be specified in an edit.dartfix request.
+   */
+  Future<EditGetDartfixInfoResult> sendEditGetDartfixInfo() async {
+    var params = new EditGetDartfixInfoParams().toJson();
+    var result = await server.send("edit.getDartfixInfo", params);
+    ResponseDecoder decoder = new ResponseDecoder(null);
+    return new EditGetDartfixInfoResult.fromJson(decoder, 'result', result);
+  }
+
+  /**
    * Analyze the specified sources for recommended changes and return a set of
    * suggested edits for those sources. These edits may include changes to
    * sources outside the set of specified sources if a change in a specified
    * source requires it.
    *
+   * If includedFixes is specified, then those fixes will be applied. If
+   * includeRequiredFixes is specified, then "required" fixes will be applied
+   * in addition to whatever fixes are specified in includedFixes if any. If
+   * neither includedFixes nor includeRequiredFixes is specified, then all
+   * fixes will be applied. If excludedFixes is specified, then those fixes
+   * will not be applied regardless of whether they are "required" or specified
+   * in includedFixes.
+   *
    * Parameters
    *
    * included: List<FilePath>
@@ -1501,6 +1685,24 @@
    *   analysis.setAnalysisRoots), an error of type FILE_NOT_ANALYZED will be
    *   generated.
    *
+   * includedFixes: List<String> (optional)
+   *
+   *   A list of names indicating which fixes should be applied.
+   *
+   *   If a name is specified that does not match the name of a known fix, an
+   *   error of type UNKNOWN_FIX will be generated.
+   *
+   * includeRequiredFixes: bool (optional)
+   *
+   *   A flag indicating that "required" fixes should be applied.
+   *
+   * excludedFixes: List<String> (optional)
+   *
+   *   A list of names indicating which fixes should not be applied.
+   *
+   *   If a name is specified that does not match the name of a known fix, an
+   *   error of type UNKNOWN_FIX will be generated.
+   *
    * Returns
    *
    * suggestions: List<DartFixSuggestion>
@@ -1522,8 +1724,15 @@
    *
    *   A list of source edits to apply the recommended changes.
    */
-  Future<EditDartfixResult> sendEditDartfix(List<String> included) async {
-    var params = new EditDartfixParams(included).toJson();
+  Future<EditDartfixResult> sendEditDartfix(List<String> included,
+      {List<String> includedFixes,
+      bool includeRequiredFixes,
+      List<String> excludedFixes}) async {
+    var params = new EditDartfixParams(included,
+            includedFixes: includedFixes,
+            includeRequiredFixes: includeRequiredFixes,
+            excludedFixes: excludedFixes)
+        .toJson();
     var result = await server.send("edit.dartfix", params);
     ResponseDecoder decoder = new ResponseDecoder(null);
     return new EditDartfixResult.fromJson(decoder, 'result', result);
@@ -2459,6 +2668,10 @@
     _onCompletionResults =
         new StreamController<CompletionResultsParams>(sync: true);
     onCompletionResults = _onCompletionResults.stream.asBroadcastStream();
+    _onCompletionAvailableSuggestions =
+        new StreamController<CompletionAvailableSuggestionsParams>(sync: true);
+    onCompletionAvailableSuggestions =
+        _onCompletionAvailableSuggestions.stream.asBroadcastStream();
     _onSearchResults = new StreamController<SearchResultsParams>(sync: true);
     onSearchResults = _onSearchResults.stream.asBroadcastStream();
     _onExecutionLaunchData =
@@ -2555,6 +2768,12 @@
         _onCompletionResults.add(
             new CompletionResultsParams.fromJson(decoder, 'params', params));
         break;
+      case "completion.availableSuggestions":
+        outOfTestExpect(params, isCompletionAvailableSuggestionsParams);
+        _onCompletionAvailableSuggestions.add(
+            new CompletionAvailableSuggestionsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case "search.results":
         outOfTestExpect(params, isSearchResultsParams);
         _onSearchResults
diff --git a/pkg/analysis_server/test/integration/support/protocol_matchers.dart b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
index 6630dbe..ef2ded9 100644
--- a/pkg/analysis_server/test/integration/support/protocol_matchers.dart
+++ b/pkg/analysis_server/test/integration/support/protocol_matchers.dart
@@ -164,6 +164,56 @@
     optionalFields: {"analysisTarget": isString}));
 
 /**
+ * AvailableSuggestion
+ *
+ * {
+ *   "label": String
+ *   "element": Element
+ *   "docComplete": optional String
+ *   "docSummary": optional String
+ *   "parameterNames": optional List<String>
+ *   "parameterTypes": optional List<String>
+ *   "relevanceTags": optional List<AvailableSuggestionRelevanceTag>
+ *   "requiredParameterCount": optional int
+ * }
+ */
+final Matcher isAvailableSuggestion =
+    new LazyMatcher(() => new MatchesJsonObject("AvailableSuggestion", {
+          "label": isString,
+          "element": isElement
+        }, optionalFields: {
+          "docComplete": isString,
+          "docSummary": isString,
+          "parameterNames": isListOf(isString),
+          "parameterTypes": isListOf(isString),
+          "relevanceTags": isListOf(isAvailableSuggestionRelevanceTag),
+          "requiredParameterCount": isInt
+        }));
+
+/**
+ * AvailableSuggestionRelevanceTag
+ *
+ * String
+ */
+final Matcher isAvailableSuggestionRelevanceTag = isString;
+
+/**
+ * AvailableSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "uri": String
+ *   "items": List<AvailableSuggestion>
+ * }
+ */
+final Matcher isAvailableSuggestionSet = new LazyMatcher(() =>
+    new MatchesJsonObject("AvailableSuggestionSet", {
+      "id": isInt,
+      "uri": isString,
+      "items": isListOf(isAvailableSuggestion)
+    }));
+
+/**
  * ChangeContentOverlay
  *
  * {
@@ -195,6 +245,16 @@
 final Matcher isCompletionId = isString;
 
 /**
+ * CompletionService
+ *
+ * enum {
+ *   AVAILABLE_SUGGESTION_SETS
+ * }
+ */
+final Matcher isCompletionService =
+    new MatchesEnum("CompletionService", ["AVAILABLE_SUGGESTION_SETS"]);
+
+/**
  * CompletionSuggestion
  *
  * {
@@ -300,6 +360,19 @@
         }));
 
 /**
+ * DartFix
+ *
+ * {
+ *   "name": String
+ *   "description": optional String
+ *   "isRequired": optional bool
+ * }
+ */
+final Matcher isDartFix = new LazyMatcher(() => new MatchesJsonObject(
+    "DartFix", {"name": isString},
+    optionalFields: {"description": isString, "isRequired": isBool}));
+
+/**
  * DartFixSuggestion
  *
  * {
@@ -873,6 +946,30 @@
     {"path": isFilePath, "prefix": isString, "elements": isListOf(isString)}));
 
 /**
+ * IncludedSuggestionRelevanceTag
+ *
+ * {
+ *   "tag": AvailableSuggestionRelevanceTag
+ *   "relevanceBoost": int
+ * }
+ */
+final Matcher isIncludedSuggestionRelevanceTag = new LazyMatcher(() =>
+    new MatchesJsonObject("IncludedSuggestionRelevanceTag",
+        {"tag": isAvailableSuggestionRelevanceTag, "relevanceBoost": isInt}));
+
+/**
+ * IncludedSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "relevance": int
+ * }
+ */
+final Matcher isIncludedSuggestionSet = new LazyMatcher(() =>
+    new MatchesJsonObject(
+        "IncludedSuggestionSet", {"id": isInt, "relevance": isInt}));
+
+/**
  * KytheEntry
  *
  * {
@@ -914,6 +1011,18 @@
         }));
 
 /**
+ * LibraryPathSet
+ *
+ * {
+ *   "scope": FilePath
+ *   "libraryPaths": List<FilePath>
+ * }
+ */
+final Matcher isLibraryPathSet = new LazyMatcher(() => new MatchesJsonObject(
+    "LibraryPathSet",
+    {"scope": isFilePath, "libraryPaths": isListOf(isFilePath)}));
+
+/**
  * LinkedEditGroup
  *
  * {
@@ -1294,6 +1403,7 @@
  *   SERVER_ERROR
  *   SORT_MEMBERS_INVALID_FILE
  *   SORT_MEMBERS_PARSE_ERRORS
+ *   UNKNOWN_FIX
  *   UNKNOWN_REQUEST
  *   UNSUPPORTED_FEATURE
  * }
@@ -1325,6 +1435,7 @@
   "SERVER_ERROR",
   "SORT_MEMBERS_INVALID_FILE",
   "SORT_MEMBERS_PARSE_ERRORS",
+  "UNKNOWN_FIX",
   "UNKNOWN_REQUEST",
   "UNSUPPORTED_FEATURE"
 ]);
@@ -2032,6 +2143,48 @@
 final Matcher isAnalyticsSendTimingResult = isNull;
 
 /**
+ * completion.availableSuggestions params
+ *
+ * {
+ *   "changedLibraries": optional List<AvailableSuggestionSet>
+ *   "removedLibraries": optional List<int>
+ * }
+ */
+final Matcher isCompletionAvailableSuggestionsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.availableSuggestions params", null,
+        optionalFields: {
+          "changedLibraries": isListOf(isAvailableSuggestionSet),
+          "removedLibraries": isListOf(isInt)
+        }));
+
+/**
+ * completion.getSuggestionDetails params
+ *
+ * {
+ *   "file": FilePath
+ *   "id": int
+ *   "label": String
+ *   "offset": int
+ * }
+ */
+final Matcher isCompletionGetSuggestionDetailsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.getSuggestionDetails params",
+        {"file": isFilePath, "id": isInt, "label": isString, "offset": isInt}));
+
+/**
+ * completion.getSuggestionDetails result
+ *
+ * {
+ *   "completion": String
+ *   "change": optional SourceChange
+ * }
+ */
+final Matcher isCompletionGetSuggestionDetailsResult = new LazyMatcher(() =>
+    new MatchesJsonObject(
+        "completion.getSuggestionDetails result", {"completion": isString},
+        optionalFields: {"change": isSourceChange}));
+
+/**
  * completion.getSuggestions params
  *
  * {
@@ -2055,6 +2208,22 @@
         "completion.getSuggestions result", {"id": isCompletionId}));
 
 /**
+ * completion.registerLibraryPaths params
+ *
+ * {
+ *   "paths": List<LibraryPathSet>
+ * }
+ */
+final Matcher isCompletionRegisterLibraryPathsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.registerLibraryPaths params",
+        {"paths": isListOf(isLibraryPathSet)}));
+
+/**
+ * completion.registerLibraryPaths result
+ */
+final Matcher isCompletionRegisterLibraryPathsResult = isNull;
+
+/**
  * completion.results params
  *
  * {
@@ -2063,6 +2232,9 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
+ *   "includedSuggestionKinds": optional List<ElementKind>
+ *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
  * }
  */
 final Matcher isCompletionResultsParams =
@@ -2072,9 +2244,30 @@
           "replacementLength": isInt,
           "results": isListOf(isCompletionSuggestion),
           "isLast": isBool
+        }, optionalFields: {
+          "includedSuggestionSets": isListOf(isIncludedSuggestionSet),
+          "includedSuggestionKinds": isListOf(isElementKind),
+          "includedSuggestionRelevanceTags":
+              isListOf(isIncludedSuggestionRelevanceTag)
         }));
 
 /**
+ * completion.setSubscriptions params
+ *
+ * {
+ *   "subscriptions": List<CompletionService>
+ * }
+ */
+final Matcher isCompletionSetSubscriptionsParams = new LazyMatcher(() =>
+    new MatchesJsonObject("completion.setSubscriptions params",
+        {"subscriptions": isListOf(isCompletionService)}));
+
+/**
+ * completion.setSubscriptions result
+ */
+final Matcher isCompletionSetSubscriptionsResult = isNull;
+
+/**
  * convertGetterToMethod feedback
  */
 final Matcher isConvertGetterToMethodFeedback = isNull;
@@ -2130,10 +2323,19 @@
  *
  * {
  *   "included": List<FilePath>
+ *   "includedFixes": optional List<String>
+ *   "includeRequiredFixes": optional bool
+ *   "excludedFixes": optional List<String>
  * }
  */
-final Matcher isEditDartfixParams = new LazyMatcher(() => new MatchesJsonObject(
-    "edit.dartfix params", {"included": isListOf(isFilePath)}));
+final Matcher isEditDartfixParams =
+    new LazyMatcher(() => new MatchesJsonObject("edit.dartfix params", {
+          "included": isListOf(isFilePath)
+        }, optionalFields: {
+          "includedFixes": isListOf(isString),
+          "includeRequiredFixes": isBool,
+          "excludedFixes": isListOf(isString)
+        }));
 
 /**
  * edit.dartfix result
@@ -2233,6 +2435,26 @@
         {"kinds": isListOf(isRefactoringKind)}));
 
 /**
+ * edit.getDartfixInfo params
+ *
+ * {
+ * }
+ */
+final Matcher isEditGetDartfixInfoParams = new LazyMatcher(
+    () => new MatchesJsonObject("edit.getDartfixInfo params", null));
+
+/**
+ * edit.getDartfixInfo result
+ *
+ * {
+ *   "fixes": List<DartFix>
+ * }
+ */
+final Matcher isEditGetDartfixInfoResult = new LazyMatcher(() =>
+    new MatchesJsonObject(
+        "edit.getDartfixInfo result", {"fixes": isListOf(isDartFix)}));
+
+/**
  * edit.getFixes params
  *
  * {
diff --git a/pkg/analysis_server/test/lsp/completion_test.dart b/pkg/analysis_server/test/lsp/completion_test.dart
index 23f9b39..26685ec 100644
--- a/pkg/analysis_server/test/lsp/completion_test.dart
+++ b/pkg/analysis_server/test/lsp/completion_test.dart
@@ -195,7 +195,7 @@
     expect(res.any((c) => c.label == 'abcdefghij'), isTrue);
     final item = res.singleWhere((c) => c.label == 'abcdefghij');
     expect(item.insertTextFormat, equals(InsertTextFormat.PlainText));
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     expect(item.insertText, anyOf(equals('abcdefghij'), isNull));
     final updated = applyTextEdits(withoutMarkers(content), [item.textEdit]);
     expect(updated, contains('a.abcdefghij'));
@@ -219,7 +219,7 @@
     expect(res.any((c) => c.label == 'abcdefghij'), isTrue);
     final item = res.singleWhere((c) => c.label == 'abcdefghij');
     expect(item.insertTextFormat, equals(InsertTextFormat.PlainText));
-    // ignore: deprecated_member_use
+    // ignore: deprecated_member_use_from_same_package
     expect(item.insertText, anyOf(equals('abcdefghij'), isNull));
     final updated = applyTextEdits(withoutMarkers(content), [item.textEdit]);
     expect(updated, contains('a.abcdefghij'));
diff --git a/pkg/analysis_server/test/lsp/server_abstract.dart b/pkg/analysis_server/test/lsp/server_abstract.dart
index 94c60f2..a1735ec 100644
--- a/pkg/analysis_server/test/lsp/server_abstract.dart
+++ b/pkg/analysis_server/test/lsp/server_abstract.dart
@@ -403,6 +403,14 @@
     return expectSuccessfulResponseTo(request);
   }
 
+  Future<List<SymbolInformation>> getWorkspaceSymbols(String query) {
+    final request = makeRequest(
+      Method.workspace_symbol,
+      new WorkspaceSymbolParams(query),
+    );
+    return expectSuccessfulResponseTo(request);
+  }
+
   Future<List<FoldingRange>> getFoldingRegions(Uri uri) {
     final request = makeRequest(
       Method.textDocument_foldingRange,
diff --git a/pkg/analysis_server/test/lsp/test_all.dart b/pkg/analysis_server/test/lsp/test_all.dart
index 2745a6b..bdd25b3 100644
--- a/pkg/analysis_server/test/lsp/test_all.dart
+++ b/pkg/analysis_server/test/lsp/test_all.dart
@@ -15,6 +15,7 @@
 import 'document_highlights_test.dart' as document_highlights_test;
 import 'document_symbols_test.dart' as document_symbols_test;
 import 'file_modification_test.dart' as file_modification_test;
+import 'folding_test.dart' as folding_test;
 import 'format_test.dart' as format_test;
 import 'hover_test.dart' as hover_test;
 import 'initialization_test.dart' as initialization_test;
@@ -23,7 +24,7 @@
 import 'rename_test.dart' as rename_test;
 import 'server_test.dart' as server_test;
 import 'signature_help_test.dart' as signature_help_test;
-import 'folding_test.dart' as folding_test;
+import 'workspace_symbols_test.dart' as workspace_symbols_test;
 
 main() {
   defineReflectiveSuite(() {
@@ -46,5 +47,6 @@
     packet_transformer_tests.main();
     rename_test.main();
     folding_test.main();
+    workspace_symbols_test.main();
   }, name: 'lsp');
 }
diff --git a/pkg/analysis_server/test/lsp/workspace_symbols_test.dart b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
new file mode 100644
index 0000000..72cad45
--- /dev/null
+++ b/pkg/analysis_server/test/lsp/workspace_symbols_test.dart
@@ -0,0 +1,107 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/lsp_protocol/protocol_generated.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'server_abstract.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(WorkspaceSymbolsTest);
+  });
+}
+
+@reflectiveTest
+class WorkspaceSymbolsTest extends AbstractLspAnalysisServerTest {
+  test_fullMatch() async {
+    const content = '''
+    [[String topLevel = '']];
+    class MyClass {
+      int myField;
+      MyClass(this.myField);
+      myMethod() {}
+    }
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final symbols = await getWorkspaceSymbols('topLevel');
+
+    final topLevel = symbols.firstWhere((s) => s.name == 'topLevel');
+    expect(topLevel.kind, equals(SymbolKind.Variable));
+    expect(topLevel.containerName, isNull);
+    expect(topLevel.location.uri, equals(mainFileUri.toString()));
+    expect(topLevel.location.range, equals(rangeFromMarkers(content)));
+
+    // Ensure we didn't get some things that definitely do not match.
+    expect(symbols.any((s) => s.name == 'MyClass'), isFalse);
+    expect(symbols.any((s) => s.name == 'myMethod'), isFalse);
+  }
+
+  test_fuzzyMatch() async {
+    const content = '''
+    String topLevel = '';
+    class MyClass {
+      [[int myField]];
+      MyClass(this.myField);
+      myMethod() {}
+    }
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    // meld should match myField
+    final symbols = await getWorkspaceSymbols('meld');
+
+    final field = symbols.firstWhere((s) => s.name == 'myField');
+    expect(field.kind, equals(SymbolKind.Field));
+    expect(field.containerName, equals('MyClass'));
+    expect(field.location.uri, equals(mainFileUri.toString()));
+    expect(field.location.range, equals(rangeFromMarkers(content)));
+
+    // Ensure we didn't get some things that definitely do not match.
+    expect(symbols.any((s) => s.name == 'MyClass'), isFalse);
+    expect(symbols.any((s) => s.name == 'myMethod'), isFalse);
+  }
+
+  test_partialMatch() async {
+    const content = '''
+    String topLevel = '';
+    class MyClass {
+      [[int myField]];
+      MyClass(this.myField);
+      [[myMethod() {}]]
+    }
+    ''';
+    newFile(mainFilePath, content: withoutMarkers(content));
+    await initialize();
+
+    final symbols = await getWorkspaceSymbols('my');
+    final ranges = rangesFromMarkers(content);
+    final fieldRange = ranges[0];
+    final methodRange = ranges[1];
+
+    final field = symbols.firstWhere((s) => s.name == 'myField');
+    expect(field.kind, equals(SymbolKind.Field));
+    expect(field.containerName, equals('MyClass'));
+    expect(field.location.uri, equals(mainFileUri.toString()));
+    expect(field.location.range, equals(fieldRange));
+
+    final klass = symbols.firstWhere((s) => s.name == 'MyClass');
+    expect(klass.kind, equals(SymbolKind.Class));
+    expect(klass.containerName, isNull);
+    expect(klass.location.uri, equals(mainFileUri.toString()));
+
+    final method = symbols.firstWhere((s) => s.name == 'myMethod');
+    expect(method.kind, equals(SymbolKind.Method));
+    expect(method.containerName, equals('MyClass'));
+    expect(method.location.uri, equals(mainFileUri.toString()));
+    expect(method.location.range, equals(methodRange));
+
+    // Ensure we didn't get some things that definitely do not match.
+    expect(symbols.any((s) => s.name == 'topLevel'), isFalse);
+  }
+}
diff --git a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
index cedde60..9d9a40d 100644
--- a/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/arglist_contributor_test.dart
@@ -41,23 +41,6 @@
     expect(suggestion.selectionLength, selectionLength);
   }
 
-  void assertSuggestArgumentList(
-      List<String> paramNames, List<String> paramTypes) {
-    // DEPRECATED... argument lists are no longer suggested.
-    // See https://github.com/dart-lang/sdk/issues/25197
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
-
-    // CompletionSuggestionKind csKind = CompletionSuggestionKind.ARGUMENT_LIST;
-    // CompletionSuggestion cs = getSuggest(csKind: csKind);
-    // if (cs == null) {
-    //   failedCompletion('expected completion $csKind', suggestions);
-    // }
-    // assertSuggestArgumentList_params(
-    //     paramNames, paramTypes, cs.parameterNames, cs.parameterTypes);
-    // expect(cs.relevance, DART_RELEVANCE_HIGH);
-    // assertNoOtherSuggestions([cs]);
-  }
-
   void assertSuggestArgumentList_params(
       List<String> expectedNames,
       List<String> expectedTypes,
@@ -531,54 +514,6 @@
     assertNoSuggestions();
   }
 
-  test_ArgumentList_imported_function_1() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/home/test/lib/a.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      expect(String arg) { }
-      void baz() { }''');
-    addTestSource('''
-      import 'a.dart'
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg'], ['String']);
-  }
-
-  test_ArgumentList_imported_function_2() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/home/test/lib/a.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      expect(String arg1, int arg2) { }
-      void baz() { }''');
-    addTestSource('''
-      import 'a.dart'
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
-  }
-
-  test_ArgumentList_imported_function_3() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/home/test/lib/a.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      expect(String arg1, int arg2, {bool arg3}) { }
-      void baz() { }''');
-    addTestSource('''
-      import 'a.dart'
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg1', 'arg2'], ['String', 'int']);
-  }
-
   test_ArgumentList_imported_function_3a() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addSource('/home/test/lib/a.dart', '''
@@ -901,39 +836,6 @@
         requiredParamIndices: [1]);
   }
 
-  test_ArgumentList_local_function_1() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('''
-      expect(arg) { }
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg'], ['dynamic']);
-  }
-
-  test_ArgumentList_local_function_2() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('''
-      expect(arg1, int arg2) { }
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
-  }
-
-  test_ArgumentList_local_function_3() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addTestSource('''
-      expect(arg1, int arg2) { }
-      class B { }
-      String bar() => true;
-      void main() {expect(^)}''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg1', 'arg2'], ['dynamic', 'int']);
-  }
-
   test_ArgumentList_local_function_3a() async {
     // ArgumentList  MethodInvocation  ExpressionStatement  Block
     addTestSource('''
@@ -1032,20 +934,4 @@
     await computeSuggestions();
     assertNoSuggestions();
   }
-
-  test_ArgumentList_local_method_2() async {
-    // ArgumentList  MethodInvocation  ExpressionStatement  Block
-    addSource('/home/test/lib/a.dart', '''
-      library A;
-      bool hasLength(int expected) { }
-      void baz() { }''');
-    addTestSource('''
-      import 'a.dart'
-      class B {
-        expect(arg, int blat) { }
-        void foo() {expect(^)}}
-      String bar() => true;''');
-    await computeSuggestions();
-    assertSuggestArgumentList(['arg', 'blat'], ['dynamic', 'int']);
-  }
 }
diff --git a/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart b/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
index a1ba82c..82d9e55 100644
--- a/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/common_usage_sorter_test.dart
@@ -86,7 +86,7 @@
     // SimpleIdentifier  PrefixedIdentifier  ExpressionStatement
     newFile('/project/bin/myLib.dart',
         content:
-            'library L; part "${convertAbsolutePathToUri(testFile)}"; class A {static int s2;}');
+            'library L; part "${toUriStr(testFile)}"; class A {static int s2;}');
     addTestFile('part of L; foo() {A.^}');
     await getSuggestionsWith({
       'L.A': ['s2']
diff --git a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
index 6e09724..6c5a310 100644
--- a/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/completion_manager_test.dart
@@ -10,7 +10,6 @@
 import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
 import 'package:analysis_server/src/services/completion/dart/imported_reference_contributor.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/src/task/dart.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -52,8 +51,7 @@
         new CompletionPerformance());
     Completer<DartCompletionRequest> requestCompleter =
         new Completer<DartCompletionRequest>();
-    DartCompletionRequestImpl.from(baseRequest,
-            resultDescriptor: RESOLVED_UNIT1)
+    DartCompletionRequestImpl.from(baseRequest)
         .then((DartCompletionRequest request) {
       requestCompleter.complete(request);
     });
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 1bbf623..0c2b22f 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
@@ -63,7 +63,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool');
     assertSuggestFunction('identical', 'bool');
@@ -90,7 +89,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool');
     assertSuggestFunction('identical', 'bool');
@@ -118,7 +116,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool',
         kind: CompletionSuggestionKind.IDENTIFIER);
@@ -150,7 +147,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool',
         kind: CompletionSuggestionKind.IDENTIFIER);
@@ -180,7 +176,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool');
     assertSuggestFunction('identical', 'bool');
@@ -207,7 +202,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool');
     assertSuggestFunction('identical', 'bool');
@@ -235,7 +229,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertSuggestFunction('hasLength', 'bool',
         kind: CompletionSuggestionKind.IDENTIFIER);
@@ -265,7 +258,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('hasLength', 'bool',
         kind: CompletionSuggestionKind.IDENTIFIER);
     assertSuggestFunction('identical', 'bool',
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 36a37e9..b0e10ba 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
@@ -87,7 +87,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -118,7 +117,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -150,7 +148,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -184,7 +181,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -216,7 +212,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -247,7 +242,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -279,7 +273,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -311,7 +304,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
     if (suggestConstructorsWithoutNew) {
diff --git a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
index d484f79..3844a66 100644
--- a/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/local_reference_contributor_test.dart
@@ -5,7 +5,6 @@
 import 'package:analysis_server/src/protocol_server.dart';
 import 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
 import 'package:analysis_server/src/services/completion/dart/local_reference_contributor.dart';
-import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -58,6 +57,20 @@
     return cs;
   }
 
+  CompletionSuggestion assertSuggestTypeParameter(String name,
+      {int relevance: DART_RELEVANCE_TYPE_PARAMETER}) {
+    CompletionSuggestion cs = assertSuggest(name,
+        csKind: CompletionSuggestionKind.IDENTIFIER, relevance: relevance);
+    expect(cs.returnType, isNull);
+    Element element = cs.element;
+    expect(element, isNotNull);
+    expect(element.kind, equals(ElementKind.TYPE_PARAMETER));
+    expect(element.name, equals(name));
+    expect(element.parameters, isNull);
+    expect(element.returnType, isNull);
+    return cs;
+  }
+
   @override
   DartCompletionContributor createContributor() {
     return new LocalReferenceContributor();
@@ -152,7 +165,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
     assertNotSuggested('hasLength');
@@ -180,7 +192,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
     assertNotSuggested('hasLength');
@@ -209,7 +220,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
@@ -241,7 +251,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
@@ -271,7 +280,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
     assertNotSuggested('hasLength');
@@ -299,7 +307,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
     assertNotSuggested('hasLength');
@@ -328,7 +335,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance: DART_RELEVANCE_LOCAL_FUNCTION);
@@ -362,7 +368,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertSuggestFunction('bar', 'String',
         kind: CompletionSuggestionKind.IDENTIFIER,
         relevance:
@@ -397,7 +402,6 @@
 
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
     assertSuggestClass('B', kind: CompletionSuggestionKind.IDENTIFIER);
@@ -2302,6 +2306,108 @@
     assertSuggestEnumConst('F.four');
   }
 
+  test_expression_localVariable() async {
+    addTestSource('''
+void f() {
+  var v = 0;
+  ^
+}
+''');
+    await computeSuggestions();
+    assertSuggestLocalVariable('v', 'int');
+  }
+
+  test_expression_parameter() async {
+    addTestSource('''
+void f(int a) {
+  ^
+}
+''');
+    await computeSuggestions();
+    assertSuggestParameter('a', 'int');
+  }
+
+  test_expression_typeParameter_classDeclaration() async {
+    addTestSource('''
+class A<T> {
+  void m() {
+    ^
+  }
+}
+class B<U> {}
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertNotSuggested('U');
+  }
+
+  test_expression_typeParameter_classTypeAlias() async {
+    addTestSource('''
+class A<U> {}
+class B<T> = A<^>;
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertNotSuggested('U');
+  }
+
+  test_expression_typeParameter_functionDeclaration() async {
+    addTestSource('''
+void f<T>() {
+  ^
+}
+void g<U>() {}
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertNotSuggested('U');
+  }
+
+  test_expression_typeParameter_functionDeclaration_local() async {
+    addTestSource('''
+void f() {
+  void g2<U>() {}
+  void g<T>() {
+    ^
+  }
+}
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertNotSuggested('U');
+  }
+
+  test_expression_typeParameter_functionTypeAlias() async {
+    addTestSource('''
+typedef void F<T>(^);
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+  }
+
+  test_expression_typeParameter_genericTypeAlias() async {
+    addTestSource('''
+typedef F<T> = void Function<U>(^);
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertSuggestTypeParameter('U');
+  }
+
+  test_expression_typeParameter_methodDeclaration() async {
+    addTestSource('''
+class A {
+  void m<T>() {
+    ^
+  }
+  void m2<U>() {}
+}
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+    assertNotSuggested('U');
+  }
+
   test_ExpressionStatement_identifier() async {
     // SimpleIdentifier  ExpressionStatement  Block
     addSource('/home/test/lib/a.dart', '''
@@ -4601,6 +4707,16 @@
     assertNoSuggestions();
   }
 
+  test_type_typeParameter_classDeclaration() async {
+    addTestSource('''
+class A<T> {
+  ^ m() {}
+}
+''');
+    await computeSuggestions();
+    assertSuggestTypeParameter('T');
+  }
+
   test_TypeArgumentList() async {
     // SimpleIdentifier  BinaryExpression  ExpressionStatement
     addSource('/home/test/lib/a.dart', '''
diff --git a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
index 076ae44..da7ec8f 100644
--- a/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/override_contributor_test.dart
@@ -246,6 +246,21 @@
         selectionLength: 22);
   }
 
+  test_outsideOfWorkspace() async {
+    testFile = convertPath('/home/other/lib/a.dart');
+    addTestSource('''
+class A {
+  void foo() {}
+}
+
+class B extends A {
+  f^
+}
+''');
+    await computeSuggestions();
+    _assertNoOverrideContaining('foo');
+  }
+
   test_private_otherLibrary() async {
     addSource('/home/test/lib/a.dart', '''
 class A {
diff --git a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
index 5fd129a..c3712b1 100644
--- a/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
+++ b/pkg/analysis_server/test/services/completion/dart/type_member_contributor_test.dart
@@ -125,7 +125,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -151,7 +150,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -178,7 +176,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -207,7 +204,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -234,7 +230,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -260,7 +255,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -287,7 +281,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -314,7 +307,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
     assertNotSuggested('B');
@@ -2914,6 +2906,30 @@
     assertNotSuggested('==');
   }
 
+  test_mixin() async {
+    addTestSource(r'''
+class A {
+  void a() {}
+}
+
+class B {
+  void b() {}
+}
+
+mixin X on A, B {
+  void x() {}
+}
+
+void f(X x) {
+  x.^
+}
+''');
+    await computeSuggestions();
+    assertSuggestMethod('a', 'A', 'void');
+    assertSuggestMethod('b', 'B', 'void');
+    assertSuggestMethod('x', 'X', 'void');
+  }
+
   test_new_instance() async {
     addTestSource('import "dart:math"; class A {x() {new Random().^}}');
     await computeSuggestions();
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 fa60f61..59f07b6 100644
--- a/pkg/analysis_server/test/services/refactoring/move_file_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/move_file_test.dart
@@ -37,7 +37,7 @@
 import '22/c.dart';
 export '333/d.dart';
 part 'a.dart';
-part '${convertAbsolutePathToUri('/absolute/uri.dart')}';
+part '${toUriStr('/absolute/uri.dart')}';
 ''');
     // perform refactoring
     _createRefactoring('/home/test/000/1111/22/new_name.dart');
@@ -51,7 +51,7 @@
 import 'c.dart';
 export '../333/d.dart';
 part '../a.dart';
-part '${convertAbsolutePathToUri('/absolute/uri.dart')}';
+part '${toUriStr('/absolute/uri.dart')}';
 ''');
   }
 
diff --git a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
index 042fdcc..14f3924 100644
--- a/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
+++ b/pkg/analysis_server/test/services/refactoring/rename_local_test.dart
@@ -488,12 +488,12 @@
     await indexUnit('/home/test/lib/test2.dart', '''
 library test2;
 class A {
-  void foo({int test: 1}) {
+  void foo({int test}) {
     print(test);
   }
 }
 class B extends A {
-  void foo({int test: 2}) {
+  void foo({int test}) {
     print(test);
   }
 }
@@ -506,7 +506,7 @@
   new C().foo(test: 30);
 }
 class C extends A {
-  void foo({int test: 3}) {
+  void foo({int test}) {
     print(test);
   }
 }
@@ -524,7 +524,7 @@
   new C().foo(newName: 30);
 }
 class C extends A {
-  void foo({int newName: 3}) {
+  void foo({int newName}) {
     print(newName);
   }
 }
@@ -532,12 +532,12 @@
     assertFileChangeResult('/home/test/lib/test2.dart', '''
 library test2;
 class A {
-  void foo({int newName: 1}) {
+  void foo({int newName}) {
     print(newName);
   }
 }
 class B extends A {
-  void foo({int newName: 2}) {
+  void foo({int newName}) {
     print(newName);
   }
 }
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
new file mode 100644
index 0000000..ecf6d0cd
--- /dev/null
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestion_sets_test.dart
@@ -0,0 +1,257 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_suggestions_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(AvailableSuggestionSetsTest);
+  });
+}
+
+@reflectiveTest
+class AvailableSuggestionSetsTest extends AvailableSuggestionsBase {
+  test_notifications_whenFileChanges() async {
+    var path = convertPath('/home/test/lib/a.dart');
+    var uriStr = 'package:test/a.dart';
+
+    // No file initially, so no set.
+    expect(uriToSetMap.keys, isNot(contains(uriStr)));
+
+    // Create the file, should get the set.
+    {
+      newFile(path, content: r'''
+class A {}
+''');
+      var set = await waitForSetWithUri(uriStr);
+      expect(set.items.map((d) => d.label), contains('A'));
+    }
+
+    // Update the file, should get the updated set.
+    {
+      newFile(path, content: r'''
+class B {}
+''');
+      removeSet(uriStr);
+      var set = await waitForSetWithUri(uriStr);
+      expect(set.items.map((d) => d.label), contains('B'));
+    }
+
+    // Delete the file, the set should be removed.
+    deleteFile(path);
+    waitForSetWithUriRemoved(uriStr);
+  }
+
+  test_suggestion_class() async {
+    var path = convertPath('/home/test/lib/a.dart');
+    var uriStr = 'package:test/a.dart';
+
+    newFile(path, content: r'''
+class A {}
+''');
+
+    var set = await waitForSetWithUri(uriStr);
+    assertJsonText(_getSuggestion(set, 'A'), '''
+{
+  "label": "A",
+  "element": {
+    "kind": "CLASS",
+    "name": "A",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 6,
+      "length": 0,
+      "startLine": 1,
+      "startColumn": 7
+    },
+    "flags": 0
+  },
+  "relevanceTags": [
+    "package:test/a.dart::A"
+  ]
+}
+''');
+  }
+
+  test_suggestion_enum() async {
+    var path = convertPath('/home/test/lib/a.dart');
+    var uriStr = 'package:test/a.dart';
+
+    newFile(path, content: r'''
+enum MyEnum {
+  aaa,
+  bbb,
+}
+''');
+
+    var set = await waitForSetWithUri(uriStr);
+    assertJsonText(_getSuggestion(set, 'MyEnum'), '''
+{
+  "label": "MyEnum",
+  "element": {
+    "kind": "ENUM",
+    "name": "MyEnum",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 5,
+      "length": 0,
+      "startLine": 1,
+      "startColumn": 6
+    },
+    "flags": 0
+  },
+  "relevanceTags": [
+    "package:test/a.dart::MyEnum"
+  ]
+}
+''');
+    assertJsonText(_getSuggestion(set, 'MyEnum.aaa'), '''
+{
+  "label": "MyEnum.aaa",
+  "element": {
+    "kind": "ENUM_CONSTANT",
+    "name": "aaa",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 16,
+      "length": 0,
+      "startLine": 2,
+      "startColumn": 3
+    },
+    "flags": 0
+  },
+  "relevanceTags": [
+    "package:test/a.dart::MyEnum"
+  ]
+}
+''');
+    assertJsonText(_getSuggestion(set, 'MyEnum.bbb'), '''
+{
+  "label": "MyEnum.bbb",
+  "element": {
+    "kind": "ENUM_CONSTANT",
+    "name": "bbb",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 23,
+      "length": 0,
+      "startLine": 3,
+      "startColumn": 3
+    },
+    "flags": 0
+  },
+  "relevanceTags": [
+    "package:test/a.dart::MyEnum"
+  ]
+}
+''');
+  }
+
+  test_suggestion_topLevelVariable() async {
+    var path = convertPath('/home/test/lib/a.dart');
+    var uriStr = 'package:test/a.dart';
+
+    newFile(path, content: r'''
+var boolV = false;
+var intV = 0;
+var doubleV = 0.1;
+var stringV = 'hi';
+''');
+
+    var set = await waitForSetWithUri(uriStr);
+    assertJsonText(_getSuggestion(set, 'boolV'), '''
+{
+  "label": "boolV",
+  "element": {
+    "kind": "TOP_LEVEL_VARIABLE",
+    "name": "boolV",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 4,
+      "length": 0,
+      "startLine": 1,
+      "startColumn": 5
+    },
+    "flags": 0,
+    "returnType": ""
+  },
+  "relevanceTags": [
+    "dart:core::bool"
+  ]
+}
+''');
+    assertJsonText(_getSuggestion(set, 'intV'), '''
+{
+  "label": "intV",
+  "element": {
+    "kind": "TOP_LEVEL_VARIABLE",
+    "name": "intV",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 23,
+      "length": 0,
+      "startLine": 2,
+      "startColumn": 5
+    },
+    "flags": 0,
+    "returnType": ""
+  },
+  "relevanceTags": [
+    "dart:core::int"
+  ]
+}
+''');
+    assertJsonText(_getSuggestion(set, 'doubleV'), '''
+{
+  "label": "doubleV",
+  "element": {
+    "kind": "TOP_LEVEL_VARIABLE",
+    "name": "doubleV",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 37,
+      "length": 0,
+      "startLine": 3,
+      "startColumn": 5
+    },
+    "flags": 0,
+    "returnType": ""
+  },
+  "relevanceTags": [
+    "dart:core::double"
+  ]
+}
+''');
+    assertJsonText(_getSuggestion(set, 'stringV'), '''
+{
+  "label": "stringV",
+  "element": {
+    "kind": "TOP_LEVEL_VARIABLE",
+    "name": "stringV",
+    "location": {
+      "file": ${jsonOfPath(path)},
+      "offset": 56,
+      "length": 0,
+      "startLine": 4,
+      "startColumn": 5
+    },
+    "flags": 0,
+    "returnType": ""
+  },
+  "relevanceTags": [
+    "dart:core::String"
+  ]
+}
+''');
+  }
+
+  static AvailableSuggestion _getSuggestion(
+      AvailableSuggestionSet set, String label) {
+    return set.items.singleWhere((s) => s.label == label);
+  }
+}
diff --git a/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.dart
new file mode 100644
index 0000000..97064f5
--- /dev/null
+++ b/pkg/analysis_server/test/src/domains/completion/available_suggestions_base.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.
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:analysis_server/protocol/protocol.dart';
+import 'package:analysis_server/protocol/protocol_constants.dart';
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/domain_completion.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../analysis_abstract.dart';
+import '../../../constants.dart';
+
+@reflectiveTest
+class AvailableSuggestionsBase extends AbstractAnalysisTest {
+  final Map<int, AvailableSuggestionSet> idToSetMap = {};
+  final Map<String, AvailableSuggestionSet> uriToSetMap = {};
+  final Map<String, CompletionResultsParams> idToSuggestions = {};
+
+  void assertJsonText(Object object, String expected) {
+    expected = expected.trimRight();
+    var actual = JsonEncoder.withIndent('  ').convert(object);
+    if (actual != expected) {
+      print('-----');
+      print(actual);
+      print('-----');
+    }
+    expect(actual, expected);
+  }
+
+  String jsonOfPath(String path) {
+    path = convertPath(path);
+    return json.encode(path);
+  }
+
+  @override
+  void processNotification(Notification notification) {
+    super.processNotification(notification);
+    if (notification.event == COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS) {
+      var params = CompletionAvailableSuggestionsParams.fromNotification(
+        notification,
+      );
+      for (var set in params.changedLibraries) {
+        idToSetMap[set.id] = set;
+        uriToSetMap[set.uri] = set;
+      }
+      for (var id in params.removedLibraries) {
+        var set = idToSetMap.remove(id);
+        uriToSetMap.remove(set?.uri);
+      }
+    } else if (notification.event == COMPLETION_RESULTS) {
+      var params = CompletionResultsParams.fromNotification(notification);
+      idToSuggestions[params.id] = params;
+    }
+  }
+
+  /// Remove the set with the given [uri].
+  /// The set must be already received.
+  void removeSet(String uri) {
+    var set = uriToSetMap.remove(uri);
+    expect(set, isNotNull);
+
+    idToSetMap.remove(set.id);
+  }
+
+  @override
+  void setUp() {
+    super.setUp();
+    projectPath = convertPath('/home');
+    testFile = convertPath('/home/test/lib/test.dart');
+
+    newFile('/home/test/pubspec.yaml', content: '');
+    newFile('/home/test/.packages', content: '''
+test:${toUri('/home/test/lib')}
+''');
+
+    createProject();
+    handler = server.handlers.whereType<CompletionDomainHandler>().single;
+    _setCompletionSubscriptions([CompletionService.AVAILABLE_SUGGESTION_SETS]);
+  }
+
+  Future<CompletionResultsParams> waitForGetSuggestions(String id) async {
+    while (true) {
+      var result = idToSuggestions[id];
+      if (result != null) {
+        return result;
+      }
+      await Future.delayed(const Duration(milliseconds: 1));
+    }
+  }
+
+  Future<AvailableSuggestionSet> waitForSetWithUri(String uri) async {
+    while (true) {
+      var result = uriToSetMap[uri];
+      if (result != null) {
+        return result;
+      }
+      await Future.delayed(const Duration(milliseconds: 1));
+    }
+  }
+
+  Future<void> waitForSetWithUriRemoved(String uri) async {
+    while (true) {
+      var result = uriToSetMap[uri];
+      if (result == null) {
+        return;
+      }
+      await Future.delayed(const Duration(milliseconds: 1));
+    }
+  }
+
+  void _setCompletionSubscriptions(List<CompletionService> subscriptions) {
+    handleSuccessfulRequest(
+      CompletionSetSubscriptionsParams(subscriptions).toRequest('0'),
+    );
+  }
+}
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
new file mode 100644
index 0000000..84fdccb
--- /dev/null
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestion_details_test.dart
@@ -0,0 +1,136 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analysis_server/protocol/protocol_generated.dart';
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:meta/meta.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_suggestions_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GetSuggestionDetailsTest);
+  });
+}
+
+@reflectiveTest
+class GetSuggestionDetailsTest extends AvailableSuggestionsBase {
+  test_enum() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+enum MyEnum {
+  aaa, bbb
+}
+''');
+    addTestFile(r'''
+main() {} // ref
+''');
+
+    var set = await waitForSetWithUri('package:test/a.dart');
+    var result = await _getSuggestionDetails(
+      id: set.id,
+      label: 'MyEnum.aaa',
+      offset: testCode.indexOf('} // ref'),
+    );
+
+    expect(result.completion, 'MyEnum.aaa');
+    _assertTestFileChange(result.change, r'''
+import 'package:test/a.dart';
+
+main() {} // ref
+''');
+  }
+
+  test_existingImport() async {
+    addTestFile(r'''
+import 'dart:math';
+
+main() {} // ref
+''');
+
+    var mathSet = await waitForSetWithUri('dart:math');
+    var result = await _getSuggestionDetails(
+      id: mathSet.id,
+      label: 'sin',
+      offset: testCode.indexOf('} // ref'),
+    );
+
+    expect(result.completion, 'sin');
+    _assertEmptyChange(result.change);
+  }
+
+  test_existingImport_prefixed() async {
+    addTestFile(r'''
+import 'dart:math' as math;
+
+main() {} // ref
+''');
+
+    var mathSet = await waitForSetWithUri('dart:math');
+    var result = await _getSuggestionDetails(
+      id: mathSet.id,
+      label: 'sin',
+      offset: testCode.indexOf('} // ref'),
+    );
+
+    expect(result.completion, 'math.sin');
+    _assertEmptyChange(result.change);
+  }
+
+  test_newImport() async {
+    addTestFile(r'''
+main() {} // ref
+''');
+
+    var mathSet = await waitForSetWithUri('dart:math');
+    var result = await _getSuggestionDetails(
+      id: mathSet.id,
+      label: 'sin',
+      offset: testCode.indexOf('} // ref'),
+    );
+
+    expect(result.completion, 'sin');
+    _assertTestFileChange(result.change, r'''
+import 'dart:math';
+
+main() {} // ref
+''');
+  }
+
+  void _assertEmptyChange(SourceChange change) {
+    expect(change.edits, isEmpty);
+  }
+
+  void _assertTestFileChange(SourceChange change, String expected) {
+    var fileEdits = change.edits;
+    expect(fileEdits, hasLength(1));
+
+    var fileEdit = fileEdits[0];
+    expect(fileEdit.file, testFile);
+
+    var edits = fileEdit.edits;
+    expect(SourceEdit.applySequence(testCode, edits), expected);
+  }
+
+  Future<CompletionGetSuggestionDetailsResult> _getSuggestionDetails({
+    String file,
+    @required int id,
+    @required String label,
+    @required int offset,
+  }) async {
+    file ??= testFile;
+    var response = await waitResponse(
+      CompletionGetSuggestionDetailsParams(
+        file,
+        id,
+        label,
+        offset,
+      ).toRequest('0'),
+    );
+    return CompletionGetSuggestionDetailsResult.fromResponse(response);
+  }
+}
diff --git a/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
new file mode 100644
index 0000000..0de95fdf
--- /dev/null
+++ b/pkg/analysis_server/test/src/domains/completion/get_suggestions_available_test.dart
@@ -0,0 +1,226 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/protocol_server.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_suggestions_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(GetSuggestionAvailableTest);
+  });
+}
+
+@reflectiveTest
+class GetSuggestionAvailableTest extends AvailableSuggestionsBase {
+  test_dart() async {
+    addTestFile('');
+    var mathSet = await waitForSetWithUri('dart:math');
+    var asyncSet = await waitForSetWithUri('dart:async');
+
+    var results = await _getSuggestions(testFile, 0);
+    expect(results.includedSuggestionKinds, isNotEmpty);
+
+    var includedIdSet = results.includedSuggestionSets.map((set) => set.id);
+    expect(includedIdSet, contains(mathSet.id));
+    expect(includedIdSet, contains(asyncSet.id));
+  }
+
+  test_includedSuggestionKinds_type() async {
+    addTestFile(r'''
+class X extends {} // ref
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf('{} // ref'),
+    );
+
+    expect(
+      results.includedSuggestionKinds,
+      unorderedEquals([
+        ElementKind.CLASS,
+        ElementKind.CLASS_TYPE_ALIAS,
+        ElementKind.ENUM,
+        ElementKind.FUNCTION_TYPE_ALIAS,
+        ElementKind.MIXIN,
+      ]),
+    );
+  }
+
+  test_includedSuggestionKinds_value() async {
+    addTestFile(r'''
+main() {
+  print(); // ref
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf('); // ref'),
+    );
+
+    expect(
+      results.includedSuggestionKinds,
+      unorderedEquals([
+        ElementKind.CLASS,
+        ElementKind.CLASS_TYPE_ALIAS,
+        ElementKind.ENUM,
+        ElementKind.ENUM_CONSTANT,
+        ElementKind.FUNCTION,
+        ElementKind.FUNCTION_TYPE_ALIAS,
+        ElementKind.MIXIN,
+        ElementKind.TOP_LEVEL_VARIABLE,
+      ]),
+    );
+  }
+
+  test_inHtml() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+
+    var path = convertPath('/home/test/doc/a.html');
+    newFile(path, content: '<html></html>');
+
+    await waitResponse(
+      CompletionGetSuggestionsParams(path, 0).toRequest('0'),
+    );
+    expect(serverErrors, isEmpty);
+  }
+
+  test_relevanceTags_enum() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+enum MyEnum {
+  aaa, bbb
+}
+''');
+    addTestFile(r'''
+import 'a.dart';
+
+void f(MyEnum e) {
+  e = // ref;
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf(' // ref'),
+    );
+
+    assertJsonText(results.includedSuggestionRelevanceTags, r'''
+[
+  {
+    "tag": "package:test/a.dart::MyEnum",
+    "relevanceBoost": 1100
+  }
+]
+''');
+  }
+
+  test_relevanceTags_location_argumentList_named() async {
+    addTestFile(r'''
+void foo({int a, String b}) {}
+
+main() {
+  foo(b: ); // ref
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf('); // ref'),
+    );
+
+    assertJsonText(results.includedSuggestionRelevanceTags, r'''
+[
+  {
+    "tag": "dart:core::String",
+    "relevanceBoost": 10
+  }
+]
+''');
+  }
+
+  test_relevanceTags_location_argumentList_positional() async {
+    addTestFile(r'''
+void foo(double a) {}
+
+main() {
+  foo(); // ref
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf('); // ref'),
+    );
+
+    assertJsonText(results.includedSuggestionRelevanceTags, r'''
+[
+  {
+    "tag": "dart:core::double",
+    "relevanceBoost": 10
+  }
+]
+''');
+  }
+
+  test_relevanceTags_location_assignment() async {
+    addTestFile(r'''
+main() {
+  int v;
+  v = // ref;
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf(' // ref'),
+    );
+
+    assertJsonText(results.includedSuggestionRelevanceTags, r'''
+[
+  {
+    "tag": "dart:core::int",
+    "relevanceBoost": 10
+  }
+]
+''');
+  }
+
+  test_relevanceTags_location_listLiteral() async {
+    addTestFile(r'''
+main() {
+  var v = [0, ]; // ref
+}
+''');
+
+    var results = await _getSuggestions(
+      testFile,
+      testCode.indexOf(']; // ref'),
+    );
+
+    assertJsonText(results.includedSuggestionRelevanceTags, r'''
+[
+  {
+    "tag": "dart:core::int",
+    "relevanceBoost": 10
+  }
+]
+''');
+  }
+
+  Future<CompletionResultsParams> _getSuggestions(
+    String path,
+    int offset,
+  ) async {
+    var response = CompletionGetSuggestionsResult.fromResponse(
+      await waitResponse(
+        CompletionGetSuggestionsParams(path, offset).toRequest('0'),
+      ),
+    );
+    return await waitForGetSuggestions(response.id);
+  }
+}
diff --git a/pkg/analysis_server/test/src/domains/completion/test_all.dart b/pkg/analysis_server/test/src/domains/completion/test_all.dart
new file mode 100644
index 0000000..066f43c
--- /dev/null
+++ b/pkg/analysis_server/test/src/domains/completion/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'available_suggestion_sets_test.dart' as available_suggestion_sets;
+import 'get_suggestion_details_test.dart' as get_suggestion_details;
+import 'get_suggestions_available_test.dart' as get_suggestions_available;
+
+main() {
+  defineReflectiveSuite(() {
+    available_suggestion_sets.main();
+    get_suggestion_details.main();
+    get_suggestions_available.main();
+  });
+}
diff --git a/pkg/analysis_server/test/src/domains/execution/completion_test.dart b/pkg/analysis_server/test/src/domains/execution/completion_test.dart
index 37ff7fa..c3d9f15 100644
--- a/pkg/analysis_server/test/src/domains/execution/completion_test.dart
+++ b/pkg/analysis_server/test/src/domains/execution/completion_test.dart
@@ -60,8 +60,7 @@
     code = code.replaceAll('^', '');
 
     var computer = new RuntimeCompletionComputer(
-        resourceProvider,
-        fileContentOverlay,
+        overlayResourceProvider,
         driver,
         code,
         codeOffset,
diff --git a/pkg/analysis_server/test/src/domains/test_all.dart b/pkg/analysis_server/test/src/domains/test_all.dart
index ea67387..b936c18 100644
--- a/pkg/analysis_server/test/src/domains/test_all.dart
+++ b/pkg/analysis_server/test/src/domains/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'execution/test_all.dart' as execution_test;
+import 'completion/test_all.dart' as completion;
+import 'execution/test_all.dart' as execution;
 
 main() {
   defineReflectiveSuite(() {
-    execution_test.main();
+    completion.main();
+    execution.main();
   });
 }
diff --git a/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
new file mode 100644
index 0000000..88c6a34
--- /dev/null
+++ b/pkg/analysis_server/test/src/nullability/migration_visitor_test.dart
@@ -0,0 +1,965 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/conditional_discard.dart';
+import 'package:analysis_server/src/nullability/constraint_gatherer.dart';
+import 'package:analysis_server/src/nullability/constraint_variable_gatherer.dart';
+import 'package:analysis_server/src/nullability/decorated_type.dart';
+import 'package:analysis_server/src/nullability/expression_checks.dart';
+import 'package:analysis_server/src/nullability/transitional_api.dart';
+import 'package:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/generated/resolver.dart';
+import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../abstract_single_unit.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstraintGathererTest);
+    defineReflectiveTests(ConstraintVariableGathererTest);
+  });
+}
+
+@reflectiveTest
+class ConstraintGathererTest extends ConstraintsTestBase {
+  @override
+  final _Constraints constraints = _Constraints();
+
+  /// Checks that a constraint was recorded with a left hand side of
+  /// [conditions] and a right hand side of [consequence].
+  void assertConstraint(
+      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence) {
+    expect(constraints._clauses,
+        contains(_Clause(conditions.toSet(), consequence)));
+  }
+
+  /// Checks that no constraint was recorded with a right hand side of
+  /// [consequence].
+  void assertNoConstraints(ConstraintVariable consequence) {
+    expect(
+        constraints._clauses,
+        isNot(contains(
+            predicate((_Clause clause) => clause.consequence == consequence))));
+  }
+
+  /// Gets the [ExpressionChecks] associated with the expression whose text
+  /// representation is [text], or `null` if the expression has no
+  /// [ExpressionChecks] associated with it.
+  ExpressionChecks checkExpression(String text) {
+    return _variables.checkExpression(findNode.expression(text));
+  }
+
+  /// Gets the [DecoratedType] associated with the expression whose text
+  /// representation is [text], or `null` if the expression has no
+  /// [DecoratedType] associated with it.
+  DecoratedType decoratedExpressionType(String text) {
+    return _variables.decoratedExpressionType(findNode.expression(text));
+  }
+
+  test_always() async {
+    await analyze('');
+
+    // No clause is needed for `always`; it is assigned the value `true` before
+    // solving begins.
+    assertNoConstraints(ConstraintVariable.always);
+    assert(ConstraintVariable.always.value, isTrue);
+  }
+
+  test_assert_demonstrates_non_null_intent() async {
+    await analyze('''
+void f(int i) {
+  assert(i != null);
+}
+''');
+
+    assertConstraint([], decoratedTypeAnnotation('int i').nonNullIntent);
+  }
+
+  test_binaryExpression_add_left_check() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int i').nullable],
+        checkExpression('i +').nullCheck);
+  }
+
+  test_binaryExpression_add_left_check_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => i + j;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('Int i').nullable],
+        checkExpression('i +').nullCheck);
+  }
+
+  test_binaryExpression_add_result_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => i + j;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('Int operator+').nullable],
+        decoratedTypeAnnotation('Int f').nullable);
+  }
+
+  test_binaryExpression_add_result_not_null() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('int f').nullable);
+  }
+
+  test_binaryExpression_add_right_check() async {
+    await analyze('''
+int f(int i, int j) => i + j;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int j').nullable],
+        checkExpression('j;').nullCheck);
+  }
+
+  test_binaryExpression_add_right_check_custom() async {
+    await analyze('''
+class Int {
+  Int operator+(Int other) => this;
+}
+Int f(Int i, Int j) => i + j;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('Int j').nullable],
+        decoratedTypeAnnotation('Int other').nullable);
+  }
+
+  test_binaryExpression_equal() async {
+    await analyze('''
+bool f(int i, int j) => i == j;
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('bool f').nullable);
+  }
+
+  test_conditionalExpression_condition_check() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  return (b ? i : j);
+}
+''');
+
+    var nullable_b = decoratedTypeAnnotation('bool b').nullable;
+    var check_b = checkExpression('b ?').nullCheck;
+    assertConstraint([nullable_b], check_b);
+  }
+
+  test_conditionalExpression_general() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  return (b ? i : j);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_j = decoratedTypeAnnotation('int j').nullable;
+    var nullable_i_or_nullable_j = _mockOr(nullable_i, nullable_j);
+    var nullable_conditional = decoratedExpressionType('(b ?').nullable;
+    var nullable_return = decoratedTypeAnnotation('int f').nullable;
+    assertConstraint([nullable_i], nullable_conditional);
+    assertConstraint([nullable_j], nullable_conditional);
+    assertConstraint([nullable_conditional], nullable_i_or_nullable_j);
+    assertConstraint([nullable_conditional], nullable_return);
+  }
+
+  test_conditionalExpression_left_non_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? (throw i) : i);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_conditional = decoratedExpressionType('(b ?').nullable;
+    expect(nullable_conditional, same(nullable_i));
+  }
+
+  test_conditionalExpression_left_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? null : i);
+}
+''');
+
+    var nullable_conditional = decoratedExpressionType('(b ?').nullable;
+    expect(nullable_conditional, same(ConstraintVariable.always));
+  }
+
+  test_conditionalExpression_right_non_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? i : (throw i));
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_conditional = decoratedExpressionType('(b ?').nullable;
+    expect(nullable_conditional, same(nullable_i));
+  }
+
+  test_conditionalExpression_right_null() async {
+    await analyze('''
+int f(bool b, int i) {
+  return (b ? i : null);
+}
+''');
+
+    var nullable_conditional = decoratedExpressionType('(b ?').nullable;
+    expect(nullable_conditional, same(ConstraintVariable.always));
+  }
+
+  test_functionDeclaration_expression_body() async {
+    await analyze('''
+int/*1*/ f(int/*2*/ i) => i;
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int/*2*/').nullable],
+        decoratedTypeAnnotation('int/*1*/').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_default_notNull() async {
+    await analyze('''
+void f({int i = 1}) {}
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_default_null() async {
+    await analyze('''
+void f({int i = null}) {}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_no_default_assume_nullable() async {
+    await analyze('''
+void f({int i}) {}
+''',
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+
+    assertConstraint([], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_no_default_assume_required() async {
+    await analyze('''
+void f({int i}) {}
+''',
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_no_default_required_assume_nullable() async {
+    addMetaPackage();
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required int i}) {}
+''',
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_named_no_default_required_assume_required() async {
+    addMetaPackage();
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required int i}) {}
+''',
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_default_notNull() async {
+    await analyze('''
+void f([int i = 1]) {}
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_default_null() async {
+    await analyze('''
+void f([int i = null]) {}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_no_default() async {
+    await analyze('''
+void f([int i]) {}
+''');
+
+    assertConstraint([], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionDeclaration_parameter_positionalOptional_no_default_assume_required() async {
+    // Note: the `assumeRequired` behavior shouldn't affect the behavior here
+    // because it only affects named parameters.
+    await analyze('''
+void f([int i]) {}
+''',
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+
+    assertConstraint([], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionInvocation_parameter_fromLocalParameter() async {
+    await analyze('''
+void f(int/*1*/ i) {}
+void test(int/*2*/ i) {
+  f(i);
+}
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int/*2*/').nullable],
+        decoratedTypeAnnotation('int/*1*/').nullable);
+  }
+
+  test_functionInvocation_parameter_named() async {
+    await analyze('''
+void f({int i: 0}) {}
+void g(int j) {
+  f(i: j);
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_j = decoratedTypeAnnotation('int j').nullable;
+    assertConstraint([nullable_j], nullable_i);
+  }
+
+  test_functionInvocation_parameter_named_missing() async {
+    await analyze('''
+void f({int i}) {}
+void g() {
+  f();
+}
+''');
+    var optional_i = possiblyOptionalParameter('int i');
+    assertConstraint([], optional_i);
+  }
+
+  test_functionInvocation_parameter_named_missing_required() async {
+    addMetaPackage();
+    verifyNoTestUnitErrors = false;
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required int i}) {}
+void g() {
+  f();
+}
+''');
+    // The call at `f()` is presumed to be in error; no constraint is recorded.
+    var optional_i = possiblyOptionalParameter('int i');
+    expect(optional_i, isNull);
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    assertNoConstraints(nullable_i);
+  }
+
+  test_functionInvocation_parameter_null() async {
+    await analyze('''
+void f(int i) {}
+void test() {
+  f(null);
+}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_functionInvocation_return() async {
+    await analyze('''
+int/*1*/ f() => 0;
+int/*2*/ g() {
+  return f();
+}
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int/*1*/').nullable],
+        decoratedTypeAnnotation('int/*2*/').nullable);
+  }
+
+  test_if_condition() async {
+    await analyze('''
+void f(bool b) {
+  if (b) {}
+}
+''');
+
+    assertConstraint([(decoratedTypeAnnotation('bool b').nullable)],
+        checkExpression('b) {}').nullCheck);
+  }
+
+  test_if_conditional_control_flow_after() async {
+    // Asserts after ifs don't demonstrate non-null intent.
+    // TODO(paulberry): if both branches complete normally, they should.
+    await analyze('''
+void f(bool b, int i) {
+  if (b) return;
+  assert(i != null);
+}
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('int i').nonNullIntent);
+  }
+
+  test_if_conditional_control_flow_within() async {
+    // Asserts inside ifs don't demonstrate non-null intent.
+    await analyze('''
+void f(bool b, int i) {
+  if (b) {
+    assert(i != null);
+  } else {
+    assert(i != null);
+  }
+}
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('int i').nonNullIntent);
+  }
+
+  test_if_guard_equals_null() async {
+    await analyze('''
+int f(int i, int j, int k) {
+  if (i == null) {
+    return j;
+  } else {
+    return k;
+  }
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_j = decoratedTypeAnnotation('int j').nullable;
+    var nullable_k = decoratedTypeAnnotation('int k').nullable;
+    var nullable_return = decoratedTypeAnnotation('int f').nullable;
+    assertConstraint([nullable_i, nullable_j], nullable_return);
+    assertConstraint([nullable_k], nullable_return);
+    var discard = statementDiscard('if (i == null)');
+    expect(discard.keepTrue, same(nullable_i));
+    expect(discard.keepFalse, same(ConstraintVariable.always));
+    expect(discard.pureCondition, true);
+  }
+
+  test_if_simple() async {
+    await analyze('''
+int f(bool b, int i, int j) {
+  if (b) {
+    return i;
+  } else {
+    return j;
+  }
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_j = decoratedTypeAnnotation('int j').nullable;
+    var nullable_return = decoratedTypeAnnotation('int f').nullable;
+    assertConstraint([nullable_i], nullable_return);
+    assertConstraint([nullable_j], nullable_return);
+  }
+
+  test_if_without_else() async {
+    await analyze('''
+int f(bool b, int i) {
+  if (b) {
+    return i;
+  }
+  return 0;
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_return = decoratedTypeAnnotation('int f').nullable;
+    assertConstraint([nullable_i], nullable_return);
+  }
+
+  test_intLiteral() async {
+    await analyze('''
+int f() {
+  return 0;
+}
+''');
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_methodInvocation_parameter_contravariant() async {
+    await analyze('''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int> c, int i) {
+  c.f(i);
+}
+''');
+
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_c_t =
+        decoratedTypeAnnotation('C<int>').typeArguments[0].nullable;
+    var nullable_t = decoratedTypeAnnotation('T t').nullable;
+    var nullable_c_t_or_nullable_t = _mockOr(nullable_c_t, nullable_t);
+    assertConstraint([nullable_i], nullable_c_t_or_nullable_t);
+  }
+
+  test_methodInvocation_parameter_generic() async {
+    await analyze('''
+class C<T> {}
+void f(C<int/*1*/>/*2*/ c) {}
+void g(C<int/*3*/>/*4*/ c) {
+  f(c);
+}
+''');
+
+    assertConstraint([decoratedTypeAnnotation('int/*3*/').nullable],
+        decoratedTypeAnnotation('int/*1*/').nullable);
+    assertConstraint([decoratedTypeAnnotation('C<int/*3*/>/*4*/').nullable],
+        decoratedTypeAnnotation('C<int/*1*/>/*2*/').nullable);
+  }
+
+  test_methodInvocation_parameter_named() async {
+    await analyze('''
+class C {
+  void f({int i: 0}) {}
+}
+void g(C c, int j) {
+  c.f(i: j);
+}
+''');
+    var nullable_i = decoratedTypeAnnotation('int i').nullable;
+    var nullable_j = decoratedTypeAnnotation('int j').nullable;
+    assertConstraint([nullable_j], nullable_i);
+  }
+
+  test_methodInvocation_target_check() async {
+    await analyze('''
+class C {
+  void m() {}
+}
+void test(C c) {
+  c.m();
+}
+''');
+
+    assertConstraint([decoratedTypeAnnotation('C c').nullable],
+        checkExpression('c.m').nullCheck);
+  }
+
+  test_parenthesizedExpression() async {
+    await analyze('''
+int f() {
+  return (null);
+}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_return_implicit_null() async {
+    verifyNoTestUnitErrors = false;
+    await analyze('''
+int f() {
+  return;
+}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_return_null() async {
+    await analyze('''
+int f() {
+  return null;
+}
+''');
+
+    assertConstraint(
+        [ConstraintVariable.always], decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_stringLiteral() async {
+    // TODO(paulberry): also test string interpolations
+    await analyze('''
+String f() {
+  return 'x';
+}
+''');
+    assertNoConstraints(decoratedTypeAnnotation('String').nullable);
+  }
+
+  test_thisExpression() async {
+    await analyze('''
+class C {
+  C f() => this;
+}
+''');
+
+    assertNoConstraints(decoratedTypeAnnotation('C f').nullable);
+  }
+
+  test_throwExpression() async {
+    await analyze('''
+int f() {
+  return throw null;
+}
+''');
+    assertNoConstraints(decoratedTypeAnnotation('int').nullable);
+  }
+
+  test_typeName() async {
+    await analyze('''
+Type f() {
+  return int;
+}
+''');
+    assertNoConstraints(decoratedTypeAnnotation('Type').nullable);
+  }
+
+  /// Creates a variable representing the disjunction of [a] and [b] solely for
+  /// the purpose of inspecting constraint equations in unit tests.  No
+  /// additional constraints will be recorded in [_constraints] as a consequence
+  /// of creating this variable.
+  ConstraintVariable _mockOr(ConstraintVariable a, ConstraintVariable b) =>
+      ConstraintVariable.or(_MockConstraints(), a, b);
+}
+
+abstract class ConstraintsTestBase extends MigrationVisitorTestBase {
+  Constraints get constraints;
+
+  /// Analyzes the given source code, producing constraint variables and
+  /// constraints for it.
+  @override
+  Future<CompilationUnit> analyze(String code,
+      {NullabilityMigrationAssumptions assumptions:
+          const NullabilityMigrationAssumptions()}) async {
+    var unit = await super.analyze(code);
+    unit.accept(ConstraintGatherer(
+        typeProvider, _variables, constraints, testSource, false, assumptions));
+    return unit;
+  }
+}
+
+@reflectiveTest
+class ConstraintVariableGathererTest extends MigrationVisitorTestBase {
+  /// Gets the [DecoratedType] associated with the function declaration whose
+  /// name matches [search].
+  DecoratedType decoratedFunctionType(String search) =>
+      _variables.decoratedElementType(
+          findNode.functionDeclaration(search).declaredElement);
+
+  test_interfaceType_nullable() async {
+    await analyze('''
+void f(int? x) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('int?');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.nullable, same(ConstraintVariable.always));
+  }
+
+  test_interfaceType_typeParameter() async {
+    await analyze('''
+void f(List<int> x) {}
+''');
+    var decoratedListType = decoratedTypeAnnotation('List<int>');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedListType));
+    expect(decoratedListType.nullable, isNotNull);
+    var decoratedIntType = decoratedTypeAnnotation('int');
+    expect(decoratedListType.typeArguments[0], same(decoratedIntType));
+    expect(decoratedIntType.nullable, isNotNull);
+  }
+
+  test_topLevelFunction_parameterType_implicit_dynamic() async {
+    await analyze('''
+void f(x) {}
+''');
+    var decoratedType =
+        _variables.decoratedElementType(findNode.simple('x').staticElement);
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.type.isDynamic, isTrue);
+    expect(decoratedType.nullable, same(ConstraintVariable.always));
+  }
+
+  test_topLevelFunction_parameterType_named_no_default() async {
+    await analyze('''
+void f({String s}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+    expect(decoratedType.nullable, isNot(same(ConstraintVariable.always)));
+    expect(functionType.namedParameterOptionalVariables['s'],
+        same(decoratedType.nullable));
+  }
+
+  test_topLevelFunction_parameterType_named_no_default_required() async {
+    addMetaPackage();
+    await analyze('''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+    expect(decoratedType.nullable, isNot(same(ConstraintVariable.always)));
+    expect(functionType.namedParameterOptionalVariables['s'], isNull);
+  }
+
+  test_topLevelFunction_parameterType_named_with_default() async {
+    await analyze('''
+void f({String s: 'x'}) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('String');
+    var functionType = decoratedFunctionType('f');
+    expect(functionType.namedParameters['s'], same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+    expect(functionType.namedParameterOptionalVariables['s'],
+        same(ConstraintVariable.always));
+  }
+
+  test_topLevelFunction_parameterType_positionalOptional() async {
+    await analyze('''
+void f([int i]) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+  }
+
+  test_topLevelFunction_parameterType_simple() async {
+    await analyze('''
+void f(int i) {}
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').positionalParameters[0],
+        same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+    expect(decoratedType.nonNullIntent, isNotNull);
+  }
+
+  test_topLevelFunction_returnType_implicit_dynamic() async {
+    await analyze('''
+f() {}
+''');
+    var decoratedType = decoratedFunctionType('f').returnType;
+    expect(decoratedType.type.isDynamic, isTrue);
+    expect(decoratedType.nullable, same(ConstraintVariable.always));
+  }
+
+  test_topLevelFunction_returnType_simple() async {
+    await analyze('''
+int f() => 0;
+''');
+    var decoratedType = decoratedTypeAnnotation('int');
+    expect(decoratedFunctionType('f').returnType, same(decoratedType));
+    expect(decoratedType.nullable, isNotNull);
+  }
+}
+
+class MigrationVisitorTestBase extends AbstractSingleUnitTest {
+  final _variables = _Variables();
+
+  FindNode findNode;
+
+  TypeProvider get typeProvider => testAnalysisResult.typeProvider;
+
+  Future<CompilationUnit> analyze(String code,
+      {NullabilityMigrationAssumptions assumptions:
+          const NullabilityMigrationAssumptions()}) async {
+    await resolveTestUnit(code);
+    testUnit.accept(
+        ConstraintVariableGatherer(_variables, testSource, false, assumptions));
+    findNode = FindNode(code, testUnit);
+    return testUnit;
+  }
+
+  /// Gets the [DecoratedType] associated with the type annotation whose text
+  /// is [text].
+  DecoratedType decoratedTypeAnnotation(String text) {
+    return _variables.decoratedTypeAnnotation(findNode.typeAnnotation(text));
+  }
+
+  ConstraintVariable possiblyOptionalParameter(String text) {
+    return _variables
+        .possiblyOptionalParameter(findNode.defaultParameter(text));
+  }
+
+  @override
+  void setUp() {
+    createAnalysisOptionsFile(experiments: [EnableString.non_nullable]);
+    super.setUp();
+  }
+
+  /// Gets the [ConditionalDiscard] information associated with the statement
+  /// whose text is [text].
+  ConditionalDiscard statementDiscard(String text) {
+    return _variables.conditionalDiscard(findNode.statement(text));
+  }
+}
+
+/// Mock representation of a constraint equation that is not connected to a
+/// constraint solver.  We use this to confirm that analysis produces the
+/// correct constraint equations.
+///
+/// [hashCode] and equality are implemented using [toString] for simplicity.
+class _Clause {
+  final Set<ConstraintVariable> conditions;
+  final ConstraintVariable consequence;
+
+  _Clause(this.conditions, this.consequence);
+
+  @override
+  int get hashCode => toString().hashCode;
+
+  @override
+  bool operator ==(Object other) =>
+      other is _Clause && toString() == other.toString();
+
+  @override
+  String toString() {
+    String lhs;
+    if (conditions.isNotEmpty) {
+      var sortedConditionStrings = conditions.map((v) => v.toString()).toList()
+        ..sort();
+      lhs = sortedConditionStrings.join(' & ') + ' => ';
+    } else {
+      lhs = '';
+    }
+    String rhs = consequence.toString();
+    return lhs + rhs;
+  }
+}
+
+/// Mock representation of a constraint solver that does not actually do any
+/// solving.  We use this to confirm that analysis produced the correct
+/// constraint equations.
+class _Constraints extends Constraints {
+  final _clauses = <_Clause>[];
+
+  @override
+  void record(
+      Iterable<ConstraintVariable> conditions, ConstraintVariable consequence) {
+    _clauses.add(_Clause(conditions.toSet(), consequence));
+  }
+}
+
+/// Mock implementation of [Constraints] that doesn't record any constraints.
+class _MockConstraints implements Constraints {
+  @override
+  void record(Iterable<ConstraintVariable> conditions,
+      ConstraintVariable consequence) {}
+}
+
+/// Mock representation of constraint variables.
+class _Variables extends Variables {
+  final _conditionalDiscard = <AstNode, ConditionalDiscard>{};
+
+  final _decoratedExpressionTypes = <Expression, DecoratedType>{};
+
+  final _decoratedTypeAnnotations = <TypeAnnotation, DecoratedType>{};
+
+  final _expressionChecks = <Expression, ExpressionChecks>{};
+
+  final _possiblyOptional = <DefaultFormalParameter, ConstraintVariable>{};
+
+  /// Gets the [ExpressionChecks] associated with the given [expression].
+  ExpressionChecks checkExpression(Expression expression) =>
+      _expressionChecks[_normalizeExpression(expression)];
+
+  /// Gets the [conditionalDiscard] associated with the given [expression].
+  ConditionalDiscard conditionalDiscard(AstNode node) =>
+      _conditionalDiscard[node];
+
+  /// Gets the [DecoratedType] associated with the given [expression].
+  DecoratedType decoratedExpressionType(Expression expression) =>
+      _decoratedExpressionTypes[_normalizeExpression(expression)];
+
+  /// Gets the [DecoratedType] associated with the given [typeAnnotation].
+  DecoratedType decoratedTypeAnnotation(TypeAnnotation typeAnnotation) =>
+      _decoratedTypeAnnotations[typeAnnotation];
+
+  /// Gets the [ConstraintVariable] associated with the possibility that
+  /// [parameter] may be optional.
+  ConstraintVariable possiblyOptionalParameter(
+          DefaultFormalParameter parameter) =>
+      _possiblyOptional[parameter];
+
+  @override
+  void recordConditionalDiscard(
+      Source source, AstNode node, ConditionalDiscard conditionalDiscard) {
+    _conditionalDiscard[node] = conditionalDiscard;
+    super.recordConditionalDiscard(source, node, conditionalDiscard);
+  }
+
+  void recordDecoratedExpressionType(Expression node, DecoratedType type) {
+    super.recordDecoratedExpressionType(node, type);
+    _decoratedExpressionTypes[_normalizeExpression(node)] = type;
+  }
+
+  void recordDecoratedTypeAnnotation(TypeAnnotation node, DecoratedType type) {
+    super.recordDecoratedTypeAnnotation(node, type);
+    _decoratedTypeAnnotations[node] = type;
+  }
+
+  @override
+  void recordExpressionChecks(Expression expression, ExpressionChecks checks) {
+    super.recordExpressionChecks(expression, checks);
+    _expressionChecks[_normalizeExpression(expression)] = checks;
+  }
+
+  @override
+  void recordPossiblyOptional(Source source, DefaultFormalParameter parameter,
+      ConstraintVariable variable) {
+    _possiblyOptional[parameter] = variable;
+    super.recordPossiblyOptional(source, parameter, variable);
+  }
+
+  /// Unwraps any parentheses surrounding [expression].
+  Expression _normalizeExpression(Expression expression) {
+    while (expression is ParenthesizedExpression) {
+      expression = (expression as ParenthesizedExpression).expression;
+    }
+    return expression;
+  }
+}
diff --git a/pkg/analysis_server/test/src/nullability/provisional_api_test.dart b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
new file mode 100644
index 0000000..8f9f86e
--- /dev/null
+++ b/pkg/analysis_server/test/src/nullability/provisional_api_test.dart
@@ -0,0 +1,611 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/nullability/provisional_api.dart';
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../abstract_context.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ProvisionalApiTest);
+    defineReflectiveTests(ProvisionalApiTestPermissive);
+    defineReflectiveTests(ProvisionalApiTestWithReset);
+  });
+}
+
+/// Tests of the provisional API.
+@reflectiveTest
+class ProvisionalApiTest extends ProvisionalApiTestBase
+    with ProvisionalApiTestCases {
+  @override
+  bool get usePermissiveMode => false;
+}
+
+/// Base class for provisional API tests.
+abstract class ProvisionalApiTestBase extends AbstractContextTest {
+  bool get usePermissiveMode;
+
+  /// Hook invoked after calling `prepareInput` on each input.
+  void _afterPrepare() {}
+
+  /// Verifies that migration of the files in [input] produces the output in
+  /// [expectedOutput].
+  Future<void> _checkMultipleFileChanges(
+      Map<String, String> input, Map<String, String> expectedOutput,
+      {NullabilityMigrationAssumptions assumptions:
+          const NullabilityMigrationAssumptions()}) async {
+    for (var path in input.keys) {
+      newFile(path, content: input[path]);
+    }
+    var listener = new TestMigrationListener();
+    var migration = NullabilityMigration(listener,
+        permissive: usePermissiveMode, assumptions: assumptions);
+    for (var path in input.keys) {
+      migration.prepareInput(await session.getResolvedUnit(path));
+    }
+    _afterPrepare();
+    for (var path in input.keys) {
+      migration.processInput(await session.getResolvedUnit(path));
+    }
+    migration.finish();
+    var sourceEdits = <String, List<SourceEdit>>{};
+    for (var fix in listener.fixes) {
+      var path = fix.source.fullName;
+      expect(expectedOutput.keys, contains(path));
+      (sourceEdits[path] ??= []).addAll(fix.sourceEdits);
+    }
+    for (var path in expectedOutput.keys) {
+      var sourceEditsForPath = sourceEdits[path] ?? [];
+      sourceEditsForPath.sort((a, b) => b.offset.compareTo(a.offset));
+      expect(SourceEdit.applySequence(input[path], sourceEditsForPath),
+          expectedOutput[path]);
+    }
+  }
+
+  /// Verifies that migraiton of the single file with the given [content]
+  /// produces the [expected] output.
+  Future<void> _checkSingleFileChanges(String content, String expected,
+      {NullabilityMigrationAssumptions assumptions:
+          const NullabilityMigrationAssumptions()}) async {
+    var sourcePath = convertPath('/home/test/lib/test.dart');
+    await _checkMultipleFileChanges(
+        {sourcePath: content}, {sourcePath: expected},
+        assumptions: assumptions);
+  }
+}
+
+/// Mixin containing test cases for the provisional API.
+mixin ProvisionalApiTestCases on ProvisionalApiTestBase {
+  test_data_flow_generic_inward() async {
+    var content = '''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int> c, int i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+
+    // Default behavior is to add nullability at the call site.  Rationale: this
+    // is correct in the common case where the generic parameter represents the
+    // type of an item in a container.  Also, if there are many callers that are
+    // largely independent, adding nullability to the callee would likely
+    // propagate to a field in the class, and thence (via return values of other
+    // methods) to most users of the class.  Whereas if we add nullability at
+    // the call site it's possible that other call sites won't need it.
+    //
+    // TODO(paulberry): possible improvement: detect that since C uses T in a
+    // contravariant way, and deduce that test should change to
+    // `void test(C<int?> c)`
+    var expected = '''
+class C<T> {
+  void f(T t) {}
+}
+void g(C<int?> c, int? i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_generic_inward_hint() async {
+    var content = '''
+class C<T> {
+  void f(T? t) {}
+}
+void g(C<int> c, int i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+
+    // The user may override the behavior shown in test_data_flow_generic_inward
+    // by explicitly marking f's use of T as nullable.  Since this makes g's
+    // call to f valid regardless of the type of c, c's type will remain
+    // C<int>.
+    var expected = '''
+class C<T> {
+  void f(T? t) {}
+}
+void g(C<int> c, int? i) {
+  c.f(i);
+}
+void test(C<int> c) {
+  g(c, null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_inward() async {
+    var content = '''
+int f(int i) => 0;
+int g(int i) => f(i);
+void test() {
+  g(null);
+}
+''';
+
+    var expected = '''
+int f(int? i) => 0;
+int g(int? i) => f(i);
+void test() {
+  g(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_inward_missing_type() async {
+    var content = '''
+int f(int i) => 0;
+int g(i) => f(i); // TODO(danrubel): suggest type
+void test() {
+  g(null);
+}
+''';
+
+    var expected = '''
+int f(int? i) => 0;
+int g(i) => f(i); // TODO(danrubel): suggest type
+void test() {
+  g(null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_outward() async {
+    var content = '''
+int f(int i) => null;
+int g(int i) => f(i);
+''';
+
+    var expected = '''
+int? f(int i) => null;
+int? g(int i) => f(i);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_data_flow_outward_missing_type() async {
+    var content = '''
+f(int i) => null; // TODO(danrubel): suggest type
+int g(int i) => f(i);
+''';
+
+    var expected = '''
+f(int i) => null; // TODO(danrubel): suggest type
+int? g(int i) => f(i);
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_discard_simple_condition() async {
+    var content = '''
+int f(int i) {
+  if (i == null) {
+    return null;
+  } else {
+    return i + 1;
+  }
+}
+''';
+
+    var expected = '''
+int f(int i) {
+  /* if (i == null) {
+    return null;
+  } else {
+    */ return i + 1; /*
+  } */
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_unused_option2_assume_nullable() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+  }
+
+  test_named_parameter_no_default_unused_option2_assume_required() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+  }
+
+  test_named_parameter_no_default_unused_required_option2_assume_nullable() async {
+    // The `@required` annotation overrides the assumption of nullability.
+    // The call at `f()` is presumed to be in error.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+  }
+
+  test_named_parameter_no_default_unused_required_option2_assume_required() async {
+    // Since the `@required` annotation is already present, it is not added
+    // again.
+    // The call at `f()` is presumed to be in error.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+  }
+
+  test_named_parameter_no_default_used_non_null_option2_assume_nullable() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+  }
+
+  test_named_parameter_no_default_used_non_null_option2_assume_required() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    var expected = '''
+void f({@required String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+  }
+
+  test_named_parameter_no_default_used_non_null_required_option2_assume_required() async {
+    // Even if we are using the "assumeRequired" heuristic, we should not add a
+    // duplicate `@required` annotation.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f(s: 'x');
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+  }
+
+  test_named_parameter_no_default_used_null_option2() async {
+    var content = '''
+void f({String s}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+void f({String? s}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_no_default_used_null_required_option2_assume_nullable() async {
+    // Explicitly passing `null` forces the parameter to be nullable even though
+    // it is required.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String? s}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeNullable));
+  }
+
+  test_named_parameter_no_default_used_null_required_option2_assume_required() async {
+    // Explicitly passing `null` forces the parameter to be nullable even though
+    // it is required.
+    addMetaPackage();
+    var content = '''
+import 'package:meta/meta.dart';
+void f({@required String s}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+import 'package:meta/meta.dart';
+void f({@required String? s}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected,
+        assumptions: NullabilityMigrationAssumptions(
+            namedNoDefaultParameterHeuristic:
+                NamedNoDefaultParameterHeuristic.assumeRequired));
+  }
+
+  test_named_parameter_with_non_null_default_unused_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String s: 'foo'}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_non_null_default_used_non_null_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: 'bar');
+}
+''';
+    var expected = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: 'bar');
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_non_null_default_used_null_option2() async {
+    var content = '''
+void f({String s: 'foo'}) {}
+main() {
+  f(s: null);
+}
+''';
+    var expected = '''
+void f({String? s: 'foo'}) {}
+main() {
+  f(s: null);
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_named_parameter_with_null_default_unused_option2() async {
+    var content = '''
+void f({String s: null}) {}
+main() {
+  f();
+}
+''';
+    var expected = '''
+void f({String? s: null}) {}
+main() {
+  f();
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_non_null_assertion() async {
+    var content = '''
+int f(int i, [int j]) {
+  if (i == 0) return i;
+  return i + j;
+}
+''';
+
+    var expected = '''
+int f(int i, [int? j]) {
+  if (i == 0) return i;
+  return i + j!;
+}
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_single_file_multiple_changes() async {
+    var content = '''
+int f() => null;
+int g() => null;
+''';
+    var expected = '''
+int? f() => null;
+int? g() => null;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_single_file_single_change() async {
+    var content = '''
+int f() => null;
+''';
+    var expected = '''
+int? f() => null;
+''';
+    await _checkSingleFileChanges(content, expected);
+  }
+
+  test_two_files() async {
+    var root = '/home/test/lib';
+    var path1 = convertPath('$root/file1.dart');
+    var file1 = '''
+import 'file2.dart';
+int f() => null;
+int h() => g();
+''';
+    var expected1 = '''
+import 'file2.dart';
+int? f() => null;
+int? h() => g();
+''';
+    var path2 = convertPath('$root/file2.dart');
+    var file2 = '''
+import 'file1.dart';
+int g() => f();
+''';
+    var expected2 = '''
+import 'file1.dart';
+int? g() => f();
+''';
+    await _checkMultipleFileChanges(
+        {path1: file1, path2: file2}, {path1: expected1, path2: expected2});
+  }
+}
+
+@reflectiveTest
+class ProvisionalApiTestPermissive extends ProvisionalApiTestBase
+    with ProvisionalApiTestCases {
+  @override
+  bool get usePermissiveMode => true;
+}
+
+/// Tests of the provisional API, where the driver is reset between calls to
+/// `prepareInput` and `processInput`, ensuring that the migration algorithm
+/// sees different AST and element objects during different phases.
+@reflectiveTest
+class ProvisionalApiTestWithReset extends ProvisionalApiTestBase
+    with ProvisionalApiTestCases {
+  @override
+  bool get usePermissiveMode => false;
+
+  @override
+  void _afterPrepare() {
+    driver.resetUriResolution();
+  }
+}
+
+class TestMigrationListener implements NullabilityMigrationListener {
+  final fixes = <SingleNullabilityFix>[];
+
+  @override
+  void addFix(SingleNullabilityFix fix) {
+    fixes.add(fix);
+  }
+}
diff --git a/pkg/analysis_server/test/src/nullability/test_all.dart b/pkg/analysis_server/test/src/nullability/test_all.dart
new file mode 100644
index 0000000..77b5187
--- /dev/null
+++ b/pkg/analysis_server/test/src/nullability/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'migration_visitor_test.dart' as migration_visitor_test;
+import 'provisional_api_test.dart' as provisional_api_test;
+import 'unit_propagation_test.dart' as unit_propagation_test;
+
+main() {
+  defineReflectiveSuite(() {
+    migration_visitor_test.main();
+    provisional_api_test.main();
+    unit_propagation_test.main();
+  });
+}
diff --git a/pkg/analysis_server/test/src/nullability/unit_propagation_test.dart b/pkg/analysis_server/test/src/nullability/unit_propagation_test.dart
new file mode 100644
index 0000000..d2fcf89
--- /dev/null
+++ b/pkg/analysis_server/test/src/nullability/unit_propagation_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:analysis_server/src/nullability/unit_propagation.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnitPropagationTest);
+  });
+}
+
+/// TODO(paulberry): write more tests
+@reflectiveTest
+class UnitPropagationTest {
+  var solver = Solver();
+
+  ConstraintVariable newVar(String name) => _NamedConstraintVariable(name);
+
+  test_record_copies_conditions() {
+    var a = newVar('a');
+    var b = newVar('b');
+    var conditions = [a];
+    solver.record(conditions, b);
+    conditions.removeLast();
+    expect(a.value, false);
+    expect(b.value, false);
+    solver.record([], a);
+    expect(a.value, true);
+    expect(b.value, true);
+  }
+
+  test_record_propagates_true_variables_immediately() {
+    var a = newVar('a');
+    expect(a.value, false);
+    solver.record([], a);
+    expect(a.value, true);
+    var b = newVar('b');
+    expect(b.value, false);
+    solver.record([a], b);
+    expect(b.value, true);
+  }
+}
+
+/// Representation of a constraint variable with a specified name.
+///
+/// This makes test failures easier to comprehend.
+class _NamedConstraintVariable extends ConstraintVariable {
+  final String _name;
+
+  _NamedConstraintVariable(this._name);
+
+  @override
+  String toString() => _name;
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart
index 535bf55..b13e269 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_documentation_into_line_test.dart
@@ -109,4 +109,25 @@
 }
 ''');
   }
+
+  test_preserveIndentation() async {
+    await resolveTestUnit('''
+class A {
+  /**
+   * First line.
+   *     Indented line.
+   * Last line.
+   */
+  m() {}
+}
+''');
+    await assertHasAssistAt('Indented', '''
+class A {
+  /// First line.
+  ///     Indented line.
+  /// Last line.
+  m() {}
+}
+''');
+  }
 }
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
index 170a3c4..5e430f9 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_into_async_body_test.dart
@@ -120,11 +120,7 @@
   int m();
 }
 ''');
-    await assertHasAssistAt('m()', '''
-abstract class C {
-  Future<int> m();
-}
-''');
+    await assertNoAssist();
   }
 
   test_method_noReturnType() async {
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_if_element_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_if_element_test.dart
new file mode 100644
index 0000000..fda239f
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_if_element_test.dart
@@ -0,0 +1,271 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToIfElementTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToIfElementTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_IF_ELEMENT;
+
+  void setUp() {
+    createAnalysisOptionsFile(experiments: [
+      EnableString.control_flow_collections,
+      EnableString.set_literals
+    ]);
+    super.setUp();
+  }
+
+  test_conditional_list() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return ['a', b /*caret*/? 'c' : 'd', 'e'];
+}
+''');
+    await assertHasAssist('''
+f(bool b) {
+  return ['a', if (b) 'c' else 'd', 'e'];
+}
+''');
+  }
+
+  test_conditional_list_withParentheses() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return ['a', (b /*caret*/? 'c' : 'd'), 'e'];
+}
+''');
+    await assertHasAssist('''
+f(bool b) {
+  return ['a', if (b) 'c' else 'd', 'e'];
+}
+''');
+  }
+
+  test_conditional_map() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return {'a' : 1, b /*caret*/? 'c' : 'd' : 2, 'e' : 3};
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_conditional_notConditional() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return {'/*caret*/a', b ? 'c' : 'd', 'e'};
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_conditional_notInLiteral() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return b /*caret*/? 'c' : 'd';
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_conditional_set() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return {'a', b /*caret*/? 'c' : 'd', 'e'};
+}
+''');
+    await assertHasAssist('''
+f(bool b) {
+  return {'a', if (b) 'c' else 'd', 'e'};
+}
+''');
+  }
+
+  test_conditional_set_withParentheses() async {
+    await resolveTestUnit('''
+f(bool b) {
+  return {'a', ((b /*caret*/? 'c' : 'd')), 'e'};
+}
+''');
+    await assertHasAssist('''
+f(bool b) {
+  return {'a', if (b) 'c' else 'd', 'e'};
+}
+''');
+  }
+
+  test_mapFromIterable_complexKey() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (e) {
+    var result = e * 2;
+    return result;
+  }, value: (e) => e + 3);
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_complexValue() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (e) => e * 2, value: (e) {
+    var result = e  + 3;
+    return result;
+  });
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInKey_conflictInValue() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  var k = 3;
+  return Map.fromIt/*caret*/erable(i, key: (k) => k * 2, value: (v) => k);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  var k = 3;
+  return { for (var e in i) e * 2 : k };
+}
+''');
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInKey_noConflictInValue() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (k) => k * 2, value: (v) => 0);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  return { for (var k in i) k * 2 : 0 };
+}
+''');
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInKeyAndValue_conflictWithDefault() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  var e = 2;
+  return Map.fromIt/*caret*/erable(i, key: (k) => k * e, value: (v) => v + e);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  var e = 2;
+  return { for (var e1 in i) e1 * e : e1 + e };
+}
+''');
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInKeyAndValue_noConflictWithDefault() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (k) => k * 2, value: (v) => v + 3);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  return { for (var e in i) e * 2 : e + 3 };
+}
+''');
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInValue_conflictInKey() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  int v = 0;
+  return Map.fromIt/*caret*/erable(i, key: (k) => v++, value: (v) => v * 10);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  int v = 0;
+  return { for (var e in i) v++ : e * 10 };
+}
+''');
+  }
+
+  test_mapFromIterable_differentParameterNames_usedInValue_noConflictInKey() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  int index = 0;
+  return Map.fromIt/*caret*/erable(i, key: (k) => index++, value: (v) => v * 10);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  int index = 0;
+  return { for (var v in i) index++ : v * 10 };
+}
+''');
+  }
+
+  test_mapFromIterable_missingKey() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, value: (e) => e + 3);
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_missingKeyAndValue() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i);
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_missingValue() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (e) => e * 2);
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_notMapFromIterable() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return A.fromIt/*caret*/erable(i, key: (e) => e * 2, value: (e) => e + 3);
+}
+class A {
+  A.fromIterable(i, {key, value});
+}
+''');
+    await assertNoAssist();
+  }
+
+  test_mapFromIterable_sameParameterNames() async {
+    await resolveTestUnit('''
+f(Iterable<int> i) {
+  return Map.fromIt/*caret*/erable(i, key: (e) => e * 2, value: (e) => e + 3);
+}
+''');
+    await assertHasAssist('''
+f(Iterable<int> i) {
+  return { for (var e in i) e * 2 : e + 3 };
+}
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_list_literal_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_list_literal_test.dart
new file mode 100644
index 0000000..a9b106e
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_list_literal_test.dart
@@ -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 file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToListLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToListLiteralTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_LIST_LITERAL;
+
+  test_default_declaredType() async {
+    await resolveTestUnit('''
+List l = Li/*caret*/st();
+''');
+    await assertHasAssist('''
+List l = [];
+''');
+  }
+
+  test_default_minimal() async {
+    await resolveTestUnit('''
+var l = Li/*caret*/st();
+''');
+    await assertHasAssist('''
+var l = [];
+''');
+  }
+
+  test_default_newKeyword() async {
+    await resolveTestUnit('''
+var l = new Li/*caret*/st();
+''');
+    await assertHasAssist('''
+var l = [];
+''');
+  }
+
+  test_default_tooManyArguments() async {
+    await resolveTestUnit('''
+var l = Li/*caret*/st(5);
+''');
+    await assertNoAssist();
+  }
+
+  test_default_typeArg() async {
+    await resolveTestUnit('''
+var l = Li/*caret*/st<int>();
+''');
+    await assertHasAssist('''
+var l = <int>[];
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_map_literal_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_map_literal_test.dart
new file mode 100644
index 0000000..150b545
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_map_literal_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToMapLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToMapLiteralTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_MAP_LITERAL;
+
+  test_default_declaredType() async {
+    await resolveTestUnit('''
+Map m = Ma/*caret*/p();
+''');
+    await assertHasAssist('''
+Map m = {};
+''');
+  }
+
+  test_default_linkedHashMap() async {
+    await resolveTestUnit('''
+import 'dart:collection';
+var m = LinkedHashMa/*caret*/p();
+''');
+    await assertHasAssist('''
+import 'dart:collection';
+var m = {};
+''');
+  }
+
+  test_default_minimal() async {
+    await resolveTestUnit('''
+var m = Ma/*caret*/p();
+''');
+    await assertHasAssist('''
+var m = {};
+''');
+  }
+
+  test_default_newKeyword() async {
+    await resolveTestUnit('''
+var m = new Ma/*caret*/p();
+''');
+    await assertHasAssist('''
+var m = {};
+''');
+  }
+
+  test_default_typeArg() async {
+    await resolveTestUnit('''
+var m = Ma/*caret*/p<String, int>();
+''');
+    await assertHasAssist('''
+var m = <String, int>{};
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_set_literal_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_set_literal_test.dart
new file mode 100644
index 0000000..053bba7
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_set_literal_test.dart
@@ -0,0 +1,181 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToSetLiteralTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToSetLiteralTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_SET_LITERAL;
+
+  test_default_declaredType() async {
+    await resolveTestUnit('''
+Set s = S/*caret*/et();
+''');
+    await assertHasAssist('''
+Set s = {};
+''');
+  }
+
+  test_default_minimal() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et();
+''');
+    await assertHasAssist('''
+var s = <dynamic>{};
+''');
+  }
+
+  test_default_newKeyword() async {
+    await resolveTestUnit('''
+var s = new S/*caret*/et();
+''');
+    await assertHasAssist('''
+var s = <dynamic>{};
+''');
+  }
+
+  test_default_typeArg() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et<int>();
+''');
+    await assertHasAssist('''
+var s = <int>{};
+''');
+  }
+
+  test_from_empty() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et.from([]);
+''');
+    await assertHasAssist('''
+var s = <dynamic>{};
+''');
+  }
+
+  test_from_newKeyword() async {
+    await resolveTestUnit('''
+var s = new S/*caret*/et.from([2, 3]);
+''');
+    await assertHasAssist('''
+var s = {2, 3};
+''');
+  }
+
+  test_from_noKeyword_declaredType() async {
+    await resolveTestUnit('''
+Set s = S/*caret*/et.from([2, 3]);
+''');
+    await assertHasAssist('''
+Set s = {2, 3};
+''');
+  }
+
+  test_from_noKeyword_typeArg_onConstructor() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et<int>.from([2, 3]);
+''');
+    await assertHasAssist('''
+var s = <int>{2, 3};
+''');
+  }
+
+  test_from_noKeyword_typeArg_onConstructorAndLiteral() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et<int>.from(<num>[2, 3]);
+''');
+    await assertHasAssist('''
+var s = <int>{2, 3};
+''');
+  }
+
+  test_from_noKeyword_typeArg_onLiteral() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et.from(<int>[2, 3]);
+''');
+    await assertHasAssist('''
+var s = <int>{2, 3};
+''');
+  }
+
+  test_from_nonEmpty() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et.from([2, 3]);
+''');
+    await assertHasAssist('''
+var s = {2, 3};
+''');
+  }
+
+  test_from_notALiteral() async {
+    await resolveTestUnit('''
+var l = [1];
+Set s = new S/*caret*/et.from(l);
+''');
+    await assertNoAssist();
+  }
+
+  test_from_trailingComma() async {
+    await resolveTestUnit('''
+var s = S/*caret*/et.from([2, 3,]);
+''');
+    await assertHasAssist('''
+var s = {2, 3,};
+''');
+  }
+
+  test_toSet_empty() async {
+    await resolveTestUnit('''
+var s = [].to/*caret*/Set();
+''');
+    await assertHasAssist('''
+var s = <dynamic>{};
+''');
+  }
+
+  test_toSet_empty_typeArg() async {
+    await resolveTestUnit('''
+var s = <int>[].to/*caret*/Set();
+''');
+    await assertHasAssist('''
+var s = <int>{};
+''');
+  }
+
+  test_toSet_nonEmpty() async {
+    await resolveTestUnit('''
+var s = [2, 3].to/*caret*/Set();
+''');
+    await assertHasAssist('''
+var s = {2, 3};
+''');
+  }
+
+  test_toSet_nonEmpty_typeArg() async {
+    await resolveTestUnit('''
+var s = <int>[2, 3].to/*caret*/Set();
+''');
+    await assertHasAssist('''
+var s = <int>{2, 3};
+''');
+  }
+
+  test_toSet_notALiteral() async {
+    await resolveTestUnit('''
+var l = [];
+var s = l.to/*caret*/Set();
+''');
+    await assertNoAssist();
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/convert_to_spread_test.dart b/pkg/analysis_server/test/src/services/correction/assist/convert_to_spread_test.dart
new file mode 100644
index 0000000..648502f
--- /dev/null
+++ b/pkg/analysis_server/test/src/services/correction/assist/convert_to_spread_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analysis_server/src/services/correction/assist.dart';
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer_plugin/utilities/assist/assist.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'assist_processor.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConvertToSpreadTest);
+    defineReflectiveTests(ConvertToSpreadWithControlFlowTest);
+  });
+}
+
+@reflectiveTest
+class ConvertToSpreadTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_SPREAD;
+
+  void setUp() {
+    createAnalysisOptionsFile(experiments: [EnableString.spread_collections]);
+    super.setUp();
+  }
+
+  test_addAll_expression() async {
+    await resolveTestUnit('''
+f() {
+  var ints = [1, 2, 3];
+  print(['a']..addAl/*caret*/l(ints.map((i) => i.toString()))..addAll(['c']));
+}
+''');
+    await assertHasAssist('''
+f() {
+  var ints = [1, 2, 3];
+  print(['a', ...ints.map((i) => i.toString())]..addAll(['c']));
+}
+''');
+  }
+
+  test_addAll_literal() async {
+    await resolveTestUnit('''
+var l = ['a']..add/*caret*/All(['b'])..addAll(['c']);
+''');
+    await assertHasAssist('''
+var l = ['a', ...['b']]..addAll(['c']);
+''');
+  }
+
+  test_addAll_nonLiteralTarget() async {
+    await resolveTestUnit('''
+var l1 = [];
+var l2 = l1..addAl/*caret*/l(['b'])..addAll(['c']);
+''');
+    await assertNoAssist();
+  }
+
+  test_addAll_notFirst() async {
+    await resolveTestUnit('''
+var l = ['a']..addAll(['b'])../*caret*/addAll(['c']);
+''');
+    await assertNoAssist();
+  }
+
+  test_addAll_nullAware_const() async {
+    await resolveTestUnit('''
+var things;
+var l = ['a']..add/*caret*/All(things ?? const []);
+''');
+    await assertHasAssist('''
+var things;
+var l = ['a', ...?things];
+''');
+  }
+
+  test_addAll_nullAware_nonConst() async {
+    await resolveTestUnit('''
+var things;
+var l = ['a']..add/*caret*/All(things ?? []);
+''');
+    await assertHasAssist('''
+var things;
+var l = ['a', ...?things];
+''');
+  }
+}
+
+@reflectiveTest
+class ConvertToSpreadWithControlFlowTest extends AssistProcessorTest {
+  @override
+  AssistKind get kind => DartAssistKind.CONVERT_TO_SPREAD;
+
+  void setUp() {
+    createAnalysisOptionsFile(experiments: [
+      EnableString.control_flow_collections,
+      EnableString.spread_collections
+    ]);
+    super.setUp();
+  }
+
+  test_addAll_condition_const() async {
+    await resolveTestUnit('''
+bool condition;
+var things;
+var l = ['a']..add/*caret*/All(condition ? things : const []);
+''');
+    await assertHasAssist('''
+bool condition;
+var things;
+var l = ['a', if (condition) ...things];
+''');
+  }
+
+  test_addAll_condition_nonConst() async {
+    await resolveTestUnit('''
+bool condition;
+var things;
+var l = ['a']..add/*caret*/All(condition ? things : []);
+''');
+    await assertHasAssist('''
+bool condition;
+var things;
+var l = ['a', if (condition) ...things];
+''');
+  }
+}
diff --git a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
index f4d13a4..d3aaded 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/flutter_convert_to_stateful_widget_test.dart
@@ -36,12 +36,10 @@
 
 class MyWidget extends StatefulWidget {
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   @override
   Widget build(BuildContext context) {
     return Container();
@@ -103,12 +101,10 @@
   }
 
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   String instanceField4;
 
   String instanceField5;
@@ -165,16 +161,14 @@
 
 class MyWidget extends StatefulWidget {
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 
   static String get staticGetter1 => '';
 
   static String get staticGetter2 => '';
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   @override
   Widget build(BuildContext context) {
     return Row(
@@ -246,9 +240,7 @@
   MyWidget(this.instanceField1);
 
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 
   static void staticMethod1() {
     print('static 1');
@@ -259,7 +251,7 @@
   }
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   String instanceField2;
 
   @override
@@ -349,12 +341,10 @@
   const MyWidget(this.aaa, this.bbb);
 
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   @override
   Widget build(BuildContext context) {
     return Row(
@@ -387,12 +377,10 @@
 
 class MyWidget extends StatefulWidget {
   @override
-  MyWidgetState createState() {
-    return MyWidgetState();
-  }
+  _MyWidgetState createState() => _MyWidgetState();
 }
 
-class MyWidgetState extends State<MyWidget> {
+class _MyWidgetState extends State<MyWidget> {
   @override
   Widget build(BuildContext context) {
     return Container();
diff --git a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
index a090848..86c5872 100644
--- a/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/assist/test_all.dart
@@ -25,11 +25,16 @@
 import 'convert_to_double_quoted_string_test.dart'
     as convert_to_double_quoted_string;
 import 'convert_to_field_parameter_test.dart' as convert_to_field_parameter;
+import 'convert_to_if_element_test.dart' as convert_to_if_element;
 import 'convert_to_int_literal_test.dart' as convert_to_int_literal;
+import 'convert_to_list_literal_test.dart' as convert_to_list_literal;
+import 'convert_to_map_literal_test.dart' as convert_to_map_literal;
 import 'convert_to_multiline_string_test.dart' as convert_to_multiline_string;
 import 'convert_to_normal_parameter_test.dart' as convert_to_normal_parameter;
+import 'convert_to_set_literal_test.dart' as convert_to_set_literal;
 import 'convert_to_single_quoted_string_test.dart'
     as convert_to_single_quoted_string;
+import 'convert_to_spread_test.dart' as convert_to_spread;
 import 'encapsulate_field_test.dart' as encapsulate_field;
 import 'exchange_operands_test.dart' as exchange_operands;
 import 'flutter_convert_to_children_test.dart' as flutter_convert_to_children;
@@ -88,10 +93,15 @@
     convert_part_of_to_uri.main();
     convert_to_double_quoted_string.main();
     convert_to_field_parameter.main();
+    convert_to_if_element.main();
     convert_to_int_literal.main();
+    convert_to_list_literal.main();
+    convert_to_map_literal.main();
     convert_to_multiline_string.main();
     convert_to_normal_parameter.main();
+    convert_to_set_literal.main();
     convert_to_single_quoted_string.main();
+    convert_to_spread.main();
     encapsulate_field.main();
     exchange_operands.main();
     flutter_convert_to_children.main();
diff --git a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
index 20df52c..57ff490 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/add_missing_required_argument_test.dart
@@ -325,6 +325,7 @@
   test(abc: null);
 }
 ''');
+    assertLinkedGroup(change.linkedEditGroups[0], ['null);']);
   }
 
   test_single_normal() async {
diff --git a/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart b/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart
deleted file mode 100644
index 7ec1088..0000000
--- a/pkg/analysis_server/test/src/services/correction/fix/replace_with_literal_test.dart
+++ /dev/null
@@ -1,113 +0,0 @@
-// 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:analysis_server/src/services/correction/fix.dart';
-import 'package:analysis_server/src/services/correction/fix_internal.dart';
-import 'package:analyzer_plugin/utilities/fixes/fixes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import 'fix_processor.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ReplaceWithLiteralTest);
-  });
-}
-
-@reflectiveTest
-class ReplaceWithLiteralTest extends FixProcessorLintTest {
-  @override
-  FixKind get kind => DartFixKind.REPLACE_WITH_LITERAL;
-
-  @override
-  String get lintCode => LintNames.prefer_collection_literals;
-
-  test_linkedHashMap_withCommentsInGeneric() async {
-    await resolveTestUnit('''
-import 'dart:collection';
-
-final a = /*LINT*/new LinkedHashMap<int,/*comment*/int>();
-''');
-    await assertHasFix('''
-import 'dart:collection';
-
-final a = /*LINT*/<int,/*comment*/int>{};
-''');
-  }
-
-  test_linkedHashMap_withDynamicGenerics() async {
-    await resolveTestUnit('''
-import 'dart:collection';
-
-final a = /*LINT*/new LinkedHashMap<dynamic,dynamic>();
-''');
-    await assertHasFix('''
-import 'dart:collection';
-
-final a = /*LINT*/<dynamic,dynamic>{};
-''');
-  }
-
-  test_linkedHashMap_withGeneric() async {
-    await resolveTestUnit('''
-import 'dart:collection';
-
-final a = /*LINT*/new LinkedHashMap<int,int>();
-''');
-    await assertHasFix('''
-import 'dart:collection';
-
-final a = /*LINT*/<int,int>{};
-''');
-  }
-
-  test_linkedHashMap_withoutGeneric() async {
-    await resolveTestUnit('''
-import 'dart:collection';
-
-final a = /*LINT*/new LinkedHashMap();
-''');
-    await assertHasFix('''
-import 'dart:collection';
-
-final a = /*LINT*/{};
-''');
-  }
-
-  test_list_withGeneric() async {
-    await resolveTestUnit('''
-final a = /*LINT*/new List<int>();
-''');
-    await assertHasFix('''
-final a = /*LINT*/<int>[];
-''');
-  }
-
-  test_list_withoutGeneric() async {
-    await resolveTestUnit('''
-final a = /*LINT*/new List();
-''');
-    await assertHasFix('''
-final a = /*LINT*/[];
-''');
-  }
-
-  test_map_withGeneric() async {
-    await resolveTestUnit('''
-final a = /*LINT*/new Map<int,int>();
-''');
-    await assertHasFix('''
-final a = /*LINT*/<int,int>{};
-''');
-  }
-
-  test_map_withoutGeneric() async {
-    await resolveTestUnit('''
-final a = /*LINT*/new Map();
-''');
-    await assertHasFix('''
-final a = /*LINT*/{};
-''');
-  }
-}
diff --git a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
index 30cad40..6a259e9 100644
--- a/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
+++ b/pkg/analysis_server/test/src/services/correction/fix/test_all.dart
@@ -86,7 +86,6 @@
 import 'replace_with_conditional_assignment_test.dart'
     as replace_with_conditional_assignment;
 import 'replace_with_identifier_test.dart' as replace_with_identifier;
-import 'replace_with_literal_test.dart' as replace_with_literal;
 import 'replace_with_null_aware_test.dart' as replace_with_null_aware;
 import 'replace_with_tear_off_test.dart' as replace_with_tear_off;
 import 'update_sdk_constraints_test.dart' as update_sdk_constraints;
@@ -170,7 +169,6 @@
     replace_var_with_dynamic.main();
     replace_with_brackets.main();
     replace_with_conditional_assignment.main();
-    replace_with_literal.main();
     replace_with_identifier.main();
     replace_with_null_aware.main();
     replace_with_tear_off.main();
diff --git a/pkg/analysis_server/test/src/test_all.dart b/pkg/analysis_server/test/src/test_all.dart
index 6a07ced..51ad9b3 100644
--- a/pkg/analysis_server/test/src/test_all.dart
+++ b/pkg/analysis_server/test/src/test_all.dart
@@ -8,6 +8,7 @@
 import 'domain_abstract_test.dart' as domain_abstract_test;
 import 'domains/test_all.dart' as domains_all;
 import 'flutter/test_all.dart' as flutter_all;
+import 'nullability/test_all.dart' as nullability_all;
 import 'plugin/test_all.dart' as plugin_all;
 import 'services/test_all.dart' as services_all;
 import 'utilities/test_all.dart' as utilities_all;
@@ -22,6 +23,7 @@
     domain_abstract_test.main();
     domains_all.main();
     flutter_all.main();
+    nullability_all.main();
     plugin_all.main();
     services_all.main();
     utilities_all.main();
diff --git a/pkg/analysis_server/tool/lsp_spec/README.md b/pkg/analysis_server/tool/lsp_spec/README.md
index b696b00..5c0ab08 100644
--- a/pkg/analysis_server/tool/lsp_spec/README.md
+++ b/pkg/analysis_server/tool/lsp_spec/README.md
@@ -41,7 +41,7 @@
 | workspace/didChangeWorkspaceFolders | ✅ | ✅ | ✅ | ✅ |
 | workspace/configuration | | | | |
 | workspace/didChangeWatchedFiles | | | | | unused, server does own watching |
-| workspace/symbol | | | | |
+| workspace/symbol | ✅ | ✅ | ✅ | ✅ |
 | workspace/executeCommand | ✅ | ✅ | ✅ | ✅ |
 | workspace/applyEdit | ✅ | ✅ | ✅ | ✅ |
 | textDocument/didOpen | ✅ | ✅ | ✅ | ✅ |
diff --git a/pkg/analysis_server/tool/spec/check_all_test.dart b/pkg/analysis_server/tool/spec/check_all_test.dart
index 3aefa25..1388652 100644
--- a/pkg/analysis_server/tool/spec/check_all_test.dart
+++ b/pkg/analysis_server/tool/spec/check_all_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart';
 
 import 'generate_all.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
index 75fc69c..d81e94c 100644
--- a/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
+++ b/pkg/analysis_server/tool/spec/codegen_analysis_server.dart
@@ -5,7 +5,7 @@
 /**
  * Code generation for the file "AnalysisServer.java".
  */
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 import 'codegen_java.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart b/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
index 45c8f2e..6acbda1 100644
--- a/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
+++ b/pkg/analysis_server/tool/spec/codegen_dart_notification_handler.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart';
 
 import 'api.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
index adb57f7..a8692f1 100644
--- a/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
+++ b/pkg/analysis_server/tool/spec/codegen_dart_protocol.dart
@@ -4,7 +4,7 @@
 
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 import 'package:path/path.dart' as path;
 
diff --git a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
index 8fec4fa..924e5c3 100644
--- a/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
+++ b/pkg/analysis_server/tool/spec/codegen_inttest_methods.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart' as path;
 
 import 'api.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_java.dart b/pkg/analysis_server/tool/spec/codegen_java.dart
index 9956fe1..56bdc8b 100644
--- a/pkg/analysis_server/tool/spec/codegen_java.dart
+++ b/pkg/analysis_server/tool/spec/codegen_java.dart
@@ -5,7 +5,7 @@
 /**
  * Tools for Java code generation.
  */
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 
 import 'api.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_java_types.dart b/pkg/analysis_server/tool/spec/codegen_java_types.dart
index 2006405..5a0e443 100644
--- a/pkg/analysis_server/tool/spec/codegen_java_types.dart
+++ b/pkg/analysis_server/tool/spec/codegen_java_types.dart
@@ -5,7 +5,7 @@
 /**
  * Code generation for the file "AnalysisServer.java".
  */
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 
 import 'api.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_matchers.dart b/pkg/analysis_server/tool/spec/codegen_matchers.dart
index 226c707..bd6c7e1 100644
--- a/pkg/analysis_server/tool/spec/codegen_matchers.dart
+++ b/pkg/analysis_server/tool/spec/codegen_matchers.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 import 'from_html.dart';
diff --git a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
index 7530d39..4c45331 100644
--- a/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
+++ b/pkg/analysis_server/tool/spec/codegen_protocol_constants.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 import 'codegen_dart.dart';
diff --git a/pkg/analysis_server/tool/spec/from_html.dart b/pkg/analysis_server/tool/spec/from_html.dart
index be77a02..f78ad63 100644
--- a/pkg/analysis_server/tool/spec/from_html.dart
+++ b/pkg/analysis_server/tool/spec/from_html.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/html.dart';
+import 'package:analysis_tool/html.dart';
 import 'package:html/dom.dart' as dom;
 import 'package:html/parser.dart' as parser;
 import 'package:path/path.dart';
@@ -131,8 +131,8 @@
     });
     for (String expectedAttribute in requiredAttributes) {
       if (!attributesFound.contains(expectedAttribute)) {
-        throw new Exception('$context: ${element
-            .localName} must contain attribute $expectedAttribute');
+        throw new Exception(
+            '$context: ${element.localName} must contain attribute $expectedAttribute');
       }
     }
   }
diff --git a/pkg/analysis_server/tool/spec/generate_all.dart b/pkg/analysis_server/tool/spec/generate_all.dart
index c5afd22..000b487 100644
--- a/pkg/analysis_server/tool/spec/generate_all.dart
+++ b/pkg/analysis_server/tool/spec/generate_all.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart';
 
 import 'codegen_analysis_server.dart' as codegen_analysis_server;
diff --git a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
index 45f18a6..895f4f4 100644
--- a/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
+++ b/pkg/analysis_server/tool/spec/generated/java/AnalysisServer.java
@@ -390,6 +390,23 @@
   public void analytics_sendTiming(String event, int millis);
 
   /**
+   * {@code completion.getSuggestionDetails}
+   *
+   * Clients must make this request when the user has selected a completion suggestion from an
+   * AvailableSuggestionSet. Analysis server will respond with the text to insert as well as any
+   * SourceChange that needs to be applied in case the completion requires an additional import to be
+   * added. It is an error if the id is no longer valid, for instance if the library has been removed
+   * after the completion suggestion is accepted.
+   *
+   * @param file The path of the file into which this completion is being inserted.
+   * @param id The identifier of the AvailableSuggestionSet containing the selected label.
+   * @param label The label from the AvailableSuggestionSet with the `id` for which insertion
+   *         information is requested.
+   * @param offset The offset in the file where the completion will be inserted.
+   */
+  public void completion_getSuggestionDetails(String file, int id, String label, int offset, GetSuggestionDetailsConsumer consumer);
+
+  /**
    * {@code completion.getSuggestions}
    *
    * Request that completion suggestions for the given offset in the given file be returned.
@@ -400,6 +417,35 @@
   public void completion_getSuggestions(String file, int offset, GetSuggestionsConsumer consumer);
 
   /**
+   * {@code completion.registerLibraryPaths}
+   *
+   * The client can make this request to express interest in certain libraries to receive completion
+   * suggestions from based on the client path. If this request is received before the client has
+   * used 'completion.setSubscriptions' to subscribe to the AVAILABLE_SUGGESTION_SETS service, then
+   * an error of type NOT_SUBSCRIBED_TO_AVAILABLE_SUGGESTION_SETS will be generated. All previous
+   * paths are replaced by the given set of paths.
+   *
+   * @param paths A list of objects each containing a path and the additional libraries from which
+   *         the client is interested in receiving completion suggestions. If one configured path is
+   *         beneath another, the descendent will override the ancestors' configured libraries of
+   *         interest.
+   */
+  public void completion_registerLibraryPaths(List<LibraryPathSet> paths);
+
+  /**
+   * {@code completion.setSubscriptions}
+   *
+   * Subscribe for completion services. All previous subscriptions are replaced by the given set of
+   * services.
+   *
+   * It is an error if any of the elements in the list are not valid services. If there is an error,
+   * then the current subscriptions will remain unchanged.
+   *
+   * @param subscriptions A list of the services being subscribed to.
+   */
+  public void completion_setSubscriptions(List<String> subscriptions);
+
+  /**
    * {@code diagnostic.getDiagnostics}
    *
    * Return server diagnostics.
@@ -422,14 +468,27 @@
    * those sources. These edits may include changes to sources outside the set of specified sources
    * if a change in a specified source requires it.
    *
+   * If includedFixes is specified, then those fixes will be applied. If includeRequiredFixes is
+   * specified, then "required" fixes will be applied in addition to whatever fixes are specified in
+   * includedFixes if any. If neither includedFixes nor includeRequiredFixes is specified, then all
+   * fixes will be applied. If excludedFixes is specified, then those fixes will not be applied
+   * regardless of whether they are "required" or specified in includedFixes.
+   *
    * @param included A list of the files and directories for which edits should be suggested. If a
    *         request is made with a path that is invalid, e.g. is not absolute and normalized, an
    *         error of type INVALID_FILE_PATH_FORMAT will be generated. If a request is made for a
    *         file which does not exist, or which is not currently subject to analysis (e.g. because
    *         it is not associated with any analysis root specified to analysis.setAnalysisRoots), an
    *         error of type FILE_NOT_ANALYZED will be generated.
+   * @param includedFixes A list of names indicating which fixes should be applied. If a name is
+   *         specified that does not match the name of a known fix, an error of type UNKNOWN_FIX will
+   *         be generated.
+   * @param includeRequiredFixes A flag indicating that "required" fixes should be applied.
+   * @param excludedFixes A list of names indicating which fixes should not be applied. If a name is
+   *         specified that does not match the name of a known fix, an error of type UNKNOWN_FIX will
+   *         be generated.
    */
-  public void edit_dartfix(List<String> included, DartfixConsumer consumer);
+  public void edit_dartfix(List<String> included, List<String> includedFixes, boolean includeRequiredFixes, List<String> excludedFixes, DartfixConsumer consumer);
 
   /**
    * {@code edit.format}
@@ -478,6 +537,14 @@
   public void edit_getAvailableRefactorings(String file, int offset, int length, GetAvailableRefactoringsConsumer consumer);
 
   /**
+   * {@code edit.getDartfixInfo}
+   *
+   * Request information about edit.dartfix such as the list of known fixes that can be specified in
+   * an edit.dartfix request.
+   */
+  public void edit_getDartfixInfo(GetDartfixInfoConsumer consumer);
+
+  /**
    * {@code edit.getFixes}
    *
    * Return the set of fixes that are available for the errors at a given offset in a given file.
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java
new file mode 100644
index 0000000..a25dd89
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestion.java
@@ -0,0 +1,271 @@
+/*
+ * 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.
+ *
+ * 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 partial completion suggestion that can be used in combination with info from
+ * completion.results to build completion suggestions for not yet imported library tokens.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class AvailableSuggestion {
+
+  public static final AvailableSuggestion[] EMPTY_ARRAY = new AvailableSuggestion[0];
+
+  public static final List<AvailableSuggestion> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  private final String label;
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  private final Element element;
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is omitted if there is no
+   * Dartdoc associated with the element.
+   */
+  private final String docComplete;
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  private final String docSummary;
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all kinds - required,
+   * optional positional, and optional named. The names of positional parameters are empty strings.
+   * Omitted if the element is not an executable.
+   */
+  private final List<String> parameterNames;
+
+  /**
+   * If the element is an executable, the declared types of the formal parameters of all kinds -
+   * required, optional positional, and optional named. Omitted if the element is not an executable.
+   */
+  private final List<String> parameterTypes;
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed depending on where
+   * completion is requested.
+   */
+  private final List<AvailableSuggestionRelevanceTag> relevanceTags;
+
+  private final Integer requiredParameterCount;
+
+  /**
+   * Constructor for {@link AvailableSuggestion}.
+   */
+  public AvailableSuggestion(String label, Element element, String docComplete, String docSummary, List<String> parameterNames, List<String> parameterTypes, List<AvailableSuggestionRelevanceTag> relevanceTags, Integer requiredParameterCount) {
+    this.label = label;
+    this.element = element;
+    this.docComplete = docComplete;
+    this.docSummary = docSummary;
+    this.parameterNames = parameterNames;
+    this.parameterTypes = parameterTypes;
+    this.relevanceTags = relevanceTags;
+    this.requiredParameterCount = requiredParameterCount;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof AvailableSuggestion) {
+      AvailableSuggestion other = (AvailableSuggestion) obj;
+      return
+        ObjectUtilities.equals(other.label, label) &&
+        ObjectUtilities.equals(other.element, element) &&
+        ObjectUtilities.equals(other.docComplete, docComplete) &&
+        ObjectUtilities.equals(other.docSummary, docSummary) &&
+        ObjectUtilities.equals(other.parameterNames, parameterNames) &&
+        ObjectUtilities.equals(other.parameterTypes, parameterTypes) &&
+        ObjectUtilities.equals(other.relevanceTags, relevanceTags) &&
+        ObjectUtilities.equals(other.requiredParameterCount, requiredParameterCount);
+    }
+    return false;
+  }
+
+  public static AvailableSuggestion fromJson(JsonObject jsonObject) {
+    String label = jsonObject.get("label").getAsString();
+    Element element = Element.fromJson(jsonObject.get("element").getAsJsonObject());
+    String docComplete = jsonObject.get("docComplete") == null ? null : jsonObject.get("docComplete").getAsString();
+    String docSummary = jsonObject.get("docSummary") == null ? null : jsonObject.get("docSummary").getAsString();
+    List<String> parameterNames = jsonObject.get("parameterNames") == null ? null : JsonUtilities.decodeStringList(jsonObject.get("parameterNames").getAsJsonArray());
+    List<String> parameterTypes = jsonObject.get("parameterTypes") == null ? null : JsonUtilities.decodeStringList(jsonObject.get("parameterTypes").getAsJsonArray());
+    List<AvailableSuggestionRelevanceTag> relevanceTags = jsonObject.get("relevanceTags") == null ? null : AvailableSuggestionRelevanceTag.fromJsonArray(jsonObject.get("relevanceTags").getAsJsonArray());
+    Integer requiredParameterCount = jsonObject.get("requiredParameterCount") == null ? null : jsonObject.get("requiredParameterCount").getAsInt();
+    return new AvailableSuggestion(label, element, docComplete, docSummary, parameterNames, parameterTypes, relevanceTags, requiredParameterCount);
+  }
+
+  public static List<AvailableSuggestion> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<AvailableSuggestion> list = new ArrayList<AvailableSuggestion>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is omitted if there is no
+   * Dartdoc associated with the element.
+   */
+  public String getDocComplete() {
+    return docComplete;
+  }
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  public String getDocSummary() {
+    return docSummary;
+  }
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  public Element getElement() {
+    return element;
+  }
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  public String getLabel() {
+    return label;
+  }
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all kinds - required,
+   * optional positional, and optional named. The names of positional parameters are empty strings.
+   * Omitted if the element is not an executable.
+   */
+  public List<String> getParameterNames() {
+    return parameterNames;
+  }
+
+  /**
+   * If the element is an executable, the declared types of the formal parameters of all kinds -
+   * required, optional positional, and optional named. Omitted if the element is not an executable.
+   */
+  public List<String> getParameterTypes() {
+    return parameterTypes;
+  }
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed depending on where
+   * completion is requested.
+   */
+  public List<AvailableSuggestionRelevanceTag> getRelevanceTags() {
+    return relevanceTags;
+  }
+
+  public Integer getRequiredParameterCount() {
+    return requiredParameterCount;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(label);
+    builder.append(element);
+    builder.append(docComplete);
+    builder.append(docSummary);
+    builder.append(parameterNames);
+    builder.append(parameterTypes);
+    builder.append(relevanceTags);
+    builder.append(requiredParameterCount);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("label", label);
+    jsonObject.add("element", element.toJson());
+    if (docComplete != null) {
+      jsonObject.addProperty("docComplete", docComplete);
+    }
+    if (docSummary != null) {
+      jsonObject.addProperty("docSummary", docSummary);
+    }
+    if (parameterNames != null) {
+      JsonArray jsonArrayParameterNames = new JsonArray();
+      for (String elt : parameterNames) {
+        jsonArrayParameterNames.add(new JsonPrimitive(elt));
+      }
+      jsonObject.add("parameterNames", jsonArrayParameterNames);
+    }
+    if (parameterTypes != null) {
+      JsonArray jsonArrayParameterTypes = new JsonArray();
+      for (String elt : parameterTypes) {
+        jsonArrayParameterTypes.add(new JsonPrimitive(elt));
+      }
+      jsonObject.add("parameterTypes", jsonArrayParameterTypes);
+    }
+    if (relevanceTags != null) {
+      JsonArray jsonArrayRelevanceTags = new JsonArray();
+      for (AvailableSuggestionRelevanceTag elt : relevanceTags) {
+        jsonArrayRelevanceTags.add(elt.toJson());
+      }
+      jsonObject.add("relevanceTags", jsonArrayRelevanceTags);
+    }
+    if (requiredParameterCount != null) {
+      jsonObject.addProperty("requiredParameterCount", requiredParameterCount);
+    }
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("label=");
+    builder.append(label + ", ");
+    builder.append("element=");
+    builder.append(element + ", ");
+    builder.append("docComplete=");
+    builder.append(docComplete + ", ");
+    builder.append("docSummary=");
+    builder.append(docSummary + ", ");
+    builder.append("parameterNames=");
+    builder.append(StringUtils.join(parameterNames, ", ") + ", ");
+    builder.append("parameterTypes=");
+    builder.append(StringUtils.join(parameterTypes, ", ") + ", ");
+    builder.append("relevanceTags=");
+    builder.append(StringUtils.join(relevanceTags, ", ") + ", ");
+    builder.append("requiredParameterCount=");
+    builder.append(requiredParameterCount);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestionSet.java b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestionSet.java
new file mode 100644
index 0000000..570ef61
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/AvailableSuggestionSet.java
@@ -0,0 +1,141 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class AvailableSuggestionSet {
+
+  public static final AvailableSuggestionSet[] EMPTY_ARRAY = new AvailableSuggestionSet[0];
+
+  public static final List<AvailableSuggestionSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The id associated with the library.
+   */
+  private final int id;
+
+  /**
+   * The URI of the library.
+   */
+  private final String uri;
+
+  private final List<AvailableSuggestion> items;
+
+  /**
+   * Constructor for {@link AvailableSuggestionSet}.
+   */
+  public AvailableSuggestionSet(int id, String uri, List<AvailableSuggestion> items) {
+    this.id = id;
+    this.uri = uri;
+    this.items = items;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof AvailableSuggestionSet) {
+      AvailableSuggestionSet other = (AvailableSuggestionSet) obj;
+      return
+        other.id == id &&
+        ObjectUtilities.equals(other.uri, uri) &&
+        ObjectUtilities.equals(other.items, items);
+    }
+    return false;
+  }
+
+  public static AvailableSuggestionSet fromJson(JsonObject jsonObject) {
+    int id = jsonObject.get("id").getAsInt();
+    String uri = jsonObject.get("uri").getAsString();
+    List<AvailableSuggestion> items = AvailableSuggestion.fromJsonArray(jsonObject.get("items").getAsJsonArray());
+    return new AvailableSuggestionSet(id, uri, items);
+  }
+
+  public static List<AvailableSuggestionSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<AvailableSuggestionSet> list = new ArrayList<AvailableSuggestionSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The id associated with the library.
+   */
+  public int getId() {
+    return id;
+  }
+
+  public List<AvailableSuggestion> getItems() {
+    return items;
+  }
+
+  /**
+   * The URI of the library.
+   */
+  public String getUri() {
+    return uri;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(id);
+    builder.append(uri);
+    builder.append(items);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("id", id);
+    jsonObject.addProperty("uri", uri);
+    JsonArray jsonArrayItems = new JsonArray();
+    for (AvailableSuggestion elt : items) {
+      jsonArrayItems.add(elt.toJson());
+    }
+    jsonObject.add("items", jsonArrayItems);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("id=");
+    builder.append(id + ", ");
+    builder.append("uri=");
+    builder.append(uri + ", ");
+    builder.append("items=");
+    builder.append(StringUtils.join(items, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
new file mode 100644
index 0000000..d7a0d19
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/CompletionService.java
@@ -0,0 +1,26 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * An enumeration of the completion services to which a client can subscribe.
+ *
+ * @coverage dart.server.generated.types
+ */
+public class CompletionService {
+
+  /**
+   * The client will receive notifications once subscribed with completion suggestion sets from the
+   * libraries of interest. The client should keep an up-to-date record of these in memory so that it
+   * will be able to union these candidates with other completion suggestions when applicable at
+   * completion time.
+   */
+  public static final String AVAILABLE_SUGGESTION_SETS = "AVAILABLE_SUGGESTION_SETS";
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/DartFix.java b/pkg/analysis_server/tool/spec/generated/java/types/DartFix.java
new file mode 100644
index 0000000..b441025
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/DartFix.java
@@ -0,0 +1,149 @@
+/*
+ * 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.
+ *
+ * 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 "fix" that can be specified in an edit.dartfix request.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class DartFix {
+
+  public static final DartFix[] EMPTY_ARRAY = new DartFix[0];
+
+  public static final List<DartFix> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The name of the fix.
+   */
+  private final String name;
+
+  /**
+   * A human readable description of the fix.
+   */
+  private final String description;
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  private final Boolean isRequired;
+
+  /**
+   * Constructor for {@link DartFix}.
+   */
+  public DartFix(String name, String description, Boolean isRequired) {
+    this.name = name;
+    this.description = description;
+    this.isRequired = isRequired;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof DartFix) {
+      DartFix other = (DartFix) obj;
+      return
+        ObjectUtilities.equals(other.name, name) &&
+        ObjectUtilities.equals(other.description, description) &&
+        ObjectUtilities.equals(other.isRequired, isRequired);
+    }
+    return false;
+  }
+
+  public static DartFix fromJson(JsonObject jsonObject) {
+    String name = jsonObject.get("name").getAsString();
+    String description = jsonObject.get("description") == null ? null : jsonObject.get("description").getAsString();
+    Boolean isRequired = jsonObject.get("isRequired") == null ? null : jsonObject.get("isRequired").getAsBoolean();
+    return new DartFix(name, description, isRequired);
+  }
+
+  public static List<DartFix> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<DartFix> list = new ArrayList<DartFix>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * A human readable description of the fix.
+   */
+  public String getDescription() {
+    return description;
+  }
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  public Boolean getIsRequired() {
+    return isRequired;
+  }
+
+  /**
+   * The name of the fix.
+   */
+  public String getName() {
+    return name;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(name);
+    builder.append(description);
+    builder.append(isRequired);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("name", name);
+    if (description != null) {
+      jsonObject.addProperty("description", description);
+    }
+    if (isRequired != null) {
+      jsonObject.addProperty("isRequired", isRequired);
+    }
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("name=");
+    builder.append(name + ", ");
+    builder.append("description=");
+    builder.append(description + ", ");
+    builder.append("isRequired=");
+    builder.append(isRequired);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionRelevanceTag.java b/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionRelevanceTag.java
new file mode 100644
index 0000000..d079df2
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionRelevanceTag.java
@@ -0,0 +1,130 @@
+/*
+ * 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.
+ *
+ * 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;
+
+/**
+ * Each AvailableSuggestion can specify zero or more tags in the field relevanceTags, so that when
+ * the included tag is equal to one of the relevanceTags, the suggestion is given higher relevance
+ * than the whole IncludedSuggestionSet.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class IncludedSuggestionRelevanceTag {
+
+  public static final IncludedSuggestionRelevanceTag[] EMPTY_ARRAY = new IncludedSuggestionRelevanceTag[0];
+
+  public static final List<IncludedSuggestionRelevanceTag> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The opaque value of the tag.
+   */
+  private final AvailableSuggestionRelevanceTag tag;
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this tag, which is added to
+   * the relevance of the containing IncludedSuggestionSet.
+   */
+  private final int relevanceBoost;
+
+  /**
+   * Constructor for {@link IncludedSuggestionRelevanceTag}.
+   */
+  public IncludedSuggestionRelevanceTag(AvailableSuggestionRelevanceTag tag, int relevanceBoost) {
+    this.tag = tag;
+    this.relevanceBoost = relevanceBoost;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof IncludedSuggestionRelevanceTag) {
+      IncludedSuggestionRelevanceTag other = (IncludedSuggestionRelevanceTag) obj;
+      return
+        ObjectUtilities.equals(other.tag, tag) &&
+        other.relevanceBoost == relevanceBoost;
+    }
+    return false;
+  }
+
+  public static IncludedSuggestionRelevanceTag fromJson(JsonObject jsonObject) {
+    AvailableSuggestionRelevanceTag tag = AvailableSuggestionRelevanceTag.fromJson(jsonObject.get("tag").getAsJsonObject());
+    int relevanceBoost = jsonObject.get("relevanceBoost").getAsInt();
+    return new IncludedSuggestionRelevanceTag(tag, relevanceBoost);
+  }
+
+  public static List<IncludedSuggestionRelevanceTag> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<IncludedSuggestionRelevanceTag> list = new ArrayList<IncludedSuggestionRelevanceTag>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this tag, which is added to
+   * the relevance of the containing IncludedSuggestionSet.
+   */
+  public int getRelevanceBoost() {
+    return relevanceBoost;
+  }
+
+  /**
+   * The opaque value of the tag.
+   */
+  public AvailableSuggestionRelevanceTag getTag() {
+    return tag;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(tag);
+    builder.append(relevanceBoost);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.add("tag", tag.toJson());
+    jsonObject.addProperty("relevanceBoost", relevanceBoost);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("tag=");
+    builder.append(tag + ", ");
+    builder.append("relevanceBoost=");
+    builder.append(relevanceBoost);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionSet.java b/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionSet.java
new file mode 100644
index 0000000..344ac5b
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/IncludedSuggestionSet.java
@@ -0,0 +1,129 @@
+/*
+ * 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.
+ *
+ * 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 reference to an AvailableSuggestionSet noting that the library's members which match the kind
+ * of this ref should be presented to the user.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class IncludedSuggestionSet {
+
+  public static final IncludedSuggestionSet[] EMPTY_ARRAY = new IncludedSuggestionSet[0];
+
+  public static final List<IncludedSuggestionSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be displayed to the user.
+   */
+  private final int id;
+
+  /**
+   * The relevance of completion suggestions from this library where a higher number indicates a
+   * higher relevance.
+   */
+  private final int relevance;
+
+  /**
+   * Constructor for {@link IncludedSuggestionSet}.
+   */
+  public IncludedSuggestionSet(int id, int relevance) {
+    this.id = id;
+    this.relevance = relevance;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof IncludedSuggestionSet) {
+      IncludedSuggestionSet other = (IncludedSuggestionSet) obj;
+      return
+        other.id == id &&
+        other.relevance == relevance;
+    }
+    return false;
+  }
+
+  public static IncludedSuggestionSet fromJson(JsonObject jsonObject) {
+    int id = jsonObject.get("id").getAsInt();
+    int relevance = jsonObject.get("relevance").getAsInt();
+    return new IncludedSuggestionSet(id, relevance);
+  }
+
+  public static List<IncludedSuggestionSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<IncludedSuggestionSet> list = new ArrayList<IncludedSuggestionSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be displayed to the user.
+   */
+  public int getId() {
+    return id;
+  }
+
+  /**
+   * The relevance of completion suggestions from this library where a higher number indicates a
+   * higher relevance.
+   */
+  public int getRelevance() {
+    return relevance;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(id);
+    builder.append(relevance);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("id", id);
+    jsonObject.addProperty("relevance", relevance);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("id=");
+    builder.append(id + ", ");
+    builder.append("relevance=");
+    builder.append(relevance);
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/LibraryPathSet.java b/pkg/analysis_server/tool/spec/generated/java/types/LibraryPathSet.java
new file mode 100644
index 0000000..de46030
--- /dev/null
+++ b/pkg/analysis_server/tool/spec/generated/java/types/LibraryPathSet.java
@@ -0,0 +1,135 @@
+/*
+ * 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.
+ *
+ * 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 list of associations between paths and the libraries that should be included for code
+ * completion when editing a file beneath that path.
+ *
+ * @coverage dart.server.generated.types
+ */
+@SuppressWarnings("unused")
+public class LibraryPathSet {
+
+  public static final LibraryPathSet[] EMPTY_ARRAY = new LibraryPathSet[0];
+
+  public static final List<LibraryPathSet> EMPTY_LIST = Lists.newArrayList();
+
+  /**
+   * The filepath for which this request's libraries should be active in completion suggestions. This
+   * object associates filesystem regions to libraries and library directories of interest to the
+   * client.
+   */
+  private final String scope;
+
+  /**
+   * The paths of the libraries of interest to the client for completion suggestions.
+   */
+  private final List<String> libraryPaths;
+
+  /**
+   * Constructor for {@link LibraryPathSet}.
+   */
+  public LibraryPathSet(String scope, List<String> libraryPaths) {
+    this.scope = scope;
+    this.libraryPaths = libraryPaths;
+  }
+
+  @Override
+  public boolean equals(Object obj) {
+    if (obj instanceof LibraryPathSet) {
+      LibraryPathSet other = (LibraryPathSet) obj;
+      return
+        ObjectUtilities.equals(other.scope, scope) &&
+        ObjectUtilities.equals(other.libraryPaths, libraryPaths);
+    }
+    return false;
+  }
+
+  public static LibraryPathSet fromJson(JsonObject jsonObject) {
+    String scope = jsonObject.get("scope").getAsString();
+    List<String> libraryPaths = JsonUtilities.decodeStringList(jsonObject.get("libraryPaths").getAsJsonArray());
+    return new LibraryPathSet(scope, libraryPaths);
+  }
+
+  public static List<LibraryPathSet> fromJsonArray(JsonArray jsonArray) {
+    if (jsonArray == null) {
+      return EMPTY_LIST;
+    }
+    ArrayList<LibraryPathSet> list = new ArrayList<LibraryPathSet>(jsonArray.size());
+    Iterator<JsonElement> iterator = jsonArray.iterator();
+    while (iterator.hasNext()) {
+      list.add(fromJson(iterator.next().getAsJsonObject()));
+    }
+    return list;
+  }
+
+  /**
+   * The paths of the libraries of interest to the client for completion suggestions.
+   */
+  public List<String> getLibraryPaths() {
+    return libraryPaths;
+  }
+
+  /**
+   * The filepath for which this request's libraries should be active in completion suggestions. This
+   * object associates filesystem regions to libraries and library directories of interest to the
+   * client.
+   */
+  public String getScope() {
+    return scope;
+  }
+
+  @Override
+  public int hashCode() {
+    HashCodeBuilder builder = new HashCodeBuilder();
+    builder.append(scope);
+    builder.append(libraryPaths);
+    return builder.toHashCode();
+  }
+
+  public JsonObject toJson() {
+    JsonObject jsonObject = new JsonObject();
+    jsonObject.addProperty("scope", scope);
+    JsonArray jsonArrayLibraryPaths = new JsonArray();
+    for (String elt : libraryPaths) {
+      jsonArrayLibraryPaths.add(new JsonPrimitive(elt));
+    }
+    jsonObject.add("libraryPaths", jsonArrayLibraryPaths);
+    return jsonObject;
+  }
+
+  @Override
+  public String toString() {
+    StringBuilder builder = new StringBuilder();
+    builder.append("[");
+    builder.append("scope=");
+    builder.append(scope + ", ");
+    builder.append("libraryPaths=");
+    builder.append(StringUtils.join(libraryPaths, ", "));
+    builder.append("]");
+    return builder.toString();
+  }
+
+}
diff --git a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
index b212bf7..dbd738a 100644
--- a/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
+++ b/pkg/analysis_server/tool/spec/generated/java/types/RequestErrorCode.java
@@ -165,6 +165,12 @@
   public static final String SORT_MEMBERS_PARSE_ERRORS = "SORT_MEMBERS_PARSE_ERRORS";
 
   /**
+   * A dartfix request was received containing the name of a fix which does not match the name of any
+   * known fixes.
+   */
+  public static final String UNKNOWN_FIX = "UNKNOWN_FIX";
+
+  /**
    * A request was received which the analysis server does not recognize, or cannot handle in its
    * current configuration.
    */
diff --git a/pkg/analysis_server/tool/spec/implied_types.dart b/pkg/analysis_server/tool/spec/implied_types.dart
index 856b2a4..2cf1c8b 100644
--- a/pkg/analysis_server/tool/spec/implied_types.dart
+++ b/pkg/analysis_server/tool/spec/implied_types.dart
@@ -5,7 +5,7 @@
 /**
  * Code for enumerating the set of types implied by the API.
  */
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 
diff --git a/pkg/analysis_server/tool/spec/spec_input.html b/pkg/analysis_server/tool/spec/spec_input.html
index 2418991..fd11715 100644
--- a/pkg/analysis_server/tool/spec/spec_input.html
+++ b/pkg/analysis_server/tool/spec/spec_input.html
@@ -7,7 +7,7 @@
 <body>
 <h1>Analysis Server API Specification</h1>
 <h1 style="color:#999999">Version
-  <version>1.22.1</version>
+  <version>1.23.0</version>
 </h1>
 <p>
   This document contains a specification of the API provided by the
@@ -1412,6 +1412,102 @@
       </field>
     </result>
   </request>
+  <request method="setSubscriptions" experimental="true">
+    <p>
+      Subscribe for completion services. All previous subscriptions are
+      replaced by the given set of services.
+    </p>
+    <p>
+      It is an error if any of the elements in the list are not valid
+      services. If there is an error, then the current subscriptions will
+      remain unchanged.
+    </p>
+    <params>
+      <field name="subscriptions">
+        <list>
+          <ref>CompletionService</ref>
+        </list>
+        <p>A list of the services being subscribed to.</p>
+      </field>
+    </params>
+  </request>
+  <request method="registerLibraryPaths" experimental="true">
+    <p>
+      The client can make this request to express interest in certain
+      libraries to receive completion suggestions from based on the client path.
+      If this request is received before the client has used
+      'completion.setSubscriptions' to subscribe to the <tt>AVAILABLE_SUGGESTION_SETS</tt>
+      service, then an error of type <tt>NOT_SUBSCRIBED_TO_AVAILABLE_SUGGESTION_SETS</tt>
+      will be generated. All previous paths are replaced by the given set of paths.
+    </p>
+    <params>
+      <field name="paths">
+        <list>
+          <ref>LibraryPathSet</ref>
+        </list>
+        <p>
+          A list of objects each containing a path and the additional libraries from which
+          the client is interested in receiving completion suggestions.
+          If one configured path is beneath another, the descendent
+          will override the ancestors' configured libraries of interest.
+        </p>
+      </field>
+    </params>
+  </request>
+  <request method="getSuggestionDetails" experimental="true">
+    <p>
+      Clients must make this request when the user has selected a completion
+      suggestion from an <tt>AvailableSuggestionSet</tt>. Analysis server will respond with
+      the text to insert as well as any <tt>SourceChange</tt> that needs to be applied
+      in case the completion requires an additional import to be added. It is an error
+      if the id is no longer valid, for instance if the library has been removed after
+      the completion suggestion is accepted.
+    </p>
+    <params>
+      <field name="file">
+        <ref>FilePath</ref>
+        <p>
+          The path of the file into which this completion is being inserted.
+        </p>
+      </field>
+      <field name="id">
+        <ref>int</ref>
+        <p>
+          The identifier of the <tt>AvailableSuggestionSet</tt> containing
+          the selected label.
+        </p>
+      </field>
+      <field name="label">
+        <ref>String</ref>
+        <p>
+          The label from the <tt>AvailableSuggestionSet</tt> with the `id`
+          for which insertion information is requested.
+        </p>
+      </field>
+      <field name="offset">
+        <ref>int</ref>
+        <p>
+          The offset in the file where the completion will be inserted.
+        </p>
+      </field>
+    </params>
+    <result>
+      <field name="completion">
+        <ref>String</ref>
+        <p>
+          The full text to insert, including any optional import prefix.
+        </p>
+      </field>
+      <field name="change" optional="true">
+        <ref>SourceChange</ref>
+        <p>
+          A change for the client to apply in case the library containing
+          the accepted completion suggestion needs to be imported. The field
+          will be omitted if there are no additional changes that need to be made.
+        </p>
+      </field>
+    </result>
+  </request>
   <notification event="results">
     <p>
       Reports the completion suggestions that should be presented
@@ -1466,6 +1562,83 @@
           returned for the indicated completion.
         </p>
       </field>
+      <field name="includedSuggestionSets" optional="true">
+        <list>
+          <ref>IncludedSuggestionSet</ref>
+        </list>
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          References to <tt>AvailableSuggestionSet</tt> objects previously sent
+          to the client. The client can include applicable names from the
+          referenced library in code completion suggestions.
+        </p>
+      </field>
+      <field name="includedSuggestionKinds" optional="true">
+        <list>
+          <ref>ElementKind</ref>
+        </list>
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          The client is expected to check this list against the
+          <tt>ElementKind</tt> sent in <tt>IncludedSuggestionSet</tt> to decide
+          whether or not these symbols should should be presented to the user.
+        </p>
+      </field>
+      <field name="includedSuggestionRelevanceTags" optional="true">
+        <list>
+          <ref>IncludedSuggestionRelevanceTag</ref>
+        </list>
+        <p>
+          This field is experimental.
+        </p>
+        <p>
+          The client is expected to check this list against the values of the
+          field <tt>relevanceTags</tt> of <tt>AvailableSuggestion</tt> to
+          decide if the suggestion should be given a different relevance than
+          the <tt>IncludedSuggestionSet</tt> that contains it. This might be
+          used for example to give higher relevance to suggestions of matching
+          types.
+        </p>
+        <p>
+          If an <tt>AvailableSuggestion</tt> has relevance tags that match more
+          than one <tt>IncludedSuggestionRelevanceTag</tt>, the maximum
+          relevance boost is used.
+        </p>
+      </field>
+    </params>
+  </notification>
+  <notification event="availableSuggestions" experimental="true">
+    <p>
+      Reports the pre-computed, candidate completions from symbols defined
+      in a corresponding library. This notification may be sent multiple times.
+      When a notification is processed, clients should replace any previous
+      information about the libraries in the list of changedLibraries, discard
+      any information about the libraries in the list of removedLibraries, and
+      preserve any previously received information about any libraries that are
+      not included in either list.
+    </p>
+    <params>
+      <field name="changedLibraries" optional="true">
+        <list>
+          <ref>AvailableSuggestionSet</ref>
+        </list>
+        <p>
+          A list of pre-computed, potential completions coming from
+          this set of completion suggestions.
+        </p>
+      </field>
+      <field name="removedLibraries" optional="true">
+        <list>
+          <ref>int</ref>
+        </list>
+        <p>
+          A list of library ids that no longer apply.
+        </p>
+      </field>
     </params>
   </notification>
 </domain>
@@ -1915,6 +2088,26 @@
       </field>
     </result>
   </request>
+  <request method="getDartfixInfo" experimental="true">
+    <p>
+      Request information about edit.dartfix
+      such as the list of known fixes that can be specified
+      in an edit.dartfix request.
+    </p>
+    <params>
+    </params>
+    <result>
+      <field name="fixes">
+        <list>
+          <ref>DartFix</ref>
+        </list>
+        <p>
+          A list of fixes that can be specified
+          in an edit.dartfix request.
+        </p>
+      </field>
+    </result>
+  </request>
   <request method="dartfix" experimental="true">
     <p>
       Analyze the specified sources for recommended changes
@@ -1922,6 +2115,15 @@
       These edits may include changes to sources outside the set
       of specified sources if a change in a specified source requires it.
     </p>
+    <p>
+      If includedFixes is specified, then those fixes will be applied.
+      If includeRequiredFixes is specified, then "required" fixes will be applied
+      in addition to whatever fixes are specified in includedFixes if any.
+      If neither includedFixes nor includeRequiredFixes is specified,
+      then all fixes will be applied.
+      If excludedFixes is specified, then those fixes will not be applied
+      regardless of whether they are "required" or specified in includedFixes.
+    </p>
     <params>
       <field name="included">
         <list>
@@ -1938,6 +2140,36 @@
           an error of type <tt>FILE_NOT_ANALYZED</tt> will be generated.
         </p>
       </field>
+      <field name="includedFixes" optional="true">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          A list of names indicating which fixes should be applied.
+        </p>
+        <p>
+          If a name is specified that does not match the name of a known fix,
+          an error of type <tt>UNKNOWN_FIX</tt> will be generated.
+        </p>
+      </field>
+      <field name="includeRequiredFixes" optional="true">
+        <ref>bool</ref>
+        <p>
+          A flag indicating that "required" fixes should be applied.
+        </p>
+      </field>
+      <field name="excludedFixes" optional="true">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          A list of names indicating which fixes should not be applied.
+        </p>
+        <p>
+          If a name is specified that does not match the name of a known fix,
+          an error of type <tt>UNKNOWN_FIX</tt> will be generated.
+        </p>
+      </field>
     </params>
     <result>
       <field name="suggestions">
@@ -3293,6 +3525,188 @@
       The identifier for a execution context.
     </p>
   </type>
+  <type name="AvailableSuggestion" experimental="true">
+    <p>
+      A partial completion suggestion that can be used in combination with
+      info from <tt>completion.results</tt> to build completion suggestions
+      for not yet imported library tokens.
+    </p>
+    <object>
+      <field name="label">
+        <ref>String</ref>
+        <p>
+          The identifier to present to the user for code completion.
+        </p>
+      </field>
+      <field name="element">
+        <ref>Element</ref>
+        <p>
+          Information about the element reference being suggested.
+        </p>
+      </field>
+      <field name="docComplete" optional="true">
+        <ref>String</ref>
+        <p>
+          The Dartdoc associated with the element being suggested. This field
+          is omitted if there is no Dartdoc associated with the element.
+        </p>
+      </field>
+      <field name="docSummary" optional="true">
+        <ref>String</ref>
+        <p>
+          An abbreviated version of the Dartdoc associated with the element being suggested.
+          This field is omitted if there is no Dartdoc associated with the element.
+        </p>
+      </field>
+      <field name="parameterNames" optional="true">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          If the element is an executable, the names of the formal parameters of
+          all kinds - required, optional positional, and optional named. The
+          names of positional parameters are empty strings. Omitted if the element
+          is not an executable.
+        </p>
+      </field>
+      <field name="parameterTypes" optional="true">
+        <list>
+          <ref>String</ref>
+        </list>
+        <p>
+          If the element is an executable, the declared types of the formal parameters
+          of all kinds - required, optional positional, and optional named.
+          Omitted if the element is not an executable.
+        </p>
+      </field>
+      <field name="relevanceTags" optional="true">
+        <list>
+          <ref>AvailableSuggestionRelevanceTag</ref>
+        </list>
+        <p>
+          This field is set if the relevance of this suggestion might be
+          changed depending on where completion is requested.
+        </p>
+      </field>
+      <field name="requiredParameterCount" optional="true">
+        <ref>int</ref>
+      </field>
+    </object>
+  </type>
+  <type name="AvailableSuggestionRelevanceTag">
+    <ref>String</ref>
+    <p>
+      The opaque tag value.
+    </p>
+  </type>
+  <type name="AvailableSuggestionSet" experimental="true">
+    <object>
+      <field name="id">
+        <ref>int</ref>
+        <p>
+          The id associated with the library.
+        </p>
+      </field>
+      <field name="uri">
+        <ref>String</ref>
+        <p>
+          The URI of the library.
+        </p>
+      </field>
+      <field name="items">
+        <list>
+          <ref>AvailableSuggestion</ref>
+        </list>
+      </field>
+    </object>
+  </type>
+  <type name="IncludedSuggestionSet" experimental="true">
+    <p>
+      A reference to an <tt>AvailableSuggestionSet</tt> noting
+      that the library's members which match the kind of this ref
+      should be presented to the user.
+    </p>
+    <object>
+      <field name="id">
+        <ref>int</ref>
+        <p>
+          Clients should use it to access the set of precomputed completions
+          to be displayed to the user.
+        </p>
+      </field>
+      <field name="relevance">
+        <ref>int</ref>
+        <p>
+          The relevance of completion suggestions from this
+          library where a higher number indicates a higher relevance.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="IncludedSuggestionRelevanceTag" experimental="true">
+    <p>
+      Each <tt>AvailableSuggestion</tt> can specify zero or more tags in the
+      field <tt>relevanceTags</tt>, so that when the included tag is equal to
+      one of the <tt>relevanceTags</tt>, the suggestion is given higher
+      relevance than the whole <tt>IncludedSuggestionSet</tt>.
+    </p>
+    <object>
+      <field name="tag">
+        <ref>AvailableSuggestionRelevanceTag</ref>
+        <p>
+          The opaque value of the tag.
+        </p>
+      </field>
+      <field name="relevanceBoost">
+        <ref>int</ref>
+        <p>
+          The boost to the relevance of the completion suggestions that match
+          this tag, which is added to the relevance of the containing
+          <tt>IncludedSuggestionSet</tt>.
+        </p>
+      </field>
+    </object>
+  </type>
+  <type name="CompletionService" experimental="true">
+    <p>
+      An enumeration of the completion services to which a client can subscribe.
+    </p>
+    <enum>
+      <value>
+        <code>AVAILABLE_SUGGESTION_SETS</code>
+        <p>
+          The client will receive notifications once subscribed with completion suggestion sets from
+          the libraries of interest. The client should keep an up-to-date record of these in
+          memory so that it will be able to union these candidates with other
+          completion suggestions when applicable at completion time.
+        </p>
+      </value>
+    </enum>
+  </type>
+  <type name="LibraryPathSet" experimental="true">
+    <p>
+      A list of associations between paths and the libraries that should be
+      included for code completion when editing a file beneath that path.
+    </p>
+    <object>
+      <field name="scope">
+        <ref>FilePath</ref>
+        <p>
+          The filepath for which this request's libraries should be active
+          in completion suggestions. This object associates filesystem regions
+          to libraries and library directories of interest to the client.
+        </p>
+      </field>
+      <field name="libraryPaths">
+        <list>
+          <ref>FilePath</ref>
+        </list>
+        <p>
+          The paths of the libraries of interest to the client for completion suggestions.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="RuntimeCompletionExpression">
     <p>
       An expression for which we want to know its runtime type.
@@ -4186,6 +4600,13 @@
         </p>
       </value>
       <value>
+        <code>UNKNOWN_FIX</code>
+        <p>
+          A dartfix request was received containing the name of a fix
+          which does not match the name of any known fixes.
+        </p>
+      </value>
+      <value>
         <code>UNKNOWN_REQUEST</code>
         <p>
           A request was received which the analysis server does
@@ -4215,6 +4636,31 @@
       request.
     </p>
   </type>
+  <type name="DartFix" experimental="true">
+    <p>
+      A "fix" that can be specified in an edit.dartfix request.
+    </p>
+    <object>
+      <field name="name">
+        <ref>String</ref>
+        <p>
+          The name of the fix.
+        </p>
+      </field>
+      <field name="description" optional="true">
+        <ref>String</ref>
+        <p>
+          A human readable description of the fix.
+        </p>
+      </field>
+      <field name="isRequired" optional="true">
+        <ref>bool</ref>
+        <p>
+          `true` if the fix is in the "required" fixes group.
+        </p>
+      </field>
+    </object>
+  </type>
   <type name="DartFixSuggestion" experimental="true">
     <p>
       A suggestion from an edit.dartfix request.
diff --git a/pkg/analysis_server/tool/spec/to_html.dart b/pkg/analysis_server/tool/spec/to_html.dart
index 1683331..820948c 100644
--- a/pkg/analysis_server/tool/spec/to_html.dart
+++ b/pkg/analysis_server/tool/spec/to_html.dart
@@ -9,8 +9,8 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/html.dart';
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/html.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 
 import 'api.dart';
diff --git a/pkg/analysis_server_client/lib/handler/notification_handler.dart b/pkg/analysis_server_client/lib/handler/notification_handler.dart
index 8bdbf14..97ec840 100644
--- a/pkg/analysis_server_client/lib/handler/notification_handler.dart
+++ b/pkg/analysis_server_client/lib/handler/notification_handler.dart
@@ -67,6 +67,11 @@
         onAnalysisOverrides(
             new AnalysisOverridesParams.fromJson(decoder, 'params', params));
         break;
+      case COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS:
+        onCompletionAvailableSuggestions(
+            new CompletionAvailableSuggestionsParams.fromJson(
+                decoder, 'params', params));
+        break;
       case COMPLETION_NOTIFICATION_RESULTS:
         onCompletionResults(
             new CompletionResultsParams.fromJson(decoder, 'params', params));
@@ -206,6 +211,16 @@
   /// request.
   void onAnalysisOverrides(AnalysisOverridesParams params) {}
 
+  /// Reports the pre-computed, candidate completions from symbols defined
+  /// in a corresponding library. This notification may be sent multiple times.
+  /// When a notification is processed, clients should replace any previous
+  /// information about the libraries in the list of changedLibraries, discard
+  /// any information about the libraries in the list of removedLibraries, and
+  /// preserve any previously received information about any libraries that are
+  /// not included in either list.
+  void onCompletionAvailableSuggestions(
+      CompletionAvailableSuggestionsParams params) {}
+
   /// Reports the completion suggestions that should be presented
   /// to the user. The set of suggestions included in the
   /// notification is always a complete list that supersedes any
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
index fd21adb..d599adc 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_constants.dart
@@ -6,7 +6,7 @@
 // To regenerate the file, use the script
 // "pkg/analysis_server/tool/spec/generate_files".
 
-const String PROTOCOL_VERSION = '1.22.1';
+const String PROTOCOL_VERSION = '1.23.0';
 
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES = 'analysis.analyzedFiles';
 const String ANALYSIS_NOTIFICATION_ANALYZED_FILES_DIRECTORIES = 'directories';
@@ -110,8 +110,21 @@
 const String ANALYTICS_REQUEST_SEND_TIMING_EVENT = 'event';
 const String ANALYTICS_REQUEST_SEND_TIMING_MILLIS = 'millis';
 const String ANALYTICS_RESPONSE_IS_ENABLED_ENABLED = 'enabled';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS =
+    'completion.availableSuggestions';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_CHANGED_LIBRARIES =
+    'changedLibraries';
+const String COMPLETION_NOTIFICATION_AVAILABLE_SUGGESTIONS_REMOVED_LIBRARIES =
+    'removedLibraries';
 const String COMPLETION_NOTIFICATION_RESULTS = 'completion.results';
 const String COMPLETION_NOTIFICATION_RESULTS_ID = 'id';
+const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_KINDS =
+    'includedSuggestionKinds';
+const String
+    COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_RELEVANCE_TAGS =
+    'includedSuggestionRelevanceTags';
+const String COMPLETION_NOTIFICATION_RESULTS_INCLUDED_SUGGESTION_SETS =
+    'includedSuggestionSets';
 const String COMPLETION_NOTIFICATION_RESULTS_IS_LAST = 'isLast';
 const String COMPLETION_NOTIFICATION_RESULTS_REPLACEMENT_LENGTH =
     'replacementLength';
@@ -121,13 +134,33 @@
 const String COMPLETION_REQUEST_GET_SUGGESTIONS = 'completion.getSuggestions';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_FILE = 'file';
 const String COMPLETION_REQUEST_GET_SUGGESTIONS_OFFSET = 'offset';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS =
+    'completion.getSuggestionDetails';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_FILE = 'file';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_ID = 'id';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_LABEL = 'label';
+const String COMPLETION_REQUEST_GET_SUGGESTION_DETAILS_OFFSET = 'offset';
+const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS =
+    'completion.registerLibraryPaths';
+const String COMPLETION_REQUEST_REGISTER_LIBRARY_PATHS_PATHS = 'paths';
+const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS =
+    'completion.setSubscriptions';
+const String COMPLETION_REQUEST_SET_SUBSCRIPTIONS_SUBSCRIPTIONS =
+    'subscriptions';
 const String COMPLETION_RESPONSE_GET_SUGGESTIONS_ID = 'id';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_CHANGE = 'change';
+const String COMPLETION_RESPONSE_GET_SUGGESTION_DETAILS_COMPLETION =
+    'completion';
 const String DIAGNOSTIC_REQUEST_GET_DIAGNOSTICS = 'diagnostic.getDiagnostics';
 const String DIAGNOSTIC_REQUEST_GET_SERVER_PORT = 'diagnostic.getServerPort';
 const String DIAGNOSTIC_RESPONSE_GET_DIAGNOSTICS_CONTEXTS = 'contexts';
 const String DIAGNOSTIC_RESPONSE_GET_SERVER_PORT_PORT = 'port';
 const String EDIT_REQUEST_DARTFIX = 'edit.dartfix';
+const String EDIT_REQUEST_DARTFIX_EXCLUDED_FIXES = 'excludedFixes';
 const String EDIT_REQUEST_DARTFIX_INCLUDED = 'included';
+const String EDIT_REQUEST_DARTFIX_INCLUDED_FIXES = 'includedFixes';
+const String EDIT_REQUEST_DARTFIX_INCLUDE_REQUIRED_FIXES =
+    'includeRequiredFixes';
 const String EDIT_REQUEST_FORMAT = 'edit.format';
 const String EDIT_REQUEST_FORMAT_FILE = 'file';
 const String EDIT_REQUEST_FORMAT_LINE_LENGTH = 'lineLength';
@@ -142,6 +175,7 @@
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_FILE = 'file';
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_LENGTH = 'length';
 const String EDIT_REQUEST_GET_AVAILABLE_REFACTORINGS_OFFSET = 'offset';
+const String EDIT_REQUEST_GET_DARTFIX_INFO = 'edit.getDartfixInfo';
 const String EDIT_REQUEST_GET_FIXES = 'edit.getFixes';
 const String EDIT_REQUEST_GET_FIXES_FILE = 'file';
 const String EDIT_REQUEST_GET_FIXES_OFFSET = 'offset';
@@ -183,6 +217,7 @@
 const String EDIT_RESPONSE_FORMAT_SELECTION_OFFSET = 'selectionOffset';
 const String EDIT_RESPONSE_GET_ASSISTS_ASSISTS = 'assists';
 const String EDIT_RESPONSE_GET_AVAILABLE_REFACTORINGS_KINDS = 'kinds';
+const String EDIT_RESPONSE_GET_DARTFIX_INFO_FIXES = 'fixes';
 const String EDIT_RESPONSE_GET_FIXES_FIXES = 'fixes';
 const String EDIT_RESPONSE_GET_POSTFIX_COMPLETION_CHANGE = 'change';
 const String EDIT_RESPONSE_GET_REFACTORING_CHANGE = 'change';
diff --git a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
index bea5464..6d464ab 100644
--- a/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
+++ b/pkg/analysis_server_client/lib/src/protocol/protocol_generated.dart
@@ -5071,6 +5071,415 @@
 }
 
 /**
+ * AvailableSuggestion
+ *
+ * {
+ *   "label": String
+ *   "element": Element
+ *   "docComplete": optional String
+ *   "docSummary": optional String
+ *   "parameterNames": optional List<String>
+ *   "parameterTypes": optional List<String>
+ *   "relevanceTags": optional List<AvailableSuggestionRelevanceTag>
+ *   "requiredParameterCount": optional int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class AvailableSuggestion implements HasToJson {
+  String _label;
+
+  Element _element;
+
+  String _docComplete;
+
+  String _docSummary;
+
+  List<String> _parameterNames;
+
+  List<String> _parameterTypes;
+
+  List<String> _relevanceTags;
+
+  int _requiredParameterCount;
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  String get label => _label;
+
+  /**
+   * The identifier to present to the user for code completion.
+   */
+  void set label(String value) {
+    assert(value != null);
+    this._label = value;
+  }
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  Element get element => _element;
+
+  /**
+   * Information about the element reference being suggested.
+   */
+  void set element(Element value) {
+    assert(value != null);
+    this._element = value;
+  }
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  String get docComplete => _docComplete;
+
+  /**
+   * The Dartdoc associated with the element being suggested. This field is
+   * omitted if there is no Dartdoc associated with the element.
+   */
+  void set docComplete(String value) {
+    this._docComplete = value;
+  }
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being
+   * suggested. This field is omitted if there is no Dartdoc associated with
+   * the element.
+   */
+  String get docSummary => _docSummary;
+
+  /**
+   * An abbreviated version of the Dartdoc associated with the element being
+   * suggested. This field is omitted if there is no Dartdoc associated with
+   * the element.
+   */
+  void set docSummary(String value) {
+    this._docSummary = value;
+  }
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all
+   * kinds - required, optional positional, and optional named. The names of
+   * positional parameters are empty strings. Omitted if the element is not an
+   * executable.
+   */
+  List<String> get parameterNames => _parameterNames;
+
+  /**
+   * If the element is an executable, the names of the formal parameters of all
+   * kinds - required, optional positional, and optional named. The names of
+   * positional parameters are empty strings. Omitted if the element is not an
+   * executable.
+   */
+  void set parameterNames(List<String> value) {
+    this._parameterNames = value;
+  }
+
+  /**
+   * If the element is an executable, the declared types of the formal
+   * parameters of all kinds - required, optional positional, and optional
+   * named. Omitted if the element is not an executable.
+   */
+  List<String> get parameterTypes => _parameterTypes;
+
+  /**
+   * If the element is an executable, the declared types of the formal
+   * parameters of all kinds - required, optional positional, and optional
+   * named. Omitted if the element is not an executable.
+   */
+  void set parameterTypes(List<String> value) {
+    this._parameterTypes = value;
+  }
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed
+   * depending on where completion is requested.
+   */
+  List<String> get relevanceTags => _relevanceTags;
+
+  /**
+   * This field is set if the relevance of this suggestion might be changed
+   * depending on where completion is requested.
+   */
+  void set relevanceTags(List<String> value) {
+    this._relevanceTags = value;
+  }
+
+  int get requiredParameterCount => _requiredParameterCount;
+
+  void set requiredParameterCount(int value) {
+    this._requiredParameterCount = value;
+  }
+
+  AvailableSuggestion(String label, Element element,
+      {String docComplete,
+      String docSummary,
+      List<String> parameterNames,
+      List<String> parameterTypes,
+      List<String> relevanceTags,
+      int requiredParameterCount}) {
+    this.label = label;
+    this.element = element;
+    this.docComplete = docComplete;
+    this.docSummary = docSummary;
+    this.parameterNames = parameterNames;
+    this.parameterTypes = parameterTypes;
+    this.relevanceTags = relevanceTags;
+    this.requiredParameterCount = requiredParameterCount;
+  }
+
+  factory AvailableSuggestion.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String label;
+      if (json.containsKey("label")) {
+        label = jsonDecoder.decodeString(jsonPath + ".label", json["label"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "label");
+      }
+      Element element;
+      if (json.containsKey("element")) {
+        element = new Element.fromJson(
+            jsonDecoder, jsonPath + ".element", json["element"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "element");
+      }
+      String docComplete;
+      if (json.containsKey("docComplete")) {
+        docComplete = jsonDecoder.decodeString(
+            jsonPath + ".docComplete", json["docComplete"]);
+      }
+      String docSummary;
+      if (json.containsKey("docSummary")) {
+        docSummary = jsonDecoder.decodeString(
+            jsonPath + ".docSummary", json["docSummary"]);
+      }
+      List<String> parameterNames;
+      if (json.containsKey("parameterNames")) {
+        parameterNames = jsonDecoder.decodeList(jsonPath + ".parameterNames",
+            json["parameterNames"], jsonDecoder.decodeString);
+      }
+      List<String> parameterTypes;
+      if (json.containsKey("parameterTypes")) {
+        parameterTypes = jsonDecoder.decodeList(jsonPath + ".parameterTypes",
+            json["parameterTypes"], jsonDecoder.decodeString);
+      }
+      List<String> relevanceTags;
+      if (json.containsKey("relevanceTags")) {
+        relevanceTags = jsonDecoder.decodeList(jsonPath + ".relevanceTags",
+            json["relevanceTags"], jsonDecoder.decodeString);
+      }
+      int requiredParameterCount;
+      if (json.containsKey("requiredParameterCount")) {
+        requiredParameterCount = jsonDecoder.decodeInt(
+            jsonPath + ".requiredParameterCount",
+            json["requiredParameterCount"]);
+      }
+      return new AvailableSuggestion(label, element,
+          docComplete: docComplete,
+          docSummary: docSummary,
+          parameterNames: parameterNames,
+          parameterTypes: parameterTypes,
+          relevanceTags: relevanceTags,
+          requiredParameterCount: requiredParameterCount);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "AvailableSuggestion", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["label"] = label;
+    result["element"] = element.toJson();
+    if (docComplete != null) {
+      result["docComplete"] = docComplete;
+    }
+    if (docSummary != null) {
+      result["docSummary"] = docSummary;
+    }
+    if (parameterNames != null) {
+      result["parameterNames"] = parameterNames;
+    }
+    if (parameterTypes != null) {
+      result["parameterTypes"] = parameterTypes;
+    }
+    if (relevanceTags != null) {
+      result["relevanceTags"] = relevanceTags;
+    }
+    if (requiredParameterCount != null) {
+      result["requiredParameterCount"] = requiredParameterCount;
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is AvailableSuggestion) {
+      return label == other.label &&
+          element == other.element &&
+          docComplete == other.docComplete &&
+          docSummary == other.docSummary &&
+          listEqual(parameterNames, other.parameterNames,
+              (String a, String b) => a == b) &&
+          listEqual(parameterTypes, other.parameterTypes,
+              (String a, String b) => a == b) &&
+          listEqual(relevanceTags, other.relevanceTags,
+              (String a, String b) => a == b) &&
+          requiredParameterCount == other.requiredParameterCount;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, element.hashCode);
+    hash = JenkinsSmiHash.combine(hash, docComplete.hashCode);
+    hash = JenkinsSmiHash.combine(hash, docSummary.hashCode);
+    hash = JenkinsSmiHash.combine(hash, parameterNames.hashCode);
+    hash = JenkinsSmiHash.combine(hash, parameterTypes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevanceTags.hashCode);
+    hash = JenkinsSmiHash.combine(hash, requiredParameterCount.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * AvailableSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "uri": String
+ *   "items": List<AvailableSuggestion>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class AvailableSuggestionSet implements HasToJson {
+  int _id;
+
+  String _uri;
+
+  List<AvailableSuggestion> _items;
+
+  /**
+   * The id associated with the library.
+   */
+  int get id => _id;
+
+  /**
+   * The id associated with the library.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The URI of the library.
+   */
+  String get uri => _uri;
+
+  /**
+   * The URI of the library.
+   */
+  void set uri(String value) {
+    assert(value != null);
+    this._uri = value;
+  }
+
+  List<AvailableSuggestion> get items => _items;
+
+  void set items(List<AvailableSuggestion> value) {
+    assert(value != null);
+    this._items = value;
+  }
+
+  AvailableSuggestionSet(int id, String uri, List<AvailableSuggestion> items) {
+    this.id = id;
+    this.uri = uri;
+    this.items = items;
+  }
+
+  factory AvailableSuggestionSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      String uri;
+      if (json.containsKey("uri")) {
+        uri = jsonDecoder.decodeString(jsonPath + ".uri", json["uri"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "uri");
+      }
+      List<AvailableSuggestion> items;
+      if (json.containsKey("items")) {
+        items = jsonDecoder.decodeList(
+            jsonPath + ".items",
+            json["items"],
+            (String jsonPath, Object json) =>
+                new AvailableSuggestion.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "items");
+      }
+      return new AvailableSuggestionSet(id, uri, items);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "AvailableSuggestionSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["id"] = id;
+    result["uri"] = uri;
+    result["items"] =
+        items.map((AvailableSuggestion value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is AvailableSuggestionSet) {
+      return id == other.id &&
+          uri == other.uri &&
+          listEqual(items, other.items,
+              (AvailableSuggestion a, AvailableSuggestion b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, uri.hashCode);
+    hash = JenkinsSmiHash.combine(hash, items.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * ClosingLabel
  *
  * {
@@ -5196,6 +5605,417 @@
 }
 
 /**
+ * completion.availableSuggestions params
+ *
+ * {
+ *   "changedLibraries": optional List<AvailableSuggestionSet>
+ *   "removedLibraries": optional List<int>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionAvailableSuggestionsParams implements HasToJson {
+  List<AvailableSuggestionSet> _changedLibraries;
+
+  List<int> _removedLibraries;
+
+  /**
+   * A list of pre-computed, potential completions coming from this set of
+   * completion suggestions.
+   */
+  List<AvailableSuggestionSet> get changedLibraries => _changedLibraries;
+
+  /**
+   * A list of pre-computed, potential completions coming from this set of
+   * completion suggestions.
+   */
+  void set changedLibraries(List<AvailableSuggestionSet> value) {
+    this._changedLibraries = value;
+  }
+
+  /**
+   * A list of library ids that no longer apply.
+   */
+  List<int> get removedLibraries => _removedLibraries;
+
+  /**
+   * A list of library ids that no longer apply.
+   */
+  void set removedLibraries(List<int> value) {
+    this._removedLibraries = value;
+  }
+
+  CompletionAvailableSuggestionsParams(
+      {List<AvailableSuggestionSet> changedLibraries,
+      List<int> removedLibraries}) {
+    this.changedLibraries = changedLibraries;
+    this.removedLibraries = removedLibraries;
+  }
+
+  factory CompletionAvailableSuggestionsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<AvailableSuggestionSet> changedLibraries;
+      if (json.containsKey("changedLibraries")) {
+        changedLibraries = jsonDecoder.decodeList(
+            jsonPath + ".changedLibraries",
+            json["changedLibraries"],
+            (String jsonPath, Object json) =>
+                new AvailableSuggestionSet.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
+      List<int> removedLibraries;
+      if (json.containsKey("removedLibraries")) {
+        removedLibraries = jsonDecoder.decodeList(
+            jsonPath + ".removedLibraries",
+            json["removedLibraries"],
+            jsonDecoder.decodeInt);
+      }
+      return new CompletionAvailableSuggestionsParams(
+          changedLibraries: changedLibraries,
+          removedLibraries: removedLibraries);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.availableSuggestions params", json);
+    }
+  }
+
+  factory CompletionAvailableSuggestionsParams.fromNotification(
+      Notification notification) {
+    return new CompletionAvailableSuggestionsParams.fromJson(
+        new ResponseDecoder(null), "params", notification.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    if (changedLibraries != null) {
+      result["changedLibraries"] = changedLibraries
+          .map((AvailableSuggestionSet value) => value.toJson())
+          .toList();
+    }
+    if (removedLibraries != null) {
+      result["removedLibraries"] = removedLibraries;
+    }
+    return result;
+  }
+
+  Notification toNotification() {
+    return new Notification("completion.availableSuggestions", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionAvailableSuggestionsParams) {
+      return listEqual(changedLibraries, other.changedLibraries,
+              (AvailableSuggestionSet a, AvailableSuggestionSet b) => a == b) &&
+          listEqual(removedLibraries, other.removedLibraries,
+              (int a, int b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, changedLibraries.hashCode);
+    hash = JenkinsSmiHash.combine(hash, removedLibraries.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.getSuggestionDetails params
+ *
+ * {
+ *   "file": FilePath
+ *   "id": int
+ *   "label": String
+ *   "offset": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionGetSuggestionDetailsParams implements RequestParams {
+  String _file;
+
+  int _id;
+
+  String _label;
+
+  int _offset;
+
+  /**
+   * The path of the file into which this completion is being inserted.
+   */
+  String get file => _file;
+
+  /**
+   * The path of the file into which this completion is being inserted.
+   */
+  void set file(String value) {
+    assert(value != null);
+    this._file = value;
+  }
+
+  /**
+   * The identifier of the AvailableSuggestionSet containing the selected
+   * label.
+   */
+  int get id => _id;
+
+  /**
+   * The identifier of the AvailableSuggestionSet containing the selected
+   * label.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The label from the AvailableSuggestionSet with the `id` for which
+   * insertion information is requested.
+   */
+  String get label => _label;
+
+  /**
+   * The label from the AvailableSuggestionSet with the `id` for which
+   * insertion information is requested.
+   */
+  void set label(String value) {
+    assert(value != null);
+    this._label = value;
+  }
+
+  /**
+   * The offset in the file where the completion will be inserted.
+   */
+  int get offset => _offset;
+
+  /**
+   * The offset in the file where the completion will be inserted.
+   */
+  void set offset(int value) {
+    assert(value != null);
+    this._offset = value;
+  }
+
+  CompletionGetSuggestionDetailsParams(
+      String file, int id, String label, int offset) {
+    this.file = file;
+    this.id = id;
+    this.label = label;
+    this.offset = offset;
+  }
+
+  factory CompletionGetSuggestionDetailsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String file;
+      if (json.containsKey("file")) {
+        file = jsonDecoder.decodeString(jsonPath + ".file", json["file"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "file");
+      }
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      String label;
+      if (json.containsKey("label")) {
+        label = jsonDecoder.decodeString(jsonPath + ".label", json["label"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "label");
+      }
+      int offset;
+      if (json.containsKey("offset")) {
+        offset = jsonDecoder.decodeInt(jsonPath + ".offset", json["offset"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "offset");
+      }
+      return new CompletionGetSuggestionDetailsParams(file, id, label, offset);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.getSuggestionDetails params", json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetailsParams.fromRequest(Request request) {
+    return new CompletionGetSuggestionDetailsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["file"] = file;
+    result["id"] = id;
+    result["label"] = label;
+    result["offset"] = offset;
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.getSuggestionDetails", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetailsParams) {
+      return file == other.file &&
+          id == other.id &&
+          label == other.label &&
+          offset == other.offset;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, file.hashCode);
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, label.hashCode);
+    hash = JenkinsSmiHash.combine(hash, offset.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.getSuggestionDetails result
+ *
+ * {
+ *   "completion": String
+ *   "change": optional SourceChange
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionGetSuggestionDetailsResult implements ResponseResult {
+  String _completion;
+
+  SourceChange _change;
+
+  /**
+   * The full text to insert, including any optional import prefix.
+   */
+  String get completion => _completion;
+
+  /**
+   * The full text to insert, including any optional import prefix.
+   */
+  void set completion(String value) {
+    assert(value != null);
+    this._completion = value;
+  }
+
+  /**
+   * A change for the client to apply in case the library containing the
+   * accepted completion suggestion needs to be imported. The field will be
+   * omitted if there are no additional changes that need to be made.
+   */
+  SourceChange get change => _change;
+
+  /**
+   * A change for the client to apply in case the library containing the
+   * accepted completion suggestion needs to be imported. The field will be
+   * omitted if there are no additional changes that need to be made.
+   */
+  void set change(SourceChange value) {
+    this._change = value;
+  }
+
+  CompletionGetSuggestionDetailsResult(String completion,
+      {SourceChange change}) {
+    this.completion = completion;
+    this.change = change;
+  }
+
+  factory CompletionGetSuggestionDetailsResult.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String completion;
+      if (json.containsKey("completion")) {
+        completion = jsonDecoder.decodeString(
+            jsonPath + ".completion", json["completion"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "completion");
+      }
+      SourceChange change;
+      if (json.containsKey("change")) {
+        change = new SourceChange.fromJson(
+            jsonDecoder, jsonPath + ".change", json["change"]);
+      }
+      return new CompletionGetSuggestionDetailsResult(completion,
+          change: change);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.getSuggestionDetails result", json);
+    }
+  }
+
+  factory CompletionGetSuggestionDetailsResult.fromResponse(Response response) {
+    return new CompletionGetSuggestionDetailsResult.fromJson(
+        new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        "result",
+        response.result);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["completion"] = completion;
+    if (change != null) {
+      result["change"] = change.toJson();
+    }
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionGetSuggestionDetailsResult) {
+      return completion == other.completion && change == other.change;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, completion.hashCode);
+    hash = JenkinsSmiHash.combine(hash, change.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * completion.getSuggestions params
  *
  * {
@@ -5391,6 +6211,130 @@
 }
 
 /**
+ * completion.registerLibraryPaths params
+ *
+ * {
+ *   "paths": List<LibraryPathSet>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionRegisterLibraryPathsParams implements RequestParams {
+  List<LibraryPathSet> _paths;
+
+  /**
+   * A list of objects each containing a path and the additional libraries from
+   * which the client is interested in receiving completion suggestions. If one
+   * configured path is beneath another, the descendent will override the
+   * ancestors' configured libraries of interest.
+   */
+  List<LibraryPathSet> get paths => _paths;
+
+  /**
+   * A list of objects each containing a path and the additional libraries from
+   * which the client is interested in receiving completion suggestions. If one
+   * configured path is beneath another, the descendent will override the
+   * ancestors' configured libraries of interest.
+   */
+  void set paths(List<LibraryPathSet> value) {
+    assert(value != null);
+    this._paths = value;
+  }
+
+  CompletionRegisterLibraryPathsParams(List<LibraryPathSet> paths) {
+    this.paths = paths;
+  }
+
+  factory CompletionRegisterLibraryPathsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<LibraryPathSet> paths;
+      if (json.containsKey("paths")) {
+        paths = jsonDecoder.decodeList(
+            jsonPath + ".paths",
+            json["paths"],
+            (String jsonPath, Object json) =>
+                new LibraryPathSet.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "paths");
+      }
+      return new CompletionRegisterLibraryPathsParams(paths);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.registerLibraryPaths params", json);
+    }
+  }
+
+  factory CompletionRegisterLibraryPathsParams.fromRequest(Request request) {
+    return new CompletionRegisterLibraryPathsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["paths"] =
+        paths.map((LibraryPathSet value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.registerLibraryPaths", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionRegisterLibraryPathsParams) {
+      return listEqual(
+          paths, other.paths, (LibraryPathSet a, LibraryPathSet b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, paths.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.registerLibraryPaths result
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionRegisterLibraryPathsResult implements ResponseResult {
+  @override
+  Map<String, dynamic> toJson() => <String, dynamic>{};
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: null);
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionRegisterLibraryPathsResult) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    return 104675661;
+  }
+}
+
+/**
  * completion.results params
  *
  * {
@@ -5399,6 +6343,9 @@
  *   "replacementLength": int
  *   "results": List<CompletionSuggestion>
  *   "isLast": bool
+ *   "includedSuggestionSets": optional List<IncludedSuggestionSet>
+ *   "includedSuggestionKinds": optional List<ElementKind>
+ *   "includedSuggestionRelevanceTags": optional List<IncludedSuggestionRelevanceTag>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -5414,6 +6361,12 @@
 
   bool _isLast;
 
+  List<IncludedSuggestionSet> _includedSuggestionSets;
+
+  List<ElementKind> _includedSuggestionKinds;
+
+  List<IncludedSuggestionRelevanceTag> _includedSuggestionRelevanceTags;
+
   /**
    * The id associated with the completion.
    */
@@ -5499,13 +6452,92 @@
     this._isLast = value;
   }
 
+  /**
+   * This field is experimental.
+   *
+   * References to AvailableSuggestionSet objects previously sent to the
+   * client. The client can include applicable names from the referenced
+   * library in code completion suggestions.
+   */
+  List<IncludedSuggestionSet> get includedSuggestionSets =>
+      _includedSuggestionSets;
+
+  /**
+   * This field is experimental.
+   *
+   * References to AvailableSuggestionSet objects previously sent to the
+   * client. The client can include applicable names from the referenced
+   * library in code completion suggestions.
+   */
+  void set includedSuggestionSets(List<IncludedSuggestionSet> value) {
+    this._includedSuggestionSets = value;
+  }
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the ElementKind sent in
+   * IncludedSuggestionSet to decide whether or not these symbols should should
+   * be presented to the user.
+   */
+  List<ElementKind> get includedSuggestionKinds => _includedSuggestionKinds;
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the ElementKind sent in
+   * IncludedSuggestionSet to decide whether or not these symbols should should
+   * be presented to the user.
+   */
+  void set includedSuggestionKinds(List<ElementKind> value) {
+    this._includedSuggestionKinds = value;
+  }
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the values of the field
+   * relevanceTags of AvailableSuggestion to decide if the suggestion should be
+   * given a different relevance than the IncludedSuggestionSet that contains
+   * it. This might be used for example to give higher relevance to suggestions
+   * of matching types.
+   *
+   * If an AvailableSuggestion has relevance tags that match more than one
+   * IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
+   */
+  List<IncludedSuggestionRelevanceTag> get includedSuggestionRelevanceTags =>
+      _includedSuggestionRelevanceTags;
+
+  /**
+   * This field is experimental.
+   *
+   * The client is expected to check this list against the values of the field
+   * relevanceTags of AvailableSuggestion to decide if the suggestion should be
+   * given a different relevance than the IncludedSuggestionSet that contains
+   * it. This might be used for example to give higher relevance to suggestions
+   * of matching types.
+   *
+   * If an AvailableSuggestion has relevance tags that match more than one
+   * IncludedSuggestionRelevanceTag, the maximum relevance boost is used.
+   */
+  void set includedSuggestionRelevanceTags(
+      List<IncludedSuggestionRelevanceTag> value) {
+    this._includedSuggestionRelevanceTags = value;
+  }
+
   CompletionResultsParams(String id, int replacementOffset,
-      int replacementLength, List<CompletionSuggestion> results, bool isLast) {
+      int replacementLength, List<CompletionSuggestion> results, bool isLast,
+      {List<IncludedSuggestionSet> includedSuggestionSets,
+      List<ElementKind> includedSuggestionKinds,
+      List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags}) {
     this.id = id;
     this.replacementOffset = replacementOffset;
     this.replacementLength = replacementLength;
     this.results = results;
     this.isLast = isLast;
+    this.includedSuggestionSets = includedSuggestionSets;
+    this.includedSuggestionKinds = includedSuggestionKinds;
+    this.includedSuggestionRelevanceTags = includedSuggestionRelevanceTags;
   }
 
   factory CompletionResultsParams.fromJson(
@@ -5550,8 +6582,37 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "isLast");
       }
+      List<IncludedSuggestionSet> includedSuggestionSets;
+      if (json.containsKey("includedSuggestionSets")) {
+        includedSuggestionSets = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionSets",
+            json["includedSuggestionSets"],
+            (String jsonPath, Object json) =>
+                new IncludedSuggestionSet.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
+      List<ElementKind> includedSuggestionKinds;
+      if (json.containsKey("includedSuggestionKinds")) {
+        includedSuggestionKinds = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionKinds",
+            json["includedSuggestionKinds"],
+            (String jsonPath, Object json) =>
+                new ElementKind.fromJson(jsonDecoder, jsonPath, json));
+      }
+      List<IncludedSuggestionRelevanceTag> includedSuggestionRelevanceTags;
+      if (json.containsKey("includedSuggestionRelevanceTags")) {
+        includedSuggestionRelevanceTags = jsonDecoder.decodeList(
+            jsonPath + ".includedSuggestionRelevanceTags",
+            json["includedSuggestionRelevanceTags"],
+            (String jsonPath, Object json) =>
+                new IncludedSuggestionRelevanceTag.fromJson(
+                    jsonDecoder, jsonPath, json));
+      }
       return new CompletionResultsParams(
-          id, replacementOffset, replacementLength, results, isLast);
+          id, replacementOffset, replacementLength, results, isLast,
+          includedSuggestionSets: includedSuggestionSets,
+          includedSuggestionKinds: includedSuggestionKinds,
+          includedSuggestionRelevanceTags: includedSuggestionRelevanceTags);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "completion.results params", json);
     }
@@ -5571,6 +6632,22 @@
     result["results"] =
         results.map((CompletionSuggestion value) => value.toJson()).toList();
     result["isLast"] = isLast;
+    if (includedSuggestionSets != null) {
+      result["includedSuggestionSets"] = includedSuggestionSets
+          .map((IncludedSuggestionSet value) => value.toJson())
+          .toList();
+    }
+    if (includedSuggestionKinds != null) {
+      result["includedSuggestionKinds"] = includedSuggestionKinds
+          .map((ElementKind value) => value.toJson())
+          .toList();
+    }
+    if (includedSuggestionRelevanceTags != null) {
+      result["includedSuggestionRelevanceTags"] =
+          includedSuggestionRelevanceTags
+              .map((IncludedSuggestionRelevanceTag value) => value.toJson())
+              .toList();
+    }
     return result;
   }
 
@@ -5589,7 +6666,17 @@
           replacementLength == other.replacementLength &&
           listEqual(results, other.results,
               (CompletionSuggestion a, CompletionSuggestion b) => a == b) &&
-          isLast == other.isLast;
+          isLast == other.isLast &&
+          listEqual(includedSuggestionSets, other.includedSuggestionSets,
+              (IncludedSuggestionSet a, IncludedSuggestionSet b) => a == b) &&
+          listEqual(includedSuggestionKinds, other.includedSuggestionKinds,
+              (ElementKind a, ElementKind b) => a == b) &&
+          listEqual(
+              includedSuggestionRelevanceTags,
+              other.includedSuggestionRelevanceTags,
+              (IncludedSuggestionRelevanceTag a,
+                      IncludedSuggestionRelevanceTag b) =>
+                  a == b);
     }
     return false;
   }
@@ -5602,11 +6689,191 @@
     hash = JenkinsSmiHash.combine(hash, replacementLength.hashCode);
     hash = JenkinsSmiHash.combine(hash, results.hashCode);
     hash = JenkinsSmiHash.combine(hash, isLast.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedSuggestionSets.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedSuggestionKinds.hashCode);
+    hash =
+        JenkinsSmiHash.combine(hash, includedSuggestionRelevanceTags.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
 
 /**
+ * CompletionService
+ *
+ * enum {
+ *   AVAILABLE_SUGGESTION_SETS
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionService implements Enum {
+  /**
+   * The client will receive notifications once subscribed with completion
+   * suggestion sets from the libraries of interest. The client should keep an
+   * up-to-date record of these in memory so that it will be able to union
+   * these candidates with other completion suggestions when applicable at
+   * completion time.
+   */
+  static const CompletionService AVAILABLE_SUGGESTION_SETS =
+      const CompletionService._("AVAILABLE_SUGGESTION_SETS");
+
+  /**
+   * A list containing all of the enum values that are defined.
+   */
+  static const List<CompletionService> VALUES = const <CompletionService>[
+    AVAILABLE_SUGGESTION_SETS
+  ];
+
+  @override
+  final String name;
+
+  const CompletionService._(this.name);
+
+  factory CompletionService(String name) {
+    switch (name) {
+      case "AVAILABLE_SUGGESTION_SETS":
+        return AVAILABLE_SUGGESTION_SETS;
+    }
+    throw new Exception('Illegal enum value: $name');
+  }
+
+  factory CompletionService.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json is String) {
+      try {
+        return new CompletionService(json);
+      } catch (_) {
+        // Fall through
+      }
+    }
+    throw jsonDecoder.mismatch(jsonPath, "CompletionService", json);
+  }
+
+  @override
+  String toString() => "CompletionService.$name";
+
+  String toJson() => name;
+}
+
+/**
+ * completion.setSubscriptions params
+ *
+ * {
+ *   "subscriptions": List<CompletionService>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionSetSubscriptionsParams implements RequestParams {
+  List<CompletionService> _subscriptions;
+
+  /**
+   * A list of the services being subscribed to.
+   */
+  List<CompletionService> get subscriptions => _subscriptions;
+
+  /**
+   * A list of the services being subscribed to.
+   */
+  void set subscriptions(List<CompletionService> value) {
+    assert(value != null);
+    this._subscriptions = value;
+  }
+
+  CompletionSetSubscriptionsParams(List<CompletionService> subscriptions) {
+    this.subscriptions = subscriptions;
+  }
+
+  factory CompletionSetSubscriptionsParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<CompletionService> subscriptions;
+      if (json.containsKey("subscriptions")) {
+        subscriptions = jsonDecoder.decodeList(
+            jsonPath + ".subscriptions",
+            json["subscriptions"],
+            (String jsonPath, Object json) =>
+                new CompletionService.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "subscriptions");
+      }
+      return new CompletionSetSubscriptionsParams(subscriptions);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "completion.setSubscriptions params", json);
+    }
+  }
+
+  factory CompletionSetSubscriptionsParams.fromRequest(Request request) {
+    return new CompletionSetSubscriptionsParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["subscriptions"] =
+        subscriptions.map((CompletionService value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "completion.setSubscriptions", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionSetSubscriptionsParams) {
+      return listEqual(subscriptions, other.subscriptions,
+          (CompletionService a, CompletionService b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, subscriptions.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * completion.setSubscriptions result
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class CompletionSetSubscriptionsResult implements ResponseResult {
+  @override
+  Map<String, dynamic> toJson() => <String, dynamic>{};
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: null);
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is CompletionSetSubscriptionsResult) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    return 2482770;
+  }
+}
+
+/**
  * ContextData
  *
  * {
@@ -5877,6 +7144,132 @@
 }
 
 /**
+ * DartFix
+ *
+ * {
+ *   "name": String
+ *   "description": optional String
+ *   "isRequired": optional bool
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class DartFix implements HasToJson {
+  String _name;
+
+  String _description;
+
+  bool _isRequired;
+
+  /**
+   * The name of the fix.
+   */
+  String get name => _name;
+
+  /**
+   * The name of the fix.
+   */
+  void set name(String value) {
+    assert(value != null);
+    this._name = value;
+  }
+
+  /**
+   * A human readable description of the fix.
+   */
+  String get description => _description;
+
+  /**
+   * A human readable description of the fix.
+   */
+  void set description(String value) {
+    this._description = value;
+  }
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  bool get isRequired => _isRequired;
+
+  /**
+   * `true` if the fix is in the "required" fixes group.
+   */
+  void set isRequired(bool value) {
+    this._isRequired = value;
+  }
+
+  DartFix(String name, {String description, bool isRequired}) {
+    this.name = name;
+    this.description = description;
+    this.isRequired = isRequired;
+  }
+
+  factory DartFix.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String name;
+      if (json.containsKey("name")) {
+        name = jsonDecoder.decodeString(jsonPath + ".name", json["name"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "name");
+      }
+      String description;
+      if (json.containsKey("description")) {
+        description = jsonDecoder.decodeString(
+            jsonPath + ".description", json["description"]);
+      }
+      bool isRequired;
+      if (json.containsKey("isRequired")) {
+        isRequired = jsonDecoder.decodeBool(
+            jsonPath + ".isRequired", json["isRequired"]);
+      }
+      return new DartFix(name,
+          description: description, isRequired: isRequired);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "DartFix", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["name"] = name;
+    if (description != null) {
+      result["description"] = description;
+    }
+    if (isRequired != null) {
+      result["isRequired"] = isRequired;
+    }
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is DartFix) {
+      return name == other.name &&
+          description == other.description &&
+          isRequired == other.isRequired;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, name.hashCode);
+    hash = JenkinsSmiHash.combine(hash, description.hashCode);
+    hash = JenkinsSmiHash.combine(hash, isRequired.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * DartFixSuggestion
  *
  * {
@@ -6214,6 +7607,9 @@
  *
  * {
  *   "included": List<FilePath>
+ *   "includedFixes": optional List<String>
+ *   "includeRequiredFixes": optional bool
+ *   "excludedFixes": optional List<String>
  * }
  *
  * Clients may not extend, implement or mix-in this class.
@@ -6221,6 +7617,12 @@
 class EditDartfixParams implements RequestParams {
   List<String> _included;
 
+  List<String> _includedFixes;
+
+  bool _includeRequiredFixes;
+
+  List<String> _excludedFixes;
+
   /**
    * A list of the files and directories for which edits should be suggested.
    *
@@ -6248,8 +7650,62 @@
     this._included = value;
   }
 
-  EditDartfixParams(List<String> included) {
+  /**
+   * A list of names indicating which fixes should be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  List<String> get includedFixes => _includedFixes;
+
+  /**
+   * A list of names indicating which fixes should be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  void set includedFixes(List<String> value) {
+    this._includedFixes = value;
+  }
+
+  /**
+   * A flag indicating that "required" fixes should be applied.
+   */
+  bool get includeRequiredFixes => _includeRequiredFixes;
+
+  /**
+   * A flag indicating that "required" fixes should be applied.
+   */
+  void set includeRequiredFixes(bool value) {
+    this._includeRequiredFixes = value;
+  }
+
+  /**
+   * A list of names indicating which fixes should not be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  List<String> get excludedFixes => _excludedFixes;
+
+  /**
+   * A list of names indicating which fixes should not be applied.
+   *
+   * If a name is specified that does not match the name of a known fix, an
+   * error of type UNKNOWN_FIX will be generated.
+   */
+  void set excludedFixes(List<String> value) {
+    this._excludedFixes = value;
+  }
+
+  EditDartfixParams(List<String> included,
+      {List<String> includedFixes,
+      bool includeRequiredFixes,
+      List<String> excludedFixes}) {
     this.included = included;
+    this.includedFixes = includedFixes;
+    this.includeRequiredFixes = includeRequiredFixes;
+    this.excludedFixes = excludedFixes;
   }
 
   factory EditDartfixParams.fromJson(
@@ -6265,7 +7721,25 @@
       } else {
         throw jsonDecoder.mismatch(jsonPath, "included");
       }
-      return new EditDartfixParams(included);
+      List<String> includedFixes;
+      if (json.containsKey("includedFixes")) {
+        includedFixes = jsonDecoder.decodeList(jsonPath + ".includedFixes",
+            json["includedFixes"], jsonDecoder.decodeString);
+      }
+      bool includeRequiredFixes;
+      if (json.containsKey("includeRequiredFixes")) {
+        includeRequiredFixes = jsonDecoder.decodeBool(
+            jsonPath + ".includeRequiredFixes", json["includeRequiredFixes"]);
+      }
+      List<String> excludedFixes;
+      if (json.containsKey("excludedFixes")) {
+        excludedFixes = jsonDecoder.decodeList(jsonPath + ".excludedFixes",
+            json["excludedFixes"], jsonDecoder.decodeString);
+      }
+      return new EditDartfixParams(included,
+          includedFixes: includedFixes,
+          includeRequiredFixes: includeRequiredFixes,
+          excludedFixes: excludedFixes);
     } else {
       throw jsonDecoder.mismatch(jsonPath, "edit.dartfix params", json);
     }
@@ -6280,6 +7754,15 @@
   Map<String, dynamic> toJson() {
     Map<String, dynamic> result = {};
     result["included"] = included;
+    if (includedFixes != null) {
+      result["includedFixes"] = includedFixes;
+    }
+    if (includeRequiredFixes != null) {
+      result["includeRequiredFixes"] = includeRequiredFixes;
+    }
+    if (excludedFixes != null) {
+      result["excludedFixes"] = excludedFixes;
+    }
     return result;
   }
 
@@ -6295,7 +7778,12 @@
   bool operator ==(other) {
     if (other is EditDartfixParams) {
       return listEqual(
-          included, other.included, (String a, String b) => a == b);
+              included, other.included, (String a, String b) => a == b) &&
+          listEqual(includedFixes, other.includedFixes,
+              (String a, String b) => a == b) &&
+          includeRequiredFixes == other.includeRequiredFixes &&
+          listEqual(excludedFixes, other.excludedFixes,
+              (String a, String b) => a == b);
     }
     return false;
   }
@@ -6304,6 +7792,9 @@
   int get hashCode {
     int hash = 0;
     hash = JenkinsSmiHash.combine(hash, included.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includedFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, includeRequiredFixes.hashCode);
+    hash = JenkinsSmiHash.combine(hash, excludedFixes.hashCode);
     return JenkinsSmiHash.finish(hash);
   }
 }
@@ -7267,6 +8758,152 @@
 }
 
 /**
+ * edit.getDartfixInfo params
+ *
+ * {
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class EditGetDartfixInfoParams implements RequestParams {
+  EditGetDartfixInfoParams();
+
+  factory EditGetDartfixInfoParams.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      return new EditGetDartfixInfoParams();
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.getDartfixInfo params", json);
+    }
+  }
+
+  factory EditGetDartfixInfoParams.fromRequest(Request request) {
+    return new EditGetDartfixInfoParams.fromJson(
+        new RequestDecoder(request), "params", request.params);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    return result;
+  }
+
+  @override
+  Request toRequest(String id) {
+    return new Request(id, "edit.getDartfixInfo", toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is EditGetDartfixInfoParams) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * edit.getDartfixInfo result
+ *
+ * {
+ *   "fixes": List<DartFix>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class EditGetDartfixInfoResult implements ResponseResult {
+  List<DartFix> _fixes;
+
+  /**
+   * A list of fixes that can be specified in an edit.dartfix request.
+   */
+  List<DartFix> get fixes => _fixes;
+
+  /**
+   * A list of fixes that can be specified in an edit.dartfix request.
+   */
+  void set fixes(List<DartFix> value) {
+    assert(value != null);
+    this._fixes = value;
+  }
+
+  EditGetDartfixInfoResult(List<DartFix> fixes) {
+    this.fixes = fixes;
+  }
+
+  factory EditGetDartfixInfoResult.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      List<DartFix> fixes;
+      if (json.containsKey("fixes")) {
+        fixes = jsonDecoder.decodeList(
+            jsonPath + ".fixes",
+            json["fixes"],
+            (String jsonPath, Object json) =>
+                new DartFix.fromJson(jsonDecoder, jsonPath, json));
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "fixes");
+      }
+      return new EditGetDartfixInfoResult(fixes);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "edit.getDartfixInfo result", json);
+    }
+  }
+
+  factory EditGetDartfixInfoResult.fromResponse(Response response) {
+    return new EditGetDartfixInfoResult.fromJson(
+        new ResponseDecoder(REQUEST_ID_REFACTORING_KINDS.remove(response.id)),
+        "result",
+        response.result);
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["fixes"] = fixes.map((DartFix value) => value.toJson()).toList();
+    return result;
+  }
+
+  @override
+  Response toResponse(String id) {
+    return new Response(id, result: toJson());
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is EditGetDartfixInfoResult) {
+      return listEqual(fixes, other.fixes, (DartFix a, DartFix b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, fixes.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * edit.getFixes params
  *
  * {
@@ -14330,6 +15967,213 @@
 }
 
 /**
+ * IncludedSuggestionRelevanceTag
+ *
+ * {
+ *   "tag": AvailableSuggestionRelevanceTag
+ *   "relevanceBoost": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class IncludedSuggestionRelevanceTag implements HasToJson {
+  String _tag;
+
+  int _relevanceBoost;
+
+  /**
+   * The opaque value of the tag.
+   */
+  String get tag => _tag;
+
+  /**
+   * The opaque value of the tag.
+   */
+  void set tag(String value) {
+    assert(value != null);
+    this._tag = value;
+  }
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this
+   * tag, which is added to the relevance of the containing
+   * IncludedSuggestionSet.
+   */
+  int get relevanceBoost => _relevanceBoost;
+
+  /**
+   * The boost to the relevance of the completion suggestions that match this
+   * tag, which is added to the relevance of the containing
+   * IncludedSuggestionSet.
+   */
+  void set relevanceBoost(int value) {
+    assert(value != null);
+    this._relevanceBoost = value;
+  }
+
+  IncludedSuggestionRelevanceTag(String tag, int relevanceBoost) {
+    this.tag = tag;
+    this.relevanceBoost = relevanceBoost;
+  }
+
+  factory IncludedSuggestionRelevanceTag.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String tag;
+      if (json.containsKey("tag")) {
+        tag = jsonDecoder.decodeString(jsonPath + ".tag", json["tag"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "tag");
+      }
+      int relevanceBoost;
+      if (json.containsKey("relevanceBoost")) {
+        relevanceBoost = jsonDecoder.decodeInt(
+            jsonPath + ".relevanceBoost", json["relevanceBoost"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "relevanceBoost");
+      }
+      return new IncludedSuggestionRelevanceTag(tag, relevanceBoost);
+    } else {
+      throw jsonDecoder.mismatch(
+          jsonPath, "IncludedSuggestionRelevanceTag", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["tag"] = tag;
+    result["relevanceBoost"] = relevanceBoost;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is IncludedSuggestionRelevanceTag) {
+      return tag == other.tag && relevanceBoost == other.relevanceBoost;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, tag.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevanceBoost.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
+ * IncludedSuggestionSet
+ *
+ * {
+ *   "id": int
+ *   "relevance": int
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class IncludedSuggestionSet implements HasToJson {
+  int _id;
+
+  int _relevance;
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be
+   * displayed to the user.
+   */
+  int get id => _id;
+
+  /**
+   * Clients should use it to access the set of precomputed completions to be
+   * displayed to the user.
+   */
+  void set id(int value) {
+    assert(value != null);
+    this._id = value;
+  }
+
+  /**
+   * The relevance of completion suggestions from this library where a higher
+   * number indicates a higher relevance.
+   */
+  int get relevance => _relevance;
+
+  /**
+   * The relevance of completion suggestions from this library where a higher
+   * number indicates a higher relevance.
+   */
+  void set relevance(int value) {
+    assert(value != null);
+    this._relevance = value;
+  }
+
+  IncludedSuggestionSet(int id, int relevance) {
+    this.id = id;
+    this.relevance = relevance;
+  }
+
+  factory IncludedSuggestionSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      int id;
+      if (json.containsKey("id")) {
+        id = jsonDecoder.decodeInt(jsonPath + ".id", json["id"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "id");
+      }
+      int relevance;
+      if (json.containsKey("relevance")) {
+        relevance =
+            jsonDecoder.decodeInt(jsonPath + ".relevance", json["relevance"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "relevance");
+      }
+      return new IncludedSuggestionSet(id, relevance);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "IncludedSuggestionSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["id"] = id;
+    result["relevance"] = relevance;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is IncludedSuggestionSet) {
+      return id == other.id && relevance == other.relevance;
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, id.hashCode);
+    hash = JenkinsSmiHash.combine(hash, relevance.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * inlineLocalVariable feedback
  *
  * {
@@ -14905,6 +16749,113 @@
 }
 
 /**
+ * LibraryPathSet
+ *
+ * {
+ *   "scope": FilePath
+ *   "libraryPaths": List<FilePath>
+ * }
+ *
+ * Clients may not extend, implement or mix-in this class.
+ */
+class LibraryPathSet implements HasToJson {
+  String _scope;
+
+  List<String> _libraryPaths;
+
+  /**
+   * The filepath for which this request's libraries should be active in
+   * completion suggestions. This object associates filesystem regions to
+   * libraries and library directories of interest to the client.
+   */
+  String get scope => _scope;
+
+  /**
+   * The filepath for which this request's libraries should be active in
+   * completion suggestions. This object associates filesystem regions to
+   * libraries and library directories of interest to the client.
+   */
+  void set scope(String value) {
+    assert(value != null);
+    this._scope = value;
+  }
+
+  /**
+   * The paths of the libraries of interest to the client for completion
+   * suggestions.
+   */
+  List<String> get libraryPaths => _libraryPaths;
+
+  /**
+   * The paths of the libraries of interest to the client for completion
+   * suggestions.
+   */
+  void set libraryPaths(List<String> value) {
+    assert(value != null);
+    this._libraryPaths = value;
+  }
+
+  LibraryPathSet(String scope, List<String> libraryPaths) {
+    this.scope = scope;
+    this.libraryPaths = libraryPaths;
+  }
+
+  factory LibraryPathSet.fromJson(
+      JsonDecoder jsonDecoder, String jsonPath, Object json) {
+    if (json == null) {
+      json = {};
+    }
+    if (json is Map) {
+      String scope;
+      if (json.containsKey("scope")) {
+        scope = jsonDecoder.decodeString(jsonPath + ".scope", json["scope"]);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "scope");
+      }
+      List<String> libraryPaths;
+      if (json.containsKey("libraryPaths")) {
+        libraryPaths = jsonDecoder.decodeList(jsonPath + ".libraryPaths",
+            json["libraryPaths"], jsonDecoder.decodeString);
+      } else {
+        throw jsonDecoder.mismatch(jsonPath, "libraryPaths");
+      }
+      return new LibraryPathSet(scope, libraryPaths);
+    } else {
+      throw jsonDecoder.mismatch(jsonPath, "LibraryPathSet", json);
+    }
+  }
+
+  @override
+  Map<String, dynamic> toJson() {
+    Map<String, dynamic> result = {};
+    result["scope"] = scope;
+    result["libraryPaths"] = libraryPaths;
+    return result;
+  }
+
+  @override
+  String toString() => json.encode(toJson());
+
+  @override
+  bool operator ==(other) {
+    if (other is LibraryPathSet) {
+      return scope == other.scope &&
+          listEqual(
+              libraryPaths, other.libraryPaths, (String a, String b) => a == b);
+    }
+    return false;
+  }
+
+  @override
+  int get hashCode {
+    int hash = 0;
+    hash = JenkinsSmiHash.combine(hash, scope.hashCode);
+    hash = JenkinsSmiHash.combine(hash, libraryPaths.hashCode);
+    return JenkinsSmiHash.finish(hash);
+  }
+}
+
+/**
  * moveFile feedback
  *
  * Clients may not extend, implement or mix-in this class.
@@ -15953,6 +17904,7 @@
  *   SERVER_ERROR
  *   SORT_MEMBERS_INVALID_FILE
  *   SORT_MEMBERS_PARSE_ERRORS
+ *   UNKNOWN_FIX
  *   UNKNOWN_REQUEST
  *   UNSUPPORTED_FEATURE
  * }
@@ -16143,6 +18095,13 @@
       const RequestErrorCode._("SORT_MEMBERS_PARSE_ERRORS");
 
   /**
+   * A dartfix request was received containing the name of a fix which does not
+   * match the name of any known fixes.
+   */
+  static const RequestErrorCode UNKNOWN_FIX =
+      const RequestErrorCode._("UNKNOWN_FIX");
+
+  /**
    * A request was received which the analysis server does not recognize, or
    * cannot handle in its current configuration.
    */
@@ -16189,6 +18148,7 @@
     SERVER_ERROR,
     SORT_MEMBERS_INVALID_FILE,
     SORT_MEMBERS_PARSE_ERRORS,
+    UNKNOWN_FIX,
     UNKNOWN_REQUEST,
     UNSUPPORTED_FEATURE
   ];
@@ -16252,6 +18212,8 @@
         return SORT_MEMBERS_INVALID_FILE;
       case "SORT_MEMBERS_PARSE_ERRORS":
         return SORT_MEMBERS_PARSE_ERRORS;
+      case "UNKNOWN_FIX":
+        return UNKNOWN_FIX;
       case "UNKNOWN_REQUEST":
         return UNKNOWN_REQUEST;
       case "UNSUPPORTED_FEATURE":
diff --git a/pkg/analysis_server_client/pubspec.yaml b/pkg/analysis_server_client/pubspec.yaml
index 9632e84..fc2de5b 100644
--- a/pkg/analysis_server_client/pubspec.yaml
+++ b/pkg/analysis_server_client/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analysis_server_client
-version: 1.1.1
+version: 1.1.2
 author: Dart Team <misc@dartlang.org>
 description:
   A client wrapper over analysis_server.
diff --git a/pkg/analysis_tool/README.md b/pkg/analysis_tool/README.md
new file mode 100644
index 0000000..c94b407
--- /dev/null
+++ b/pkg/analysis_tool/README.md
@@ -0,0 +1,3 @@
+A set of utilities used by the tools in several analyzer-related packages.
+
+Not meant to be published.
diff --git a/pkg/analyzer/lib/src/codegen/html.dart b/pkg/analysis_tool/lib/html.dart
similarity index 100%
rename from pkg/analyzer/lib/src/codegen/html.dart
rename to pkg/analysis_tool/lib/html.dart
diff --git a/pkg/analyzer/lib/src/codegen/text_formatter.dart b/pkg/analysis_tool/lib/text_formatter.dart
similarity index 98%
rename from pkg/analyzer/lib/src/codegen/text_formatter.dart
rename to pkg/analysis_tool/lib/text_formatter.dart
index 0ffad91..2305910 100644
--- a/pkg/analyzer/lib/src/codegen/text_formatter.dart
+++ b/pkg/analysis_tool/lib/text_formatter.dart
@@ -6,7 +6,8 @@
  * Code for converting HTML into text, for use during code generation of
  * analyzer and analysis server.
  */
-import 'package:analyzer/src/codegen/tools.dart';
+
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 
 final RegExp whitespace = new RegExp(r'\s');
diff --git a/pkg/analyzer/lib/src/codegen/tools.dart b/pkg/analysis_tool/lib/tools.dart
similarity index 99%
rename from pkg/analyzer/lib/src/codegen/tools.dart
rename to pkg/analysis_tool/lib/tools.dart
index 8b4e96d..0e35b61 100644
--- a/pkg/analyzer/lib/src/codegen/tools.dart
+++ b/pkg/analysis_tool/lib/tools.dart
@@ -8,8 +8,8 @@
 import 'dart:async';
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/html.dart';
-import 'package:analyzer/src/codegen/text_formatter.dart';
+import 'package:analysis_tool/html.dart';
+import 'package:analysis_tool/text_formatter.dart';
 import 'package:html/dom.dart' as dom;
 import 'package:path/path.dart';
 
diff --git a/pkg/analysis_tool/pubspec.yaml b/pkg/analysis_tool/pubspec.yaml
new file mode 100644
index 0000000..57ab3ee
--- /dev/null
+++ b/pkg/analysis_tool/pubspec.yaml
@@ -0,0 +1,9 @@
+name: analysis_tool
+publish_to: none
+
+environment:
+  sdk: '>=2.1.0 <3.0.0'
+
+dependencies:
+  html: any
+  path: any
diff --git a/pkg/analyzer/CHANGELOG.md b/pkg/analyzer/CHANGELOG.md
index f7ff184..591419d 100644
--- a/pkg/analyzer/CHANGELOG.md
+++ b/pkg/analyzer/CHANGELOG.md
@@ -1,3 +1,18 @@
+## 0.35.1
+* The new "set literals" language feature is now enabled by default.
+* The dev_dependency analysis_tool was created so that clients do not have to
+  depend on code that is used internally in the analyzer at development time.
+* The `InheritanceManager` class is now deprecated.  The new
+  `InheritanceManager2` class now supports accessing inherited interface/class
+  maps.
+* Added quick assists to support set literals.
+* Added the ability for linter tests to drive the analyzer using custom analysis
+  options.
+* Updated support in the AST structure for the control_flow_collections and
+  spread_collections experiments.  The new AST structures are still in
+  development.
+* Bug fixes: #34437, #35127, #35141, #35306, #35621.
+
 ## 0.35.0
 * Added support in the AST structure for the control_flow_collections and
   spread_collections experiments. This includes adding new visitor methods to
@@ -9,6 +24,19 @@
 * Disabled support for the task model.  Please use the new `AnalysisSession`
   API.
 * Removed `StrongTypeSystemImpl`.  Please use `Dart2TypeSystem` instead.
+* Made ERROR the default severity for StaticWarningCode.  We no longer need to
+  promote warnings to errors in "strong mode" because strong mode is the only
+  mode.
+* Added exact type analysis for set literals (#35742).
+* Bug fixes: #35305, #35750.
+
+## 0.34.3
+* Non-breaking AST changes in support for the control_flow_collections and
+  spread_collections experiments.  Clients who wish to begin adding support for
+  these experiments can depend on this release of the analyzer and begin writing
+  visit methods.  The visit methods won't be added to the AstVisitor base class
+  until 0.35.0.
+* Bug fixes: #35551, #35708, #35723.
 
 ## 0.34.2
 * Removed support for the `@checked` annotation.  Please use the `covariant`
diff --git a/pkg/analyzer/README.md b/pkg/analyzer/README.md
index d633684..f2f9b6a 100644
--- a/pkg/analyzer/README.md
+++ b/pkg/analyzer/README.md
@@ -64,6 +64,9 @@
     - camel_case_types
 ```
 
+For more information, see the docs for
+[customizing static analysis][custom_analysis].
+
 ## Who uses this library?
 
 Many tools embed this library, such as:
@@ -104,3 +107,4 @@
 [dartfmt]: https://github.com/dart-lang/dart_style
 [dartdoc]: https://github.com/dart-lang/dartdoc
 [analysis_sever]: https://github.com/dart-lang/sdk/tree/master/pkg/analysis_server
+[custom_analysis]: https://www.dartlang.org/guides/language/analysis-options
diff --git a/pkg/analyzer/lib/dart/ast/ast.dart b/pkg/analyzer/lib/dart/ast/ast.dart
index 1094872..3bf434e 100644
--- a/pkg/analyzer/lib/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/dart/ast/ast.dart
@@ -2,38 +2,36 @@
 // for 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 AST model. The AST (Abstract Syntax Tree) model describes the
- * syntactic (as opposed to semantic) structure of Dart code. The semantic
- * structure of the code is modeled by the
- * [element model](../dart_element_element/dart_element_element-library.html).
- *
- * An AST consists of nodes (instances of a subclass of [AstNode]). The nodes
- * are organized in a tree structure in which the children of a node are the
- * smaller syntactic units from which the node is composed. For example, a
- * binary expression consists of two sub-expressions (the operands) and an
- * operator. The two expressions are represented as nodes. The operator is not
- * represented as a node.
- *
- * The AST is constructed by the parser based on the sequence of tokens produced
- * by the scanner. Most nodes provide direct access to the tokens used to build
- * the node. For example, the token for the operator in a binary expression can
- * be accessed from the node representing the binary expression.
- *
- * While any node can theoretically be the root of an AST structure, almost all
- * of the AST structures known to the analyzer have a [CompilationUnit] as the
- * root of the structure. A compilation unit represents all of the Dart code in
- * a single file.
- *
- * An AST can be either unresolved or resolved. When an AST is unresolved
- * certain properties will not have been computed and the accessors for those
- * properties will return `null`. The documentation for those getters should
- * describe that this is a possibility.
- *
- * When an AST is resolved, the identifiers in the AST will be associated with
- * the elements that they refer to and every expression in the AST will have a
- * type associated with it.
- */
+/// Defines the AST model. The AST (Abstract Syntax Tree) model describes the
+/// syntactic (as opposed to semantic) structure of Dart code. The semantic
+/// structure of the code is modeled by the
+/// [element model](../dart_element_element/dart_element_element-library.html).
+///
+/// An AST consists of nodes (instances of a subclass of [AstNode]). The nodes
+/// are organized in a tree structure in which the children of a node are the
+/// smaller syntactic units from which the node is composed. For example, a
+/// binary expression consists of two sub-expressions (the operands) and an
+/// operator. The two expressions are represented as nodes. The operator is not
+/// represented as a node.
+///
+/// The AST is constructed by the parser based on the sequence of tokens
+/// produced by the scanner. Most nodes provide direct access to the tokens used
+/// to build the node. For example, the token for the operator in a binary
+/// expression can be accessed from the node representing the binary expression.
+///
+/// While any node can theoretically be the root of an AST structure, almost all
+/// of the AST structures known to the analyzer have a [CompilationUnit] as the
+/// root of the structure. A compilation unit represents all of the Dart code in
+/// a single file.
+///
+/// An AST can be either unresolved or resolved. When an AST is unresolved
+/// certain properties will not have been computed and the accessors for those
+/// properties will return `null`. The documentation for those getters should
+/// describe that this is a possibility.
+///
+/// When an AST is resolved, the identifiers in the AST will be associated with
+/// the elements that they refer to and every expression in the AST will have a
+/// type associated with it.
 import 'package:analyzer/dart/ast/syntactic_entity.dart';
 import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -43,449 +41,313 @@
 import 'package:analyzer/src/generated/source.dart' show LineInfo, Source;
 import 'package:analyzer/src/generated/utilities_dart.dart';
 
-/**
- * Two or more string literals that are implicitly concatenated because of being
- * adjacent (separated only by whitespace).
- *
- * While the grammar only allows adjacent strings when all of the strings are of
- * the same kind (single line or multi-line), this class doesn't enforce that
- * restriction.
- *
- *    adjacentStrings ::=
- *        [StringLiteral] [StringLiteral]+
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AdjacentStrings extends StringLiteral {
-  /**
-   * Return the strings that are implicitly concatenated.
-   */
+/// Two or more string literals that are implicitly concatenated because of
+/// being adjacent (separated only by whitespace).
+///
+/// While the grammar only allows adjacent strings when all of the strings are
+/// of the same kind (single line or multi-line), this class doesn't enforce
+/// that restriction.
+///
+///    adjacentStrings ::=
+///        [StringLiteral] [StringLiteral]+
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AdjacentStrings implements StringLiteral {
+  /// Return the strings that are implicitly concatenated.
   NodeList<StringLiteral> get strings;
 }
 
-/**
- * An AST node that can be annotated with both a documentation comment and a
- * list of annotations.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AnnotatedNode extends AstNode {
-  /**
-   * Return the documentation comment associated with this node, or `null` if
-   * this node does not have a documentation comment associated with it.
-   */
+/// An AST node that can be annotated with both a documentation comment and a
+/// list of annotations.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AnnotatedNode implements AstNode {
+  /// Return the documentation comment associated with this node, or `null` if
+  /// this node does not have a documentation comment associated with it.
   Comment get documentationComment;
 
-  /**
-   * Set the documentation comment associated with this node to the given
-   * [comment].
-   */
+  /// Set the documentation comment associated with this node to the given
+  /// [comment].
   void set documentationComment(Comment comment);
 
-  /**
-   * Return the first token following the comment and metadata.
-   */
+  /// Return the first token following the comment and metadata.
   Token get firstTokenAfterCommentAndMetadata;
 
-  /**
-   * Return the annotations associated with this node.
-   */
+  /// Return the annotations associated with this node.
   NodeList<Annotation> get metadata;
 
-  /**
-   * Return a list containing the comment and annotations associated with this
-   * node, sorted in lexical order.
-   */
+  /// Return a list containing the comment and annotations associated with this
+  /// node, sorted in lexical order.
   List<AstNode> get sortedCommentAndAnnotations;
 }
 
-/**
- * An annotation that can be associated with an AST node.
- *
- *    metadata ::=
- *        annotation*
- *
- *    annotation ::=
- *        '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Annotation extends AstNode {
-  /**
-   * Return the arguments to the constructor being invoked, or `null` if this
-   * annotation is not the invocation of a constructor.
-   */
+/// An annotation that can be associated with an AST node.
+///
+///    metadata ::=
+///        annotation*
+///
+///    annotation ::=
+///        '@' [Identifier] ('.' [SimpleIdentifier])? [ArgumentList]?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Annotation implements AstNode {
+  /// Return the arguments to the constructor being invoked, or `null` if this
+  /// annotation is not the invocation of a constructor.
   ArgumentList get arguments;
 
-  /**
-   * Set the arguments to the constructor being invoked to the given [arguments].
-   */
+  /// Set the arguments to the constructor being invoked to the given
+  /// [arguments].
   void set arguments(ArgumentList arguments);
 
-  /**
-   * Return the at sign that introduced the annotation.
-   */
+  /// Return the at sign that introduced the annotation.
   Token get atSign;
 
-  /**
-   * Set the at sign that introduced the annotation to the given [token].
-   */
+  /// Set the at sign that introduced the annotation to the given [token].
   void set atSign(Token token);
 
-  /**
-   * Return the name of the constructor being invoked, or `null` if this
-   * annotation is not the invocation of a named constructor.
-   */
+  /// Return the name of the constructor being invoked, or `null` if this
+  /// annotation is not the invocation of a named constructor.
   SimpleIdentifier get constructorName;
 
-  /**
-   * Set the name of the constructor being invoked to the given [name].
-   */
+  /// Set the name of the constructor being invoked to the given [name].
   void set constructorName(SimpleIdentifier name);
 
-  /**
-   * Return the element associated with this annotation, or `null` if the AST
-   * structure has not been resolved or if this annotation could not be
-   * resolved.
-   */
+  /// Return the element associated with this annotation, or `null` if the AST
+  /// structure has not been resolved or if this annotation could not be
+  /// resolved.
   Element get element;
 
-  /**
-   * Set the element associated with this annotation to the given [element].
-   */
+  /// Set the element associated with this annotation to the given [element].
   void set element(Element element);
 
-  /**
-   * Return the element annotation representing this annotation in the element model.
-   */
+  /// Return the element annotation representing this annotation in the element
+  /// model.
   ElementAnnotation get elementAnnotation;
 
-  /**
-   * Set the element annotation representing this annotation in the element
-   * model to the given [annotation].
-   */
+  /// Set the element annotation representing this annotation in the element
+  /// model to the given [annotation].
   void set elementAnnotation(ElementAnnotation annotation);
 
-  /**
-   * Return the name of the class defining the constructor that is being invoked
-   * or the name of the field that is being referenced.
-   */
+  /// Return the name of the class defining the constructor that is being
+  /// invoked or the name of the field that is being referenced.
   Identifier get name;
 
-  /**
-   * Set the name of the class defining the constructor that is being invoked or
-   * the name of the field that is being referenced to the given [name].
-   */
+  /// Set the name of the class defining the constructor that is being invoked
+  /// or the name of the field that is being referenced to the given [name].
   void set name(Identifier name);
 
-  /**
-   * Return the period before the constructor name, or `null` if this annotation
-   * is not the invocation of a named constructor.
-   */
+  /// Return the period before the constructor name, or `null` if this
+  /// annotation is not the invocation of a named constructor.
   Token get period;
 
-  /**
-   * Set the period before the constructor name to the given [token].
-   */
+  /// Set the period before the constructor name to the given [token].
   void set period(Token token);
 }
 
-/**
- * A list of arguments in the invocation of an executable element (that is, a
- * function, method, or constructor).
- *
- *    argumentList ::=
- *        '(' arguments? ')'
- *
- *    arguments ::=
- *        [NamedExpression] (',' [NamedExpression])*
- *      | [Expression] (',' [Expression])* (',' [NamedExpression])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ArgumentList extends AstNode {
-  /**
-   * Return the expressions producing the values of the arguments. Although the
-   * language requires that positional arguments appear before named arguments,
-   * this class allows them to be intermixed.
-   */
+/// A list of arguments in the invocation of an executable element (that is, a
+/// function, method, or constructor).
+///
+///    argumentList ::=
+///        '(' arguments? ')'
+///
+///    arguments ::=
+///        [NamedExpression] (',' [NamedExpression])*
+///      | [Expression] (',' [Expression])* (',' [NamedExpression])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ArgumentList implements AstNode {
+  /// Return the expressions producing the values of the arguments. Although the
+  /// language requires that positional arguments appear before named arguments,
+  /// this class allows them to be intermixed.
   NodeList<Expression> get arguments;
 
-  /**
-   * Set the parameter elements corresponding to each of the arguments in this
-   * list to the given list of [parameters]. The list of parameters must be the
-   * same length as the number of arguments, but can contain `null` entries if a
-   * given argument does not correspond to a formal parameter.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [correspondingStaticParameters] instead.
-   */
+  /// Set the parameter elements corresponding to each of the arguments in this
+  /// list to the given list of [parameters]. The list of parameters must be the
+  /// same length as the number of arguments, but can contain `null` entries if
+  /// a given argument does not correspond to a formal parameter.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [correspondingStaticParameters] instead.
   @deprecated
   void set correspondingPropagatedParameters(List<ParameterElement> parameters);
 
-  /**
-   * Set the parameter elements corresponding to each of the arguments in this
-   * list to the given list of [parameters]. The list of parameters must be the
-   * same length as the number of arguments, but can contain `null` entries if a
-   * given argument does not correspond to a formal parameter.
-   */
+  /// Set the parameter elements corresponding to each of the arguments in this
+  /// list to the given list of [parameters]. The list of parameters must be the
+  /// same length as the number of arguments, but can contain `null` entries if
+  /// a given argument does not correspond to a formal parameter.
   void set correspondingStaticParameters(List<ParameterElement> parameters);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 }
 
-/**
- * An as expression.
- *
- *    asExpression ::=
- *        [Expression] 'as' [TypeAnnotation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AsExpression extends Expression {
-  /**
-   * Return the 'as' operator.
-   */
+/// An as expression.
+///
+///    asExpression ::=
+///        [Expression] 'as' [TypeAnnotation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AsExpression implements Expression {
+  /// Return the 'as' operator.
   Token get asOperator;
 
-  /**
-   * Set the 'as' operator to the given [token].
-   */
+  /// Set the 'as' operator to the given [token].
   void set asOperator(Token token);
 
-  /**
-   * Return the expression used to compute the value being cast.
-   */
+  /// Return the expression used to compute the value being cast.
   Expression get expression;
 
-  /**
-   * Set the expression used to compute the value being cast to the given
-   * [expression].
-   */
+  /// Set the expression used to compute the value being cast to the given
+  /// [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the type being cast to.
-   */
+  /// Return the type being cast to.
   TypeAnnotation get type;
 
-  /**
-   * Set the type being cast to to the given [type].
-   */
+  /// Set the type being cast to to the given [type].
   void set type(TypeAnnotation type);
 }
 
-/**
- * An assert in the initializer list of a constructor.
- *
- *    assertInitializer ::=
- *        'assert' '(' [Expression] (',' [Expression])? ')'
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An assert in the initializer list of a constructor.
+///
+///    assertInitializer ::=
+///        'assert' '(' [Expression] (',' [Expression])? ')'
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class AssertInitializer implements Assertion, ConstructorInitializer {}
 
-/**
- * An assertion, either in a block or in the initializer list of a constructor.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An assertion, either in a block or in the initializer list of a constructor.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class Assertion implements AstNode {
-  /**
-   * Return the token representing the 'assert' keyword.
-   */
+  /// Return the token representing the 'assert' keyword.
   Token get assertKeyword;
 
-  /**
-   * Set the token representing the 'assert' keyword to the given [token].
-   */
+  /// Set the token representing the 'assert' keyword to the given [token].
   void set assertKeyword(Token token);
 
-  /**
-   * Return the comma between the [condition] and the [message], or `null` if no
-   * message was supplied.
-   */
+  /// Return the comma between the [condition] and the [message], or `null` if
+  /// no message was supplied.
   Token get comma;
 
-  /**
-   * Set the comma between the [condition] and the [message] to the given
-   * [token].
-   */
+  /// Set the comma between the [condition] and the [message] to the given
+  /// [token].
   void set comma(Token token);
 
-  /**
-   * Return the condition that is being asserted to be `true`.
-   */
+  /// Return the condition that is being asserted to be `true`.
   Expression get condition;
 
-  /**
-   * Set the condition that is being asserted to be `true` to the given
-   * [condition].
-   */
+  /// Set the condition that is being asserted to be `true` to the given
+  /// [condition].
   void set condition(Expression condition);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the message to report if the assertion fails, or `null` if no
-   * message was supplied.
-   */
+  /// Return the message to report if the assertion fails, or `null` if no
+  /// message was supplied.
   Expression get message;
 
-  /**
-   * Set the message to report if the assertion fails to the given
-   * [expression].
-   */
+  /// Set the message to report if the assertion fails to the given
+  /// [expression].
   void set message(Expression expression);
 
-  /**
-   *  Return the right parenthesis.
-   */
+  ///  Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   *  Set the right parenthesis to the given [token].
-   */
+  ///  Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 }
 
-/**
- * An assert statement.
- *
- *    assertStatement ::=
- *        'assert' '(' [Expression] (',' [Expression])? ')' ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An assert statement.
+///
+///    assertStatement ::=
+///        'assert' '(' [Expression] (',' [Expression])? ')' ';'
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class AssertStatement implements Assertion, Statement {
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * An assignment expression.
- *
- *    assignmentExpression ::=
- *        [Expression] operator [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AssignmentExpression extends Expression
-    implements MethodReferenceExpression {
-  /**
-   * Return the expression used to compute the left hand side.
-   */
+/// An assignment expression.
+///
+///    assignmentExpression ::=
+///        [Expression] operator [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AssignmentExpression
+    implements Expression, MethodReferenceExpression {
+  /// Return the expression used to compute the left hand side.
   Expression get leftHandSide;
 
-  /**
-   * Return the expression used to compute the left hand side.
-   */
+  /// Return the expression used to compute the left hand side.
   void set leftHandSide(Expression expression);
 
-  /**
-   * Return the assignment operator being applied.
-   */
+  /// Return the assignment operator being applied.
   Token get operator;
 
-  /**
-   * Set the assignment operator being applied to the given [token].
-   */
+  /// Set the assignment operator being applied to the given [token].
   void set operator(Token token);
 
-  /**
-   * Return the expression used to compute the right hand side.
-   */
+  /// Return the expression used to compute the right hand side.
   Expression get rightHandSide;
 
-  /**
-   * Set the expression used to compute the left hand side to the given
-   * [expression].
-   */
+  /// Set the expression used to compute the left hand side to the given
+  /// [expression].
   void set rightHandSide(Expression expression);
 }
 
-/**
- * A node in the AST structure for a Dart program.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// A node in the AST structure for a Dart program.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class AstNode implements SyntacticEntity {
-  /**
-   * A comparator that can be used to sort AST nodes in lexical order. In other
-   * words, `compare` will return a negative value if the offset of the first
-   * node is less than the offset of the second node, zero (0) if the nodes have
-   * the same offset, and a positive value if the offset of the first node is
-   * greater than the offset of the second node.
-   */
+  /// A comparator that can be used to sort AST nodes in lexical order. In other
+  /// words, `compare` will return a negative value if the offset of the first
+  /// node is less than the offset of the second node, zero (0) if the nodes
+  /// have the same offset, and a positive value if the offset of the first node
+  /// is greater than the offset of the second node.
   static Comparator<AstNode> LEXICAL_ORDER =
       (AstNode first, AstNode second) => first.offset - second.offset;
 
-  /**
-   * Return the first token included in this node's source range.
-   */
+  /// Return the first token included in this node's source range.
   Token get beginToken;
 
-  /**
-   * Return an iterator that can be used to iterate through all the entities
-   * (either AST nodes or tokens) that make up the contents of this node,
-   * including doc comments but excluding other comments.
-   */
+  /// Return an iterator that can be used to iterate through all the entities
+  /// (either AST nodes or tokens) that make up the contents of this node,
+  /// including doc comments but excluding other comments.
   Iterable<SyntacticEntity> get childEntities;
 
-  /**
-   * Return the offset of the character immediately following the last character
-   * of this node's source range. This is equivalent to
-   * `node.getOffset() + node.getLength()`. For a compilation unit this will be
-   * equal to the length of the unit's source. For synthetic nodes this will be
-   * equivalent to the node's offset (because the length is zero (0) by
-   * definition).
-   */
+  /// Return the offset of the character immediately following the last
+  /// character of this node's source range. This is equivalent to
+  /// `node.getOffset() + node.getLength()`. For a compilation unit this will be
+  /// equal to the length of the unit's source. For synthetic nodes this will be
+  /// equivalent to the node's offset (because the length is zero (0) by
+  /// definition).
   @override
   int get end;
 
-  /**
-   * Return the last token included in this node's source range.
-   */
+  /// Return the last token included in this node's source range.
   Token get endToken;
 
-  /**
-   * Return `true` if this node is a synthetic node. A synthetic node is a node
-   * that was introduced by the parser in order to recover from an error in the
-   * code. Synthetic nodes always have a length of zero (`0`).
-   */
+  /// Return `true` if this node is a synthetic node. A synthetic node is a node
+  /// that was introduced by the parser in order to recover from an error in the
+  /// code. Synthetic nodes always have a length of zero (`0`).
   bool get isSynthetic;
 
   @override
@@ -494,91 +356,68 @@
   @override
   int get offset;
 
-  /**
-   * Return this node's parent node, or `null` if this node is the root of an
-   * AST structure.
-   *
-   * Note that the relationship between an AST node and its parent node may
-   * change over the lifetime of a node.
-   */
+  /// Return this node's parent node, or `null` if this node is the root of an
+  /// AST structure.
+  ///
+  /// Note that the relationship between an AST node and its parent node may
+  /// change over the lifetime of a node.
   AstNode get parent;
 
-  /**
-   * Return the node at the root of this node's AST structure. Note that this
-   * method's performance is linear with respect to the depth of the node in the
-   * AST structure (O(depth)).
-   */
+  /// Return the node at the root of this node's AST structure. Note that this
+  /// method's performance is linear with respect to the depth of the node in
+  /// the AST structure (O(depth)).
   AstNode get root;
 
-  /**
-   * Use the given [visitor] to visit this node. Return the value returned by
-   * the visitor as a result of visiting this node.
-   */
+  /// Use the given [visitor] to visit this node. Return the value returned by
+  /// the visitor as a result of visiting this node.
   E accept<E>(AstVisitor<E> visitor);
 
-  /**
-   * Return the token before [target] or `null` if it cannot be found.
-   */
+  /// Return the token before [target] or `null` if it cannot be found.
   Token findPrevious(Token target);
 
-  /**
-   * Return the most immediate ancestor of this node for which the [predicate]
-   * returns `true`, or `null` if there is no such ancestor. Note that this node
-   * will never be returned.
-   */
+  /// Return the most immediate ancestor of this node for which the [predicate]
+  /// returns `true`, or `null` if there is no such ancestor. Note that this
+  /// node will never be returned.
   @deprecated
   E getAncestor<E extends AstNode>(Predicate<AstNode> predicate);
 
-  /**
-   * Return the value of the property with the given [name], or `null` if this
-   * node does not have a property with the given name.
-   */
+  /// Return the value of the property with the given [name], or `null` if this
+  /// node does not have a property with the given name.
   E getProperty<E>(String name);
 
-  /**
-   * Set the value of the property with the given [name] to the given [value].
-   * If the value is `null`, the property will effectively be removed.
-   */
+  /// Set the value of the property with the given [name] to the given [value].
+  /// If the value is `null`, the property will effectively be removed.
   void setProperty(String name, Object value);
 
-  /**
-   * Return either this node or the most immediate ancestor of this node for
-   * which the [predicate] returns `true`, or `null` if there is no such node.
-   */
+  /// Return either this node or the most immediate ancestor of this node for
+  /// which the [predicate] returns `true`, or `null` if there is no such node.
   E thisOrAncestorMatching<E extends AstNode>(Predicate<AstNode> predicate);
 
-  /**
-   * Return either this node or the most immediate ancestor of this node that
-   * has the given type, or `null` if there is no such node.
-   */
+  /// Return either this node or the most immediate ancestor of this node that
+  /// has the given type, or `null` if there is no such node.
   T thisOrAncestorOfType<T extends AstNode>();
 
-  /**
-   * Return a textual description of this node in a form approximating valid
-   * source. The returned string will not be valid source primarily in the case
-   * where the node itself is not well-formed.
-   */
+  /// Return a textual description of this node in a form approximating valid
+  /// source. The returned string will not be valid source primarily in the case
+  /// where the node itself is not well-formed.
   String toSource();
 
-  /**
-   * Use the given [visitor] to visit all of the children of this node. The
-   * children will be visited in lexical order.
-   */
+  /// Use the given [visitor] to visit all of the children of this node. The
+  /// children will be visited in lexical order.
   void visitChildren(AstVisitor visitor);
 }
 
-/**
- * An object that can be used to visit an AST structure.
- *
- * Clients may not extend, implement or mix-in this class. There are classes
- * that implement this interface that provide useful default behaviors in
- * `package:analyzer/dart/ast/visitor.dart`. A couple of the most useful include
- * * SimpleAstVisitor which implements every visit method by doing nothing,
- * * RecursiveAstVisitor which will cause every node in a structure to be
- *   visited, and
- * * ThrowingAstVisitor which implements every visit method by throwing an
- *   exception.
- */
+/// An object that can be used to visit an AST structure.
+///
+/// Clients may not extend, implement or mix-in this class. There are classes
+/// that implement this interface that provide useful default behaviors in
+/// `package:analyzer/dart/ast/visitor.dart`. A couple of the most useful
+/// include
+/// * SimpleAstVisitor which implements every visit method by doing nothing,
+/// * RecursiveAstVisitor which will cause every node in a structure to be
+///   visited, and
+/// * ThrowingAstVisitor which implements every visit method by throwing an
+///   exception.
 abstract class AstVisitor<R> {
   R visitAdjacentStrings(AdjacentStrings node);
 
@@ -614,10 +453,6 @@
 
   R visitClassTypeAlias(ClassTypeAlias node);
 
-  R visitCollectionForElement(CollectionForElement node);
-
-  R visitCollectionIfElement(CollectionIfElement node);
-
   R visitComment(Comment node);
 
   R visitCommentReference(CommentReference node);
@@ -672,6 +507,8 @@
 
   R visitForEachStatement(ForEachStatement node);
 
+  R visitForElement(ForElement node);
+
   R visitFormalParameterList(FormalParameterList node);
 
   R visitForPartsWithDeclarations(ForPartsWithDeclarations node);
@@ -700,6 +537,8 @@
 
   R visitHideCombinator(HideCombinator node);
 
+  R visitIfElement(IfElement node);
+
   R visitIfStatement(IfStatement node);
 
   R visitImplementsClause(ImplementsClause node);
@@ -730,10 +569,6 @@
 
   R visitListLiteral2(ListLiteral2 node);
 
-  R visitMapForElement(MapForElement node);
-
-  R visitMapIfElement(MapIfElement node);
-
   R visitMapLiteral(MapLiteral node);
 
   R visitMapLiteral2(MapLiteral2 node);
@@ -836,1107 +671,758 @@
   R visitYieldStatement(YieldStatement node);
 }
 
-/**
- * An await expression.
- *
- *    awaitExpression ::=
- *        'await' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class AwaitExpression extends Expression {
-  /**
-   * Return the 'await' keyword.
-   */
+/// An await expression.
+///
+///    awaitExpression ::=
+///        'await' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class AwaitExpression implements Expression {
+  /// Return the 'await' keyword.
   Token get awaitKeyword;
 
-  /**
-   * Set the 'await' keyword to the given [token].
-   */
+  /// Set the 'await' keyword to the given [token].
   void set awaitKeyword(Token token);
 
-  /**
-   * Return the expression whose value is being waited on.
-   */
+  /// Return the expression whose value is being waited on.
   Expression get expression;
 
-  /**
-   * Set the expression whose value is being waited on to the given [expression].
-   */
+  /// Set the expression whose value is being waited on to the given
+  /// [expression].
   void set expression(Expression expression);
 }
 
-/**
- * A binary (infix) expression.
- *
- *    binaryExpression ::=
- *        [Expression] [Token] [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class BinaryExpression extends Expression
-    implements MethodReferenceExpression {
-  /**
-   * Return the expression used to compute the left operand.
-   */
+/// A binary (infix) expression.
+///
+///    binaryExpression ::=
+///        [Expression] [Token] [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class BinaryExpression
+    implements Expression, MethodReferenceExpression {
+  /// Return the expression used to compute the left operand.
   Expression get leftOperand;
 
-  /**
-   * Set the expression used to compute the left operand to the given
-   * [expression].
-   */
+  /// Set the expression used to compute the left operand to the given
+  /// [expression].
   void set leftOperand(Expression expression);
 
-  /**
-   * Return the binary operator being applied.
-   */
+  /// Return the binary operator being applied.
   Token get operator;
 
-  /**
-   * Set the binary operator being applied to the given [token].
-   */
+  /// Set the binary operator being applied to the given [token].
   void set operator(Token token);
 
-  /**
-   * Return the expression used to compute the right operand.
-   */
+  /// Return the expression used to compute the right operand.
   Expression get rightOperand;
 
-  /**
-   * Set the expression used to compute the right operand to the given
-   * [expression].
-   */
+  /// Set the expression used to compute the right operand to the given
+  /// [expression].
   void set rightOperand(Expression expression);
 
-  /**
-   * The function type of the invocation, or `null` if the AST structure has
-   * not been resolved, or if the invocation could not be resolved.
-   */
+  /// The function type of the invocation, or `null` if the AST structure has
+  /// not been resolved, or if the invocation could not be resolved.
   FunctionType get staticInvokeType;
 
-  /**
-   * Sets the function type of the invocation.
-   */
+  /// Sets the function type of the invocation.
   void set staticInvokeType(FunctionType value);
 }
 
-/**
- * A sequence of statements.
- *
- *    block ::=
- *        '{' statement* '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Block extends Statement {
-  /**
-   * Return the left curly bracket.
-   */
+/// A sequence of statements.
+///
+///    block ::=
+///        '{' statement* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Block implements Statement {
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 
-  /**
-   * Return the statements contained in the block.
-   */
+  /// Return the statements contained in the block.
   NodeList<Statement> get statements;
 }
 
-/**
- * A function body that consists of a block of statements.
- *
- *    blockFunctionBody ::=
- *        ('async' | 'async' '*' | 'sync' '*')? [Block]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class BlockFunctionBody extends FunctionBody {
-  /**
-   * Return the block representing the body of the function.
-   */
+/// A function body that consists of a block of statements.
+///
+///    blockFunctionBody ::=
+///        ('async' | 'async' '*' | 'sync' '*')? [Block]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class BlockFunctionBody implements FunctionBody {
+  /// Return the block representing the body of the function.
   Block get block;
 
-  /**
-   * Set the block representing the body of the function to the given [block].
-   */
+  /// Set the block representing the body of the function to the given [block].
   void set block(Block block);
 
-  /**
-   * Set token representing the 'async' or 'sync' keyword to the given [token].
-   */
+  /// Set token representing the 'async' or 'sync' keyword to the given [token].
   void set keyword(Token token);
 
-  /**
-   * Set the star following the 'async' or 'sync' keyword to the given [token].
-   */
+  /// Set the star following the 'async' or 'sync' keyword to the given [token].
   void set star(Token token);
 }
 
-/**
- * A boolean literal expression.
- *
- *    booleanLiteral ::=
- *        'false' | 'true'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class BooleanLiteral extends Literal {
-  /**
-   * Return the token representing the literal.
-   */
+/// A boolean literal expression.
+///
+///    booleanLiteral ::=
+///        'false' | 'true'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class BooleanLiteral implements Literal {
+  /// Return the token representing the literal.
   Token get literal;
 
-  /**
-   * Set the token representing the literal to the given [token].
-   */
+  /// Set the token representing the literal to the given [token].
   void set literal(Token token);
 
-  /**
-   * Return the value of the literal.
-   */
+  /// Return the value of the literal.
   bool get value;
 }
 
-/**
- * A break statement.
- *
- *    breakStatement ::=
- *        'break' [SimpleIdentifier]? ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class BreakStatement extends Statement {
-  /**
-   * Return the token representing the 'break' keyword.
-   */
+/// A break statement.
+///
+///    breakStatement ::=
+///        'break' [SimpleIdentifier]? ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class BreakStatement implements Statement {
+  /// Return the token representing the 'break' keyword.
   Token get breakKeyword;
 
-  /**
-   * Set the token representing the 'break' keyword to the given [token].
-   */
+  /// Set the token representing the 'break' keyword to the given [token].
   void set breakKeyword(Token token);
 
-  /**
-   * Return the label associated with the statement, or `null` if there is no
-   * label.
-   */
+  /// Return the label associated with the statement, or `null` if there is no
+  /// label.
   SimpleIdentifier get label;
 
-  /**
-   * Set the label associated with the statement to the given [identifier].
-   */
+  /// Set the label associated with the statement to the given [identifier].
   void set label(SimpleIdentifier identifier);
 
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the node from which this break statement is breaking. This will be
-   * either a [Statement] (in the case of breaking out of a loop), a
-   * [SwitchMember] (in the case of a labeled break statement whose label
-   * matches a label on a switch case in an enclosing switch statement), or
-   * `null` if the AST has not yet been resolved or if the target could not be
-   * resolved. Note that if the source code has errors, the target might be
-   * invalid (e.g. trying to break to a switch case).
-   */
+  /// Return the node from which this break statement is breaking. This will be
+  /// either a [Statement] (in the case of breaking out of a loop), a
+  /// [SwitchMember] (in the case of a labeled break statement whose label
+  /// matches a label on a switch case in an enclosing switch statement), or
+  /// `null` if the AST has not yet been resolved or if the target could not be
+  /// resolved. Note that if the source code has errors, the target might be
+  /// invalid (e.g. trying to break to a switch case).
   AstNode get target;
 
-  /**
-   * Set the node from which this break statement is breaking to the given
-   * [node].
-   */
+  /// Set the node from which this break statement is breaking to the given
+  /// [node].
   void set target(AstNode node);
 }
 
-/**
- * A sequence of cascaded expressions: expressions that share a common target.
- * There are three kinds of expressions that can be used in a cascade
- * expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
- *
- *    cascadeExpression ::=
- *        [Expression] cascadeSection*
- *
- *    cascadeSection ::=
- *        '..'  (cascadeSelector arguments*) (assignableSelector arguments*)*
- *        (assignmentOperator expressionWithoutCascade)?
- *
- *    cascadeSelector ::=
- *        '[ ' expression '] '
- *      | identifier
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CascadeExpression extends Expression {
-  /**
-   * Return the cascade sections sharing the common target.
-   */
+/// A sequence of cascaded expressions: expressions that share a common target.
+/// There are three kinds of expressions that can be used in a cascade
+/// expression: [IndexExpression], [MethodInvocation] and [PropertyAccess].
+///
+///    cascadeExpression ::=
+///        [Expression] cascadeSection*
+///
+///    cascadeSection ::=
+///        '..'  (cascadeSelector arguments*) (assignableSelector arguments*)*
+///        (assignmentOperator expressionWithoutCascade)?
+///
+///    cascadeSelector ::=
+///        '[ ' expression '] '
+///      | identifier
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CascadeExpression implements Expression {
+  /// Return the cascade sections sharing the common target.
   NodeList<Expression> get cascadeSections;
 
-  /**
-   * Return the target of the cascade sections.
-   */
+  /// Return the target of the cascade sections.
   Expression get target;
 
-  /**
-   * Set the target of the cascade sections to the given [target].
-   */
+  /// Set the target of the cascade sections to the given [target].
   void set target(Expression target);
 }
 
-/**
- * A catch clause within a try statement.
- *
- *    onPart ::=
- *        catchPart [Block]
- *      | 'on' type catchPart? [Block]
- *
- *    catchPart ::=
- *        'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CatchClause extends AstNode {
-  /**
-   * Return the body of the catch block.
-   */
+/// A catch clause within a try statement.
+///
+///    onPart ::=
+///        catchPart [Block]
+///      | 'on' type catchPart? [Block]
+///
+///    catchPart ::=
+///        'catch' '(' [SimpleIdentifier] (',' [SimpleIdentifier])? ')'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CatchClause implements AstNode {
+  /// Return the body of the catch block.
   Block get body;
 
-  /**
-   * Set the body of the catch block to the given [block].
-   */
+  /// Set the body of the catch block to the given [block].
   void set body(Block block);
 
-  /**
-   * Return the token representing the 'catch' keyword, or `null` if there is no
-   * 'catch' keyword.
-   */
+  /// Return the token representing the 'catch' keyword, or `null` if there is
+  /// no 'catch' keyword.
   Token get catchKeyword;
 
-  /**
-   * Set the token representing the 'catch' keyword to the given [token].
-   */
+  /// Set the token representing the 'catch' keyword to the given [token].
   void set catchKeyword(Token token);
 
-  /**
-   * Return the comma separating the exception parameter from the stack trace
-   * parameter, or `null` if there is no stack trace parameter.
-   */
+  /// Return the comma separating the exception parameter from the stack trace
+  /// parameter, or `null` if there is no stack trace parameter.
   Token get comma;
 
-  /**
-   * Set the comma separating the exception parameter from the stack trace
-   * parameter to the given [token].
-   */
+  /// Set the comma separating the exception parameter from the stack trace
+  /// parameter to the given [token].
   void set comma(Token token);
 
-  /**
-   * Return the parameter whose value will be the exception that was thrown, or
-   * `null` if there is no 'catch' keyword.
-   */
+  /// Return the parameter whose value will be the exception that was thrown, or
+  /// `null` if there is no 'catch' keyword.
   SimpleIdentifier get exceptionParameter;
 
-  /**
-   * Set the parameter whose value will be the exception that was thrown to the
-   * given [parameter].
-   */
+  /// Set the parameter whose value will be the exception that was thrown to the
+  /// given [parameter].
   void set exceptionParameter(SimpleIdentifier parameter);
 
-  /**
-   * Return the type of exceptions caught by this catch clause, or `null` if
-   * this catch clause catches every type of exception.
-   */
+  /// Return the type of exceptions caught by this catch clause, or `null` if
+  /// this catch clause catches every type of exception.
   TypeAnnotation get exceptionType;
 
-  /**
-   * Set the type of exceptions caught by this catch clause to the given
-   * [exceptionType].
-   */
+  /// Set the type of exceptions caught by this catch clause to the given
+  /// [exceptionType].
   void set exceptionType(TypeAnnotation exceptionType);
 
-  /**
-   * Return the left parenthesis, or `null` if there is no 'catch' keyword.
-   */
+  /// Return the left parenthesis, or `null` if there is no 'catch' keyword.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the token representing the 'on' keyword, or `null` if there is no 'on'
-   * keyword.
-   */
+  /// Return the token representing the 'on' keyword, or `null` if there is no
+  /// 'on' keyword.
   Token get onKeyword;
 
-  /**
-   * Set the token representing the 'on' keyword to the given [token].
-   */
+  /// Set the token representing the 'on' keyword to the given [token].
   void set onKeyword(Token token);
 
-  /**
-   * Return the right parenthesis, or `null` if there is no 'catch' keyword.
-   */
+  /// Return the right parenthesis, or `null` if there is no 'catch' keyword.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the parameter whose value will be the stack trace associated with
-   * the exception, or `null` if there is no stack trace parameter.
-   */
+  /// Return the parameter whose value will be the stack trace associated with
+  /// the exception, or `null` if there is no stack trace parameter.
   SimpleIdentifier get stackTraceParameter;
 
-  /**
-   * Set the parameter whose value will be the stack trace associated with the
-   * exception to the given [parameter].
-   */
+  /// Set the parameter whose value will be the stack trace associated with the
+  /// exception to the given [parameter].
   void set stackTraceParameter(SimpleIdentifier parameter);
 }
 
-/**
- * The declaration of a class.
- *
- *    classDeclaration ::=
- *        'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
- *        ([ExtendsClause] [WithClause]?)?
- *        [ImplementsClause]?
- *        '{' [ClassMember]* '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ClassDeclaration extends ClassOrMixinDeclaration {
-  /**
-   * Return the 'abstract' keyword, or `null` if the keyword was absent.
-   */
+/// The declaration of a class.
+///
+///    classDeclaration ::=
+///        'abstract'? 'class' [SimpleIdentifier] [TypeParameterList]?
+///        ([ExtendsClause] [WithClause]?)?
+///        [ImplementsClause]?
+///        '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ClassDeclaration implements ClassOrMixinDeclaration {
+  /// Return the 'abstract' keyword, or `null` if the keyword was absent.
   Token get abstractKeyword;
 
-  /**
-   * Set the 'abstract' keyword to the given [token].
-   */
+  /// Set the 'abstract' keyword to the given [token].
   void set abstractKeyword(Token token);
 
-  /**
-   * Return the token representing the 'class' keyword.
-   */
+  /// Return the token representing the 'class' keyword.
   Token get classKeyword;
 
-  /**
-   * Set the token representing the 'class' keyword.
-   */
+  /// Set the token representing the 'class' keyword.
   void set classKeyword(Token token);
 
   @deprecated
   @override
   ClassElement get element;
 
-  /**
-   * Return the extends clause for this class, or `null` if the class does not
-   * extend any other class.
-   */
+  /// Return the extends clause for this class, or `null` if the class does not
+  /// extend any other class.
   ExtendsClause get extendsClause;
 
-  /**
-   * Set the extends clause for this class to the given [extendsClause].
-   */
+  /// Set the extends clause for this class to the given [extendsClause].
   void set extendsClause(ExtendsClause extendsClause);
 
-  /**
-   * Set the implements clause for the class to the given [implementsClause].
-   */
+  /// Set the implements clause for the class to the given [implementsClause].
   void set implementsClause(ImplementsClause implementsClause);
 
-  /**
-   * Return `true` if this class is declared to be an abstract class.
-   */
+  /// Return `true` if this class is declared to be an abstract class.
   bool get isAbstract;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the native clause for this class, or `null` if the class does not
-   * have a native clause.
-   */
+  /// Return the native clause for this class, or `null` if the class does not
+  /// have a native clause.
   NativeClause get nativeClause;
 
-  /**
-   * Set the native clause for this class to the given [nativeClause].
-   */
+  /// Set the native clause for this class to the given [nativeClause].
   void set nativeClause(NativeClause nativeClause);
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 
-  /**
-   * Set the type parameters for the class to the given list of [typeParameters].
-   */
+  /// Set the type parameters for the class to the given list of
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 
-  /**
-   * Return the with clause for the class, or `null` if the class does not have
-   * a with clause.
-   */
+  /// Return the with clause for the class, or `null` if the class does not have
+  /// a with clause.
   WithClause get withClause;
 
-  /**
-   * Set the with clause for the class to the given [withClause].
-   */
+  /// Set the with clause for the class to the given [withClause].
   void set withClause(WithClause withClause);
 
-  /**
-   * Return the constructor declared in the class with the given [name], or
-   * `null` if there is no such constructor. If the [name] is `null` then the
-   * default constructor will be searched for.
-   */
+  /// Return the constructor declared in the class with the given [name], or
+  /// `null` if there is no such constructor. If the [name] is `null` then the
+  /// default constructor will be searched for.
   ConstructorDeclaration getConstructor(String name);
 }
 
-/**
- * A node that declares a name within the scope of a class.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ClassMember extends Declaration {}
+/// A node that declares a name within the scope of a class.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ClassMember implements Declaration {}
 
-/**
- * The declaration of a class or mixin.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ClassOrMixinDeclaration extends NamedCompilationUnitMember {
+/// The declaration of a class or mixin.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ClassOrMixinDeclaration implements NamedCompilationUnitMember {
   @override
   ClassElement get declaredElement;
 
-  /**
-   * Returns the implements clause for the class/mixin, or `null` if the
-   * class/mixin does not implement any interfaces.
-   */
+  /// Returns the implements clause for the class/mixin, or `null` if the
+  /// class/mixin does not implement any interfaces.
   ImplementsClause get implementsClause;
 
-  /**
-   * Returns the left curly bracket.
-   */
+  /// Returns the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Returns the members defined by the class/mixin.
-   */
+  /// Returns the members defined by the class/mixin.
   NodeList<ClassMember> get members;
 
-  /**
-   * Returns the right curly bracket.
-   */
+  /// Returns the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Returns the type parameters for the class/mixin, or `null` if the
-   * class/mixin does not have any type parameters.
-   */
+  /// Returns the type parameters for the class/mixin, or `null` if the
+  /// class/mixin does not have any type parameters.
   TypeParameterList get typeParameters;
 
-  /**
-   * Returns the field declared in the class/mixin with the given [name], or
-   * `null` if there is no such field.
-   */
+  /// Returns the field declared in the class/mixin with the given [name], or
+  /// `null` if there is no such field.
   VariableDeclaration getField(String name);
 
-  /**
-   * Returns the method declared in the class/mixin with the given [name], or
-   * `null` if there is no such method.
-   */
+  /// Returns the method declared in the class/mixin with the given [name], or
+  /// `null` if there is no such method.
   MethodDeclaration getMethod(String name);
 }
 
-/**
- * A class type alias.
- *
- *    classTypeAlias ::=
- *        [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
- *
- *    mixinApplication ::=
- *        [TypeName] [WithClause] [ImplementsClause]? ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ClassTypeAlias extends TypeAlias {
-  /**
-   * Return the token for the 'abstract' keyword, or `null` if this is not
-   * defining an abstract class.
-   */
+/// A class type alias.
+///
+///    classTypeAlias ::=
+///        [SimpleIdentifier] [TypeParameterList]? '=' 'abstract'? mixinApplication
+///
+///    mixinApplication ::=
+///        [TypeName] [WithClause] [ImplementsClause]? ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ClassTypeAlias implements TypeAlias {
+  /// Return the token for the 'abstract' keyword, or `null` if this is not
+  /// defining an abstract class.
   Token get abstractKeyword;
 
-  /**
-   * Set the token for the 'abstract' keyword to the given [token].
-   */
+  /// Set the token for the 'abstract' keyword to the given [token].
   void set abstractKeyword(Token token);
 
-  /**
-   * Return the token for the '=' separating the name from the definition.
-   */
+  /// Return the token for the '=' separating the name from the definition.
   Token get equals;
 
-  /**
-   * Set the token for the '=' separating the name from the definition to the
-   * given [token].
-   */
+  /// Set the token for the '=' separating the name from the definition to the
+  /// given [token].
   void set equals(Token token);
 
-  /**
-   * Return the implements clause for this class, or `null` if there is no
-   * implements clause.
-   */
+  /// Return the implements clause for this class, or `null` if there is no
+  /// implements clause.
   ImplementsClause get implementsClause;
 
-  /**
-   * Set the implements clause for this class to the given [implementsClause].
-   */
+  /// Set the implements clause for this class to the given [implementsClause].
   void set implementsClause(ImplementsClause implementsClause);
 
-  /**
-   * Return `true` if this class is declared to be an abstract class.
-   */
+  /// Return `true` if this class is declared to be an abstract class.
   bool get isAbstract;
 
-  /**
-   * Return the name of the superclass of the class being declared.
-   */
+  /// Return the name of the superclass of the class being declared.
   TypeName get superclass;
 
-  /**
-   * Set the name of the superclass of the class being declared to the given
-   * [superclass] name.
-   */
+  /// Set the name of the superclass of the class being declared to the given
+  /// [superclass] name.
   void set superclass(TypeName superclass);
 
-  /**
-   * Return the type parameters for the class, or `null` if the class does not
-   * have any type parameters.
-   */
+  /// Return the type parameters for the class, or `null` if the class does not
+  /// have any type parameters.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters for the class to the given list of [typeParameters].
-   */
+  /// Set the type parameters for the class to the given list of
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 
-  /**
-   * Return the with clause for this class.
-   */
+  /// Return the with clause for this class.
   WithClause get withClause;
 
-  /**
-   * Set the with clause for this class to the given with [withClause].
-   */
+  /// Set the with clause for this class to the given with [withClause].
   void set withClause(WithClause withClause);
 }
 
-/**
- * An element in a literal list or literal set.
- *
- *    collectionElement ::=
- *        [Expression]
- *      | [IfElement<CollectionElement>]
- *      | [ForElement<CollectionElement>]
- *      | [SpreadElement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An element in a list, map or set literal.
+///
+///    collectionElement ::=
+///        [Expression]
+///      | [IfElement]
+///      | [ForElement]
+///      | [MapLiteralEntry]
+///      | [SpreadElement]
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class CollectionElement implements AstNode {}
 
-/**
- * A for element in a literal list or literal set.
- *
- *    forElement ::=
- *        'await'? 'for' '(' [ForLoopParts] ')' [CollectionElement | MapElement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CollectionForElement
-    implements CollectionElement, ForElement<CollectionElement> {}
-
-/**
- * An if element in a literal list or literal set.
- *
- *    ifElement ::=
- *        'if' '(' [Expression] ')' [CollectionElement]
- *        ( 'else' [CollectionElement] )?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CollectionIfElement
-    implements CollectionElement, IfElement<CollectionElement> {}
-
-/**
- * A combinator associated with an import or export directive.
- *
- *    combinator ::=
- *        [HideCombinator]
- *      | [ShowCombinator]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Combinator extends AstNode {
-  /**
-   * Return the 'hide' or 'show' keyword specifying what kind of processing is
-   * to be done on the names.
-   */
+/// A combinator associated with an import or export directive.
+///
+///    combinator ::=
+///        [HideCombinator]
+///      | [ShowCombinator]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Combinator implements AstNode {
+  /// Return the 'hide' or 'show' keyword specifying what kind of processing is
+  /// to be done on the names.
   Token get keyword;
 
-  /**
-   * Set the 'hide' or 'show' keyword specifying what kind of processing is
-   * to be done on the names to the given [token].
-   */
+  /// Set the 'hide' or 'show' keyword specifying what kind of processing is
+  /// to be done on the names to the given [token].
   void set keyword(Token token);
 }
 
-/**
- * A comment within the source code.
- *
- *    comment ::=
- *        endOfLineComment
- *      | blockComment
- *      | documentationComment
- *
- *    endOfLineComment ::=
- *        '//' (CHARACTER - EOL)* EOL
- *
- *    blockComment ::=
- *        '/ *' CHARACTER* '&#42;/'
- *
- *    documentationComment ::=
- *        '/ **' (CHARACTER | [CommentReference])* '&#42;/'
- *      | ('///' (CHARACTER - EOL)* EOL)+
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Comment extends AstNode {
-  /**
-   * Return `true` if this is a block comment.
-   */
+/// A comment within the source code.
+///
+///    comment ::=
+///        endOfLineComment
+///      | blockComment
+///      | documentationComment
+///
+///    endOfLineComment ::=
+///        '//' (CHARACTER - EOL)* EOL
+///
+///    blockComment ::=
+///        '/ *' CHARACTER* '&#42;/'
+///
+///    documentationComment ::=
+///        '/ **' (CHARACTER | [CommentReference])* '&#42;/'
+///      | ('///' (CHARACTER - EOL)* EOL)+
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Comment implements AstNode {
+  /// Return `true` if this is a block comment.
   bool get isBlock;
 
-  /**
-   * Return `true` if this is a documentation comment.
-   */
+  /// Return `true` if this is a documentation comment.
   bool get isDocumentation;
 
-  /**
-   * Return `true` if this is an end-of-line comment.
-   */
+  /// Return `true` if this is an end-of-line comment.
   bool get isEndOfLine;
 
-  /**
-   * Return the references embedded within the documentation comment.
-   */
+  /// Return the references embedded within the documentation comment.
   NodeList<CommentReference> get references;
 
-  /**
-   * Return the tokens representing the comment.
-   */
+  /// Return the tokens representing the comment.
   List<Token> get tokens;
 }
 
-/**
- * A reference to a Dart element that is found within a documentation comment.
- *
- *    commentReference ::=
- *        '[' 'new'? [Identifier] ']'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CommentReference extends AstNode {
-  /**
-   * Return the identifier being referenced.
-   */
+/// A reference to a Dart element that is found within a documentation comment.
+///
+///    commentReference ::=
+///        '[' 'new'? [Identifier] ']'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CommentReference implements AstNode {
+  /// Return the identifier being referenced.
   Identifier get identifier;
 
-  /**
-   * Set the identifier being referenced to the given [identifier].
-   */
+  /// Set the identifier being referenced to the given [identifier].
   void set identifier(Identifier identifier);
 
-  /**
-   * Return the token representing the 'new' keyword, or `null` if there was no
-   * 'new' keyword.
-   */
+  /// Return the token representing the 'new' keyword, or `null` if there was no
+  /// 'new' keyword.
   Token get newKeyword;
 
-  /**
-   * Set the token representing the 'new' keyword to the given [token].
-   */
+  /// Set the token representing the 'new' keyword to the given [token].
   void set newKeyword(Token token);
 }
 
-/**
- * A compilation unit.
- *
- * While the grammar restricts the order of the directives and declarations
- * within a compilation unit, this class does not enforce those restrictions.
- * In particular, the children of a compilation unit will be visited in lexical
- * order even if lexical order does not conform to the restrictions of the
- * grammar.
- *
- *    compilationUnit ::=
- *        directives declarations
- *
- *    directives ::=
- *        [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
- *      | [PartOfDirective]
- *
- *    namespaceDirective ::=
- *        [ImportDirective]
- *      | [ExportDirective]
- *
- *    declarations ::=
- *        [CompilationUnitMember]*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CompilationUnit extends AstNode {
-  /**
-   * Set the first token included in this node's source range to the given
-   * [token].
-   */
+/// A compilation unit.
+///
+/// While the grammar restricts the order of the directives and declarations
+/// within a compilation unit, this class does not enforce those restrictions.
+/// In particular, the children of a compilation unit will be visited in lexical
+/// order even if lexical order does not conform to the restrictions of the
+/// grammar.
+///
+///    compilationUnit ::=
+///        directives declarations
+///
+///    directives ::=
+///        [ScriptTag]? [LibraryDirective]? namespaceDirective* [PartDirective]*
+///      | [PartOfDirective]
+///
+///    namespaceDirective ::=
+///        [ImportDirective]
+///      | [ExportDirective]
+///
+///    declarations ::=
+///        [CompilationUnitMember]*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CompilationUnit implements AstNode {
+  /// Set the first token included in this node's source range to the given
+  /// [token].
   void set beginToken(Token token);
 
-  /**
-   * Return the declarations contained in this compilation unit.
-   */
+  /// Return the declarations contained in this compilation unit.
   NodeList<CompilationUnitMember> get declarations;
 
-  /**
-   * Return the element associated with this compilation unit, or `null` if the
-   * AST structure has not been resolved.
-   */
+  /// Return the element associated with this compilation unit, or `null` if the
+  /// AST structure has not been resolved.
   CompilationUnitElement get declaredElement;
 
-  /**
-   * Return the directives contained in this compilation unit.
-   */
+  /// Return the directives contained in this compilation unit.
   NodeList<Directive> get directives;
 
-  /**
-   * Return the element associated with this compilation unit, or `null` if the
-   * AST structure has not been resolved.
-   */
+  /// Return the element associated with this compilation unit, or `null` if the
+  /// AST structure has not been resolved.
   @deprecated
   CompilationUnitElement get element;
 
-  /**
-   * Set the element associated with this compilation unit to the given
-   * [element].
-   */
+  /// Set the element associated with this compilation unit to the given
+  /// [element].
   void set element(CompilationUnitElement element);
 
-  /**
-   * Set the last token included in this node's source range to the given
-   * [token].
-   */
+  /// Set the last token included in this node's source range to the given
+  /// [token].
   void set endToken(Token token);
 
-  /**
-   * Return the line information for this compilation unit.
-   */
+  /// Return the line information for this compilation unit.
   LineInfo get lineInfo;
 
-  /**
-   * Set the line information for this compilation unit to the given [info].
-   */
+  /// Set the line information for this compilation unit to the given [info].
   void set lineInfo(LineInfo info);
 
-  /**
-   * Return the script tag at the beginning of the compilation unit, or `null`
-   * if there is no script tag in this compilation unit.
-   */
+  /// Return the script tag at the beginning of the compilation unit, or `null`
+  /// if there is no script tag in this compilation unit.
   ScriptTag get scriptTag;
 
-  /**
-   * Set the script tag at the beginning of the compilation unit to the given
-   * [scriptTag].
-   */
+  /// Set the script tag at the beginning of the compilation unit to the given
+  /// [scriptTag].
   void set scriptTag(ScriptTag scriptTag);
 
-  /**
-   * Return a list containing all of the directives and declarations in this
-   * compilation unit, sorted in lexical order.
-   */
+  /// Return a list containing all of the directives and declarations in this
+  /// compilation unit, sorted in lexical order.
   List<AstNode> get sortedDirectivesAndDeclarations;
 }
 
-/**
- * A node that declares one or more names within the scope of a compilation
- * unit.
- *
- *    compilationUnitMember ::=
- *        [ClassDeclaration]
- *      | [TypeAlias]
- *      | [FunctionDeclaration]
- *      | [MethodDeclaration]
- *      | [VariableDeclaration]
- *      | [VariableDeclaration]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class CompilationUnitMember extends Declaration {}
+/// A node that declares one or more names within the scope of a compilation
+/// unit.
+///
+///    compilationUnitMember ::=
+///        [ClassDeclaration]
+///      | [TypeAlias]
+///      | [FunctionDeclaration]
+///      | [MethodDeclaration]
+///      | [VariableDeclaration]
+///      | [VariableDeclaration]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class CompilationUnitMember implements Declaration {}
 
-/**
- * A conditional expression.
- *
- *    conditionalExpression ::=
- *        [Expression] '?' [Expression] ':' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ConditionalExpression extends Expression {
-  /**
-   * Return the token used to separate the then expression from the else
-   * expression.
-   */
+/// A conditional expression.
+///
+///    conditionalExpression ::=
+///        [Expression] '?' [Expression] ':' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConditionalExpression implements Expression {
+  /// Return the token used to separate the then expression from the else
+  /// expression.
   Token get colon;
 
-  /**
-   * Set the token used to separate the then expression from the else expression
-   * to the given [token].
-   */
+  /// Set the token used to separate the then expression from the else
+  /// expression to the given [token].
   void set colon(Token token);
 
-  /**
-   * Return the condition used to determine which of the expressions is executed
-   * next.
-   */
+  /// Return the condition used to determine which of the expressions is
+  /// executed next.
   Expression get condition;
 
-  /**
-   * Set the condition used to determine which of the expressions is executed
-   * next to the given [expression].
-   */
+  /// Set the condition used to determine which of the expressions is executed
+  /// next to the given [expression].
   void set condition(Expression expression);
 
-  /**
-   * Return the expression that is executed if the condition evaluates to
-   * `false`.
-   */
+  /// Return the expression that is executed if the condition evaluates to
+  /// `false`.
   Expression get elseExpression;
 
-  /**
-   * Set the expression that is executed if the condition evaluates to `false`
-   * to the given [expression].
-   */
+  /// Set the expression that is executed if the condition evaluates to `false`
+  /// to the given [expression].
   void set elseExpression(Expression expression);
 
-  /**
-   * Return the token used to separate the condition from the then expression.
-   */
+  /// Return the token used to separate the condition from the then expression.
   Token get question;
 
-  /**
-   * Set the token used to separate the condition from the then expression to
-   * the given [token].
-   */
+  /// Set the token used to separate the condition from the then expression to
+  /// the given [token].
   void set question(Token token);
 
-  /**
-   * Return the expression that is executed if the condition evaluates to
-   * `true`.
-   */
+  /// Return the expression that is executed if the condition evaluates to
+  /// `true`.
   Expression get thenExpression;
 
-  /**
-   * Set the expression that is executed if the condition evaluates to `true` to
-   * the given [expression].
-   */
+  /// Set the expression that is executed if the condition evaluates to `true`
+  /// to the given [expression].
   void set thenExpression(Expression expression);
 }
 
-/**
- * A configuration in either an import or export directive.
- *
- *    configuration ::=
- *        'if' '(' test ')' uri
- *
- *    test ::=
- *        dottedName ('==' stringLiteral)?
- *
- *    dottedName ::=
- *        identifier ('.' identifier)*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Configuration extends AstNode {
-  /**
-   * Return the token for the equal operator, or `null` if the condition does
-   * not include an equality test.
-   */
+/// A configuration in either an import or export directive.
+///
+///    configuration ::=
+///        'if' '(' test ')' uri
+///
+///    test ::=
+///        dottedName ('==' stringLiteral)?
+///
+///    dottedName ::=
+///        identifier ('.' identifier)*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Configuration implements AstNode {
+  /// Return the token for the equal operator, or `null` if the condition does
+  /// not include an equality test.
   Token get equalToken;
 
-  /**
-   * Set the token for the equal operator to the given [token].
-   */
+  /// Set the token for the equal operator to the given [token].
   void set equalToken(Token token);
 
-  /**
-   * Return the token for the 'if' keyword.
-   */
+  /// Return the token for the 'if' keyword.
   Token get ifKeyword;
 
-  /**
-   * Set the token for the 'if' keyword to the given [token].
-   */
+  /// Set the token for the 'if' keyword to the given [token].
   void set ifKeyword(Token token);
 
-  /**
-   * Return the token for the left parenthesis.
-   */
+  /// Return the token for the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the token for the left parenthesis to the given [token].
-   */
+  /// Set the token for the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the URI of the implementation library to be used if the condition is
-   * true.
-   */
+  /// Return the URI of the implementation library to be used if the condition
+  /// is true.
   @deprecated
   StringLiteral get libraryUri;
 
-  /**
-   * Set the URI of the implementation library to be used if the condition is
-   * true to the given [uri].
-   */
+  /// Set the URI of the implementation library to be used if the condition is
+  /// true to the given [uri].
   @deprecated
   void set libraryUri(StringLiteral uri);
 
-  /**
-   * Return the name of the declared variable whose value is being used in the
-   * condition.
-   */
+  /// Return the name of the declared variable whose value is being used in the
+  /// condition.
   DottedName get name;
 
-  /**
-   * Set the name of the declared variable whose value is being used in the
-   * condition to the given [name].
-   */
+  /// Set the name of the declared variable whose value is being used in the
+  /// condition to the given [name].
   void set name(DottedName name);
 
-  /**
-   * Return the token for the right parenthesis.
-   */
+  /// Return the token for the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the token for the right parenthesis to the given [token].
-   */
+  /// Set the token for the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the URI of the implementation library to be used if the condition is
-   * true.
-   */
+  /// Return the URI of the implementation library to be used if the condition
+  /// is true.
   StringLiteral get uri;
 
-  /**
-   * Set the URI of the implementation library to be used if the condition is
-   * true to the given [uri].
-   */
+  /// Set the URI of the implementation library to be used if the condition is
+  /// true to the given [uri].
   void set uri(StringLiteral uri);
 
-  /**
-   * Return the source to which the [uri] was resolved.
-   */
+  /// Return the source to which the [uri] was resolved.
   Source get uriSource;
 
-  /**
-   * Set the source to which the [uri] was resolved to the given [source].
-   */
+  /// Set the source to which the [uri] was resolved to the given [source].
   void set uriSource(Source source);
 
-  /**
-   * Return the value to which the value of the declared variable will be
-   * compared, or `null` if the condition does not include an equality test.
-   */
+  /// Return the value to which the value of the declared variable will be
+  /// compared, or `null` if the condition does not include an equality test.
   StringLiteral get value;
 
-  /**
-   * Set the value to which the value of the declared variable will be
-   * compared to the given [value].
-   */
+  /// Set the value to which the value of the declared variable will be
+  /// compared to the given [value].
   void set value(StringLiteral value);
 }
 
-/**
- * A constructor declaration.
- *
- *    constructorDeclaration ::=
- *        constructorSignature [FunctionBody]?
- *      | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
- *
- *    constructorSignature ::=
- *        'external'? constructorName formalParameterList initializerList?
- *      | 'external'? 'factory' factoryName formalParameterList initializerList?
- *      | 'external'? 'const'  constructorName formalParameterList initializerList?
- *
- *    constructorName ::=
- *        [SimpleIdentifier] ('.' [SimpleIdentifier])?
- *
- *    factoryName ::=
- *        [Identifier] ('.' [SimpleIdentifier])?
- *
- *    initializerList ::=
- *        ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ConstructorDeclaration extends ClassMember {
-  /**
-   * Return the body of the constructor, or `null` if the constructor does not
-   * have a body.
-   */
+/// A constructor declaration.
+///
+///    constructorDeclaration ::=
+///        constructorSignature [FunctionBody]?
+///      | constructorName formalParameterList ':' 'this' ('.' [SimpleIdentifier])? arguments
+///
+///    constructorSignature ::=
+///        'external'? constructorName formalParameterList initializerList?
+///      | 'external'? 'factory' factoryName formalParameterList initializerList?
+///      | 'external'? 'const'  constructorName formalParameterList initializerList?
+///
+///    constructorName ::=
+///        [SimpleIdentifier] ('.' [SimpleIdentifier])?
+///
+///    factoryName ::=
+///        [Identifier] ('.' [SimpleIdentifier])?
+///
+///    initializerList ::=
+///        ':' [ConstructorInitializer] (',' [ConstructorInitializer])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConstructorDeclaration implements ClassMember {
+  /// Return the body of the constructor, or `null` if the constructor does not
+  /// have a body.
   FunctionBody get body;
 
-  /**
-   * Set the body of the constructor to the given [functionBody].
-   */
+  /// Set the body of the constructor to the given [functionBody].
   void set body(FunctionBody functionBody);
 
-  /**
-   * Return the token for the 'const' keyword, or `null` if the constructor is
-   * not a const constructor.
-   */
+  /// Return the token for the 'const' keyword, or `null` if the constructor is
+  /// not a const constructor.
   Token get constKeyword;
 
-  /**
-   * Set the token for the 'const' keyword to the given [token].
-   */
+  /// Set the token for the 'const' keyword to the given [token].
   void set constKeyword(Token token);
 
   @override
@@ -1946,340 +1432,235 @@
   @deprecated
   ConstructorElement get element;
 
-  /**
-   * Set the element associated with this constructor to the given [element].
-   */
+  /// Set the element associated with this constructor to the given [element].
   void set element(ConstructorElement element);
 
-  /**
-   * Return the token for the 'external' keyword to the given [token].
-   */
+  /// Return the token for the 'external' keyword to the given [token].
   Token get externalKeyword;
 
-  /**
-   * Set the token for the 'external' keyword, or `null` if the constructor
-   * is not external.
-   */
+  /// Set the token for the 'external' keyword, or `null` if the constructor
+  /// is not external.
   void set externalKeyword(Token token);
 
-  /**
-   * Return the token for the 'factory' keyword, or `null` if the constructor is
-   * not a factory constructor.
-   */
+  /// Return the token for the 'factory' keyword, or `null` if the constructor
+  /// is not a factory constructor.
   Token get factoryKeyword;
 
-  /**
-   * Set the token for the 'factory' keyword to the given [token].
-   */
+  /// Set the token for the 'factory' keyword to the given [token].
   void set factoryKeyword(Token token);
 
-  /**
-   * Return the initializers associated with the constructor.
-   */
+  /// Return the initializers associated with the constructor.
   NodeList<ConstructorInitializer> get initializers;
 
-  /**
-   * Return the name of the constructor, or `null` if the constructor being
-   * declared is unnamed.
-   */
+  /// Return the name of the constructor, or `null` if the constructor being
+  /// declared is unnamed.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the constructor to the given [identifier].
-   */
+  /// Set the name of the constructor to the given [identifier].
   void set name(SimpleIdentifier identifier);
 
-  /**
-   * Return the parameters associated with the constructor.
-   */
+  /// Return the parameters associated with the constructor.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters associated with the constructor to the given list of
-   * [parameters].
-   */
+  /// Set the parameters associated with the constructor to the given list of
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the token for the period before the constructor name, or `null` if
-   * the constructor being declared is unnamed.
-   */
+  /// Return the token for the period before the constructor name, or `null` if
+  /// the constructor being declared is unnamed.
   Token get period;
 
-  /**
-   * Set the token for the period before the constructor name to the given
-   * [token].
-   */
+  /// Set the token for the period before the constructor name to the given
+  /// [token].
   void set period(Token token);
 
-  /**
-   * Return the name of the constructor to which this constructor will be
-   * redirected, or `null` if this is not a redirecting factory constructor.
-   */
+  /// Return the name of the constructor to which this constructor will be
+  /// redirected, or `null` if this is not a redirecting factory constructor.
   ConstructorName get redirectedConstructor;
 
-  /**
-   * Set the name of the constructor to which this constructor will be
-   * redirected to the given [redirectedConstructor] name.
-   */
+  /// Set the name of the constructor to which this constructor will be
+  /// redirected to the given [redirectedConstructor] name.
   void set redirectedConstructor(ConstructorName redirectedConstructor);
 
-  /**
-   * Return the type of object being created. This can be different than the
-   * type in which the constructor is being declared if the constructor is the
-   * implementation of a factory constructor.
-   */
+  /// Return the type of object being created. This can be different than the
+  /// type in which the constructor is being declared if the constructor is the
+  /// implementation of a factory constructor.
   Identifier get returnType;
 
-  /**
-   * Set the type of object being created to the given [typeName].
-   */
+  /// Set the type of object being created to the given [typeName].
   void set returnType(Identifier typeName);
 
-  /**
-   * Return the token for the separator (colon or equals) before the initializer
-   * list or redirection, or `null` if there are no initializers.
-   */
+  /// Return the token for the separator (colon or equals) before the
+  /// initializer list or redirection, or `null` if there are no initializers.
   Token get separator;
 
-  /**
-   * Set the token for the separator (colon or equals) before the initializer
-   * list or redirection to the given [token].
-   */
+  /// Set the token for the separator (colon or equals) before the initializer
+  /// list or redirection to the given [token].
   void set separator(Token token);
 }
 
-/**
- * The initialization of a field within a constructor's initialization list.
- *
- *    fieldInitializer ::=
- *        ('this' '.')? [SimpleIdentifier] '=' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ConstructorFieldInitializer extends ConstructorInitializer {
-  /**
-   * Return the token for the equal sign between the field name and the
-   * expression.
-   */
+/// The initialization of a field within a constructor's initialization list.
+///
+///    fieldInitializer ::=
+///        ('this' '.')? [SimpleIdentifier] '=' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConstructorFieldInitializer implements ConstructorInitializer {
+  /// Return the token for the equal sign between the field name and the
+  /// expression.
   Token get equals;
 
-  /**
-   * Set the token for the equal sign between the field name and the
-   * expression to the given [token].
-   */
+  /// Set the token for the equal sign between the field name and the
+  /// expression to the given [token].
   void set equals(Token token);
 
-  /**
-   * Return the expression computing the value to which the field will be
-   * initialized.
-   */
+  /// Return the expression computing the value to which the field will be
+  /// initialized.
   Expression get expression;
 
-  /**
-   * Set the expression computing the value to which the field will be
-   * initialized to the given [expression].
-   */
+  /// Set the expression computing the value to which the field will be
+  /// initialized to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the name of the field being initialized.
-   */
+  /// Return the name of the field being initialized.
   SimpleIdentifier get fieldName;
 
-  /**
-   * Set the name of the field being initialized to the given [identifier].
-   */
+  /// Set the name of the field being initialized to the given [identifier].
   void set fieldName(SimpleIdentifier identifier);
 
-  /**
-   * Return the token for the period after the 'this' keyword, or `null` if
-   * there is no 'this' keyword.
-   */
+  /// Return the token for the period after the 'this' keyword, or `null` if
+  /// there is no 'this' keyword.
   Token get period;
 
-  /**
-   * Set the token for the period after the 'this' keyword to the given [token].
-   */
+  /// Set the token for the period after the 'this' keyword to the given
+  /// [token].
   void set period(Token token);
 
-  /**
-   * Return the token for the 'this' keyword, or `null` if there is no 'this'
-   * keyword.
-   */
+  /// Return the token for the 'this' keyword, or `null` if there is no 'this'
+  /// keyword.
   Token get thisKeyword;
 
-  /**
-   * Set the token for the 'this' keyword to the given [token].
-   */
+  /// Set the token for the 'this' keyword to the given [token].
   void set thisKeyword(Token token);
 }
 
-/**
- * A node that can occur in the initializer list of a constructor declaration.
- *
- *    constructorInitializer ::=
- *        [SuperConstructorInvocation]
- *      | [ConstructorFieldInitializer]
- *      | [RedirectingConstructorInvocation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ConstructorInitializer extends AstNode {}
+/// A node that can occur in the initializer list of a constructor declaration.
+///
+///    constructorInitializer ::=
+///        [SuperConstructorInvocation]
+///      | [ConstructorFieldInitializer]
+///      | [RedirectingConstructorInvocation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConstructorInitializer implements AstNode {}
 
-/**
- * The name of a constructor.
- *
- *    constructorName ::=
- *        type ('.' identifier)?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ConstructorName extends AstNode
-    implements ConstructorReferenceNode {
-  /**
-   * Return the name of the constructor, or `null` if the specified constructor
-   * is the unnamed constructor.
-   */
+/// The name of a constructor.
+///
+///    constructorName ::=
+///        type ('.' identifier)?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ConstructorName implements AstNode, ConstructorReferenceNode {
+  /// Return the name of the constructor, or `null` if the specified constructor
+  /// is the unnamed constructor.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the constructor to the given [name].
-   */
+  /// Set the name of the constructor to the given [name].
   void set name(SimpleIdentifier name);
 
-  /**
-   * Return the token for the period before the constructor name, or `null` if
-   * the specified constructor is the unnamed constructor.
-   */
+  /// Return the token for the period before the constructor name, or `null` if
+  /// the specified constructor is the unnamed constructor.
   Token get period;
 
-  /**
-   * Set the token for the period before the constructor name to the given
-   * [token].
-   */
+  /// Set the token for the period before the constructor name to the given
+  /// [token].
   void set period(Token token);
 
-  /**
-   * Return the name of the type defining the constructor.
-   */
+  /// Return the name of the type defining the constructor.
   TypeName get type;
 
-  /**
-   * Set the name of the type defining the constructor to the given [type] name.
-   */
+  /// Set the name of the type defining the constructor to the given [type]
+  /// name.
   void set type(TypeName type);
 }
 
-/**
- * An AST node that makes reference to a constructor.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An AST node that makes reference to a constructor.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ConstructorReferenceNode implements AstNode {
-  /**
-   * Return the element associated with the referenced constructor based on
-   * static type information, or `null` if the AST structure has not been
-   * resolved or if the constructor could not be resolved.
-   */
+  /// Return the element associated with the referenced constructor based on
+  /// static type information, or `null` if the AST structure has not been
+  /// resolved or if the constructor could not be resolved.
   ConstructorElement get staticElement;
 
-  /**
-   * Set the element associated with the referenced constructor based on static
-   * type information to the given [element].
-   */
+  /// Set the element associated with the referenced constructor based on static
+  /// type information to the given [element].
   void set staticElement(ConstructorElement element);
 }
 
-/**
- * A continue statement.
- *
- *    continueStatement ::=
- *        'continue' [SimpleIdentifier]? ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ContinueStatement extends Statement {
-  /**
-   * Return the token representing the 'continue' keyword.
-   */
+/// A continue statement.
+///
+///    continueStatement ::=
+///        'continue' [SimpleIdentifier]? ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ContinueStatement implements Statement {
+  /// Return the token representing the 'continue' keyword.
   Token get continueKeyword;
 
-  /**
-   * Set the token representing the 'continue' keyword to the given [token].
-   */
+  /// Set the token representing the 'continue' keyword to the given [token].
   void set continueKeyword(Token token);
 
-  /**
-   * Return the label associated with the statement, or `null` if there is no
-   * label.
-   */
+  /// Return the label associated with the statement, or `null` if there is no
+  /// label.
   SimpleIdentifier get label;
 
-  /**
-   * Set the label associated with the statement to the given [identifier].
-   */
+  /// Set the label associated with the statement to the given [identifier].
   void set label(SimpleIdentifier identifier);
 
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the node to which this continue statement is continuing. This will
-   * be either a [Statement] (in the case of continuing a loop), a
-   * [SwitchMember] (in the case of continuing from one switch case to another),
-   * or `null` if the AST has not yet been resolved or if the target could not
-   * be resolved. Note that if the source code has errors, the target might be
-   * invalid (e.g. the target may be in an enclosing function).
-   */
+  /// Return the node to which this continue statement is continuing. This will
+  /// be either a [Statement] (in the case of continuing a loop), a
+  /// [SwitchMember] (in the case of continuing from one switch case to
+  /// another), or `null` if the AST has not yet been resolved or if the target
+  /// could not be resolved. Note that if the source code has errors, the target
+  /// might be invalid (e.g. the target may be in an enclosing function).
   AstNode get target;
 
-  /**
-   * Set the node to which this continue statement is continuing to the given
-   * [node].
-   */
+  /// Set the node to which this continue statement is continuing to the given
+  /// [node].
   void set target(AstNode node);
 }
 
-/**
- * A node that represents the declaration of one or more names. Each declared
- * name is visible within a name scope.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Declaration extends AnnotatedNode {
-  /**
-   * Return the element associated with this declaration, or `null` if either
-   * this node corresponds to a list of declarations or if the AST structure has
-   * not been resolved.
-   */
+/// A node that represents the declaration of one or more names. Each declared
+/// name is visible within a name scope.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Declaration implements AnnotatedNode {
+  /// Return the element associated with this declaration, or `null` if either
+  /// this node corresponds to a list of declarations or if the AST structure
+  /// has not been resolved.
   Element get declaredElement;
 
-  /**
-   * Return the element associated with this declaration, or `null` if either
-   * this node corresponds to a list of declarations or if the AST structure has
-   * not been resolved.
-   */
+  /// Return the element associated with this declaration, or `null` if either
+  /// this node corresponds to a list of declarations or if the AST structure
+  /// has not been resolved.
   @deprecated
   Element get element;
 }
 
-/**
- * The declaration of a single identifier.
- *
- *    declaredIdentifier ::=
- *        [Annotation] finalConstVarOrType [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class DeclaredIdentifier extends Declaration {
+/// The declaration of a single identifier.
+///
+///    declaredIdentifier ::=
+///        [Annotation] finalConstVarOrType [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DeclaredIdentifier implements Declaration {
   @override
   LocalVariableElement get declaredElement;
 
@@ -2287,340 +1668,235 @@
   @override
   LocalVariableElement get element;
 
-  /**
-   * Return the name of the variable being declared.
-   */
+  /// Return the name of the variable being declared.
   SimpleIdentifier get identifier;
 
-  /**
-   * Set the name of the variable being declared to the given [identifier].
-   */
+  /// Set the name of the variable being declared to the given [identifier].
   void set identifier(SimpleIdentifier identifier);
 
-  /**
-   * Return `true` if this variable was declared with the 'const' modifier.
-   */
+  /// Return `true` if this variable was declared with the 'const' modifier.
   bool get isConst;
 
-  /**
-   * Return `true` if this variable was declared with the 'final' modifier.
-   * Variables that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
+  /// Return `true` if this variable was declared with the 'final' modifier.
+  /// Variables that are declared with the 'const' modifier will return `false`
+  /// even though they are implicitly final.
   bool get isFinal;
 
-  /**
-   * Return the token representing either the 'final', 'const' or 'var' keyword,
-   * or `null` if no keyword was used.
-   */
+  /// Return the token representing either the 'final', 'const' or 'var'
+  /// keyword, or `null` if no keyword was used.
   Token get keyword;
 
-  /**
-   * Set the token representing either the 'final', 'const' or 'var' keyword to
-   * the given [token].
-   */
+  /// Set the token representing either the 'final', 'const' or 'var' keyword to
+  /// the given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the name of the declared type of the parameter, or `null` if the
-   * parameter does not have a declared type.
-   */
+  /// Return the name of the declared type of the parameter, or `null` if the
+  /// parameter does not have a declared type.
   TypeAnnotation get type;
 
-  /**
-   * Set the declared type of the parameter to the given [type].
-   */
+  /// Set the declared type of the parameter to the given [type].
   void set type(TypeAnnotation type);
 }
 
-/**
- * A formal parameter with a default value. There are two kinds of parameters
- * that are both represented by this class: named formal parameters and
- * positional formal parameters.
- *
- *    defaultFormalParameter ::=
- *        [NormalFormalParameter] ('=' [Expression])?
- *
- *    defaultNamedParameter ::=
- *        [NormalFormalParameter] (':' [Expression])?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class DefaultFormalParameter extends FormalParameter {
-  /**
-   * Return the expression computing the default value for the parameter, or
-   * `null` if there is no default value.
-   */
+/// A formal parameter with a default value. There are two kinds of parameters
+/// that are both represented by this class: named formal parameters and
+/// positional formal parameters.
+///
+///    defaultFormalParameter ::=
+///        [NormalFormalParameter] ('=' [Expression])?
+///
+///    defaultNamedParameter ::=
+///        [NormalFormalParameter] (':' [Expression])?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DefaultFormalParameter implements FormalParameter {
+  /// Return the expression computing the default value for the parameter, or
+  /// `null` if there is no default value.
   Expression get defaultValue;
 
-  /**
-   * Set the expression computing the default value for the parameter to the
-   * given [expression].
-   */
+  /// Set the expression computing the default value for the parameter to the
+  /// given [expression].
   void set defaultValue(Expression expression);
 
-  /**
-   * Set the kind of this parameter to the given [kind].
-   */
+  /// Set the kind of this parameter to the given [kind].
   void set kind(ParameterKind kind);
 
-  /**
-   * Return the formal parameter with which the default value is associated.
-   */
+  /// Return the formal parameter with which the default value is associated.
   NormalFormalParameter get parameter;
 
-  /**
-   * Set the formal parameter with which the default value is associated to the
-   * given [formalParameter].
-   */
+  /// Set the formal parameter with which the default value is associated to the
+  /// given [formalParameter].
   void set parameter(NormalFormalParameter formalParameter);
 
-  /**
-   * Return the token separating the parameter from the default value, or `null`
-   * if there is no default value.
-   */
+  /// Return the token separating the parameter from the default value, or
+  /// `null` if there is no default value.
   Token get separator;
 
-  /**
-   * Set the token separating the parameter from the default value to the given
-   * [token].
-   */
+  /// Set the token separating the parameter from the default value to the given
+  /// [token].
   void set separator(Token token);
 }
 
-/**
- * A node that represents a directive.
- *
- *    directive ::=
- *        [ExportDirective]
- *      | [ImportDirective]
- *      | [LibraryDirective]
- *      | [PartDirective]
- *      | [PartOfDirective]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Directive extends AnnotatedNode {
-  /**
-   * Return the element associated with this directive, or `null` if the AST
-   * structure has not been resolved or if this directive could not be resolved.
-   */
+/// A node that represents a directive.
+///
+///    directive ::=
+///        [ExportDirective]
+///      | [ImportDirective]
+///      | [LibraryDirective]
+///      | [PartDirective]
+///      | [PartOfDirective]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Directive implements AnnotatedNode {
+  /// Return the element associated with this directive, or `null` if the AST
+  /// structure has not been resolved or if this directive could not be
+  /// resolved.
   Element get element;
 
-  /**
-   * Set the element associated with this directive to the given [element].
-   */
+  /// Set the element associated with this directive to the given [element].
   void set element(Element element);
 
-  /**
-   * Return the token representing the keyword that introduces this directive
-   * ('import', 'export', 'library' or 'part').
-   */
+  /// Return the token representing the keyword that introduces this directive
+  /// ('import', 'export', 'library' or 'part').
   Token get keyword;
 }
 
-/**
- * A do statement.
- *
- *    doStatement ::=
- *        'do' [Statement] 'while' '(' [Expression] ')' ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class DoStatement extends Statement {
-  /**
-   * Return the body of the loop.
-   */
+/// A do statement.
+///
+///    doStatement ::=
+///        'do' [Statement] 'while' '(' [Expression] ')' ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DoStatement implements Statement {
+  /// Return the body of the loop.
   Statement get body;
 
-  /**
-   * Set the body of the loop to the given [statement].
-   */
+  /// Set the body of the loop to the given [statement].
   void set body(Statement statement);
 
-  /**
-   * Return the condition that determines when the loop will terminate.
-   */
+  /// Return the condition that determines when the loop will terminate.
   Expression get condition;
 
-  /**
-   * Set the condition that determines when the loop will terminate to the given
-   * [expression].
-   */
+  /// Set the condition that determines when the loop will terminate to the
+  /// given [expression].
   void set condition(Expression expression);
 
-  /**
-   * Return the token representing the 'do' keyword.
-   */
+  /// Return the token representing the 'do' keyword.
   Token get doKeyword;
 
-  /**
-   * Set the token representing the 'do' keyword to the given [token].
-   */
+  /// Set the token representing the 'do' keyword to the given [token].
   void set doKeyword(Token token);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the token representing the 'while' keyword.
-   */
+  /// Return the token representing the 'while' keyword.
   Token get whileKeyword;
 
-  /**
-   * Set the token representing the 'while' keyword to the given [token].
-   */
+  /// Set the token representing the 'while' keyword to the given [token].
   void set whileKeyword(Token token);
 }
 
-/**
- * A dotted name, used in a configuration within an import or export directive.
- *
- *    dottedName ::=
- *        [SimpleIdentifier] ('.' [SimpleIdentifier])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class DottedName extends AstNode {
-  /**
-   * Return the components of the identifier.
-   */
+/// A dotted name, used in a configuration within an import or export directive.
+///
+///    dottedName ::=
+///        [SimpleIdentifier] ('.' [SimpleIdentifier])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DottedName implements AstNode {
+  /// Return the components of the identifier.
   NodeList<SimpleIdentifier> get components;
 }
 
-/**
- * A floating point literal expression.
- *
- *    doubleLiteral ::=
- *        decimalDigit+ ('.' decimalDigit*)? exponent?
- *      | '.' decimalDigit+ exponent?
- *
- *    exponent ::=
- *        ('e' | 'E') ('+' | '-')? decimalDigit+
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class DoubleLiteral extends Literal {
-  /**
-   * Return the token representing the literal.
-   */
+/// A floating point literal expression.
+///
+///    doubleLiteral ::=
+///        decimalDigit+ ('.' decimalDigit*)? exponent?
+///      | '.' decimalDigit+ exponent?
+///
+///    exponent ::=
+///        ('e' | 'E') ('+' | '-')? decimalDigit+
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class DoubleLiteral implements Literal {
+  /// Return the token representing the literal.
   Token get literal;
 
-  /**
-   * Set the token representing the literal to the given [token].
-   */
+  /// Set the token representing the literal to the given [token].
   void set literal(Token token);
 
-  /**
-   * Return the value of the literal.
-   */
+  /// Return the value of the literal.
   double get value;
 
-  /**
-   * Set the value of the literal to the given [value].
-   */
+  /// Set the value of the literal to the given [value].
   void set value(double value);
 }
 
-/**
- * An empty function body, which can only appear in constructors or abstract
- * methods.
- *
- *    emptyFunctionBody ::=
- *        ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class EmptyFunctionBody extends FunctionBody {
-  /**
-   * Return the token representing the semicolon that marks the end of the
-   * function body.
-   */
+/// An empty function body, which can only appear in constructors or abstract
+/// methods.
+///
+///    emptyFunctionBody ::=
+///        ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class EmptyFunctionBody implements FunctionBody {
+  /// Return the token representing the semicolon that marks the end of the
+  /// function body.
   Token get semicolon;
 
-  /**
-   * Set the token representing the semicolon that marks the end of the
-   * function body to the given [token].
-   */
+  /// Set the token representing the semicolon that marks the end of the
+  /// function body to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * An empty statement.
- *
- *    emptyStatement ::=
- *        ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class EmptyStatement extends Statement {
-  /**
-   * Return the semicolon terminating the statement.
-   */
+/// An empty statement.
+///
+///    emptyStatement ::=
+///        ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class EmptyStatement implements Statement {
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * The declaration of an enum constant.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class EnumConstantDeclaration extends Declaration {
-  /**
-   * Return the name of the constant.
-   */
+/// The declaration of an enum constant.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class EnumConstantDeclaration implements Declaration {
+  /// Return the name of the constant.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the constant to the given [name].
-   */
+  /// Set the name of the constant to the given [name].
   void set name(SimpleIdentifier name);
 }
 
-/**
- * The declaration of an enumeration.
- *
- *    enumType ::=
- *        metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class EnumDeclaration extends NamedCompilationUnitMember {
-  /**
-   * Return the enumeration constants being declared.
-   */
+/// The declaration of an enumeration.
+///
+///    enumType ::=
+///        metadata 'enum' [SimpleIdentifier] '{' [SimpleIdentifier] (',' [SimpleIdentifier])* (',')? '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class EnumDeclaration implements NamedCompilationUnitMember {
+  /// Return the enumeration constants being declared.
   NodeList<EnumConstantDeclaration> get constants;
 
   @override
@@ -2630,1118 +1906,792 @@
   @override
   ClassElement get element;
 
-  /**
-   * Return the 'enum' keyword.
-   */
+  /// Return the 'enum' keyword.
   Token get enumKeyword;
 
-  /**
-   * Set the 'enum' keyword to the given [token].
-   */
+  /// Set the 'enum' keyword to the given [token].
   void set enumKeyword(Token token);
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * An export directive.
- *
- *    exportDirective ::=
- *        [Annotation] 'export' [StringLiteral] [Combinator]* ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ExportDirective extends NamespaceDirective {}
+/// An export directive.
+///
+///    exportDirective ::=
+///        [Annotation] 'export' [StringLiteral] [Combinator]* ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExportDirective implements NamespaceDirective {}
 
-/**
- * A node that represents an expression.
- *
- *    expression ::=
- *        [AssignmentExpression]
- *      | [ConditionalExpression] cascadeSection*
- *      | [ThrowExpression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// A node that represents an expression.
+///
+///    expression ::=
+///        [AssignmentExpression]
+///      | [ConditionalExpression] cascadeSection*
+///      | [ThrowExpression]
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class Expression implements CollectionElement {
-  /**
-   * Return the best parameter element information available for this
-   * expression. If type propagation was able to find a better parameter element
-   * than static analysis, that type will be returned. Otherwise, the result of
-   * static analysis will be returned.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticParameterElement] instead.
-   */
+  /// Return the best parameter element information available for this
+  /// expression. If type propagation was able to find a better parameter
+  /// element than static analysis, that type will be returned. Otherwise, the
+  /// result of static analysis will be returned.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticParameterElement] instead.
   @deprecated
   ParameterElement get bestParameterElement;
 
-  /**
-   * Return the best type information available for this expression. If type
-   * propagation was able to find a better type than static analysis, that type
-   * will be returned. Otherwise, the result of static analysis will be
-   * returned. If no type analysis has been performed, then the type 'dynamic'
-   * will be returned.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticType] instead, but be aware that [staticType] will return `null`
-   * under some circumstances, while [bestType] did not.
-   */
+  /// Return the best type information available for this expression. If type
+  /// propagation was able to find a better type than static analysis, that type
+  /// will be returned. Otherwise, the result of static analysis will be
+  /// returned. If no type analysis has been performed, then the type 'dynamic'
+  /// will be returned.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticType] instead, but be aware that [staticType] will return
+  /// `null` under some circumstances, while [bestType] did not.
   @deprecated
   DartType get bestType;
 
-  /**
-   * Return `true` if this expression is syntactically valid for the LHS of an
-   * [AssignmentExpression].
-   */
+  /// Return `true` if this expression is syntactically valid for the LHS of an
+  /// [AssignmentExpression].
   bool get isAssignable;
 
-  /**
-   * Return the precedence of this expression. The precedence is a positive
-   * integer value that defines how the source code is parsed into an AST. For
-   * example `a * b + c` is parsed as `(a * b) + c` because the precedence of
-   * `*` is greater than the precedence of `+`.
-   *
-   * Clients should not assume that returned values will stay the same, they
-   * might change as result of specification change. Only relative order should
-   * be used.
-   */
+  /// Return the precedence of this expression. The precedence is a positive
+  /// integer value that defines how the source code is parsed into an AST. For
+  /// example `a * b + c` is parsed as `(a * b) + c` because the precedence of
+  /// `*` is greater than the precedence of `+`.
+  ///
+  /// Clients should not assume that returned values will stay the same, they
+  /// might change as result of specification change. Only relative order should
+  /// be used.
   int get precedence;
 
-  /**
-   * If this expression is an argument to an invocation, and the AST structure
-   * has been resolved, and the function being invoked is known based on
-   * propagated type information, and this expression corresponds to one of the
-   * parameters of the function being invoked, then return the parameter element
-   * representing the parameter to which the value of this expression will be
-   * bound. Otherwise, return `null`.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticParameterElement] instead.
-   */
+  /// If this expression is an argument to an invocation, and the AST structure
+  /// has been resolved, and the function being invoked is known based on
+  /// propagated type information, and this expression corresponds to one of the
+  /// parameters of the function being invoked, then return the parameter
+  /// element representing the parameter to which the value of this expression
+  /// will be bound. Otherwise, return `null`.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticParameterElement] instead.
   @deprecated
   ParameterElement get propagatedParameterElement;
 
-  /**
-   * Return the propagated type of this expression, or `null` if type
-   * propagation has not been performed on the AST structure.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticType] instead.
-   */
+  /// Return the propagated type of this expression, or `null` if type
+  /// propagation has not been performed on the AST structure.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticType] instead.
   @deprecated
   DartType get propagatedType;
 
-  /**
-   * Set the propagated type of this expression to the given [type].
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticType] instead.
-   */
+  /// Set the propagated type of this expression to the given [type].
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticType] instead.
   @deprecated
   void set propagatedType(DartType type);
 
-  /**
-   * If this expression is an argument to an invocation, and the AST structure
-   * has been resolved, and the function being invoked is known based on static
-   * type information, and this expression corresponds to one of the parameters
-   * of the function being invoked, then return the parameter element
-   * representing the parameter to which the value of this expression will be
-   * bound. Otherwise, return `null`.
-   */
+  /// If this expression is an argument to an invocation, and the AST structure
+  /// has been resolved, and the function being invoked is known based on static
+  /// type information, and this expression corresponds to one of the parameters
+  /// of the function being invoked, then return the parameter element
+  /// representing the parameter to which the value of this expression will be
+  /// bound. Otherwise, return `null`.
   ParameterElement get staticParameterElement;
 
-  /**
-   * Return the static type of this expression, or `null` if the AST structure
-   * has not been resolved.
-   */
+  /// Return the static type of this expression, or `null` if the AST structure
+  /// has not been resolved.
   DartType get staticType;
 
-  /**
-   * Set the static type of this expression to the given [type].
-   */
+  /// Set the static type of this expression to the given [type].
   void set staticType(DartType type);
 
-  /**
-   * If this expression is a parenthesized expression, return the result of
-   * unwrapping the expression inside the parentheses. Otherwise, return this
-   * expression.
-   */
+  /// If this expression is a parenthesized expression, return the result of
+  /// unwrapping the expression inside the parentheses. Otherwise, return this
+  /// expression.
   Expression get unParenthesized;
 }
 
-/**
- * A function body consisting of a single expression.
- *
- *    expressionFunctionBody ::=
- *        'async'? '=>' [Expression] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ExpressionFunctionBody extends FunctionBody {
-  /**
-   * Return the expression representing the body of the function.
-   */
+/// A function body consisting of a single expression.
+///
+///    expressionFunctionBody ::=
+///        'async'? '=>' [Expression] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExpressionFunctionBody implements FunctionBody {
+  /// Return the expression representing the body of the function.
   Expression get expression;
 
-  /**
-   * Set the expression representing the body of the function to the given
-   * [expression].
-   */
+  /// Set the expression representing the body of the function to the given
+  /// [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the token introducing the expression that represents the body of the
-   * function.
-   */
+  /// Return the token introducing the expression that represents the body of the
+  /// function.
   Token get functionDefinition;
 
-  /**
-   * Set the token introducing the expression that represents the body of the
-   * function to the given [token].
-   */
+  /// Set the token introducing the expression that represents the body of the
+  /// function to the given [token].
   void set functionDefinition(Token token);
 
-  /**
-   * Set token representing the 'async' or 'sync' keyword to the given [token].
-   */
+  /// Set token representing the 'async' or 'sync' keyword to the given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * An expression used as a statement.
- *
- *    expressionStatement ::=
- *        [Expression]? ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ExpressionStatement extends Statement {
-  /**
-   * Return the expression that comprises the statement.
-   */
+/// An expression used as a statement.
+///
+///    expressionStatement ::=
+///        [Expression]? ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExpressionStatement implements Statement {
+  /// Return the expression that comprises the statement.
   Expression get expression;
 
-  /**
-   * Set the expression that comprises the statement to the given [expression].
-   */
+  /// Set the expression that comprises the statement to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the semicolon terminating the statement, or `null` if the expression is a
-   * function expression and therefore isn't followed by a semicolon.
-   */
+  /// Return the semicolon terminating the statement, or `null` if the
+  /// expression is a function expression and therefore isn't followed by a
+  /// semicolon.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * The "extends" clause in a class declaration.
- *
- *    extendsClause ::=
- *        'extends' [TypeName]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ExtendsClause extends AstNode {
-  /**
-   * Return the token representing the 'extends' keyword.
-   */
+/// The "extends" clause in a class declaration.
+///
+///    extendsClause ::=
+///        'extends' [TypeName]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ExtendsClause implements AstNode {
+  /// Return the token representing the 'extends' keyword.
   Token get extendsKeyword;
 
-  /**
-   * Set the token representing the 'extends' keyword to the given [token].
-   */
+  /// Set the token representing the 'extends' keyword to the given [token].
   void set extendsKeyword(Token token);
 
-  /**
-   * Return the name of the class that is being extended.
-   */
+  /// Return the name of the class that is being extended.
   TypeName get superclass;
 
-  /**
-   * Set the name of the class that is being extended to the given [name].
-   */
+  /// Set the name of the class that is being extended to the given [name].
   void set superclass(TypeName name);
 }
 
-/**
- * The declaration of one or more fields of the same type.
- *
- *    fieldDeclaration ::=
- *        'static'? [VariableDeclarationList] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FieldDeclaration extends ClassMember {
-  /**
-   * The 'covariant' keyword, or `null` if the keyword was not used.
-   */
+/// The declaration of one or more fields of the same type.
+///
+///    fieldDeclaration ::=
+///        'static'? [VariableDeclarationList] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FieldDeclaration implements ClassMember {
+  /// The 'covariant' keyword, or `null` if the keyword was not used.
   Token get covariantKeyword;
 
-  /**
-   * Set the token for the 'covariant' keyword to the given [token].
-   */
+  /// Set the token for the 'covariant' keyword to the given [token].
   void set covariantKeyword(Token token);
 
-  /**
-   * Return the fields being declared.
-   */
+  /// Return the fields being declared.
   VariableDeclarationList get fields;
 
-  /**
-   * Set the fields being declared to the given list of [fields].
-   */
+  /// Set the fields being declared to the given list of [fields].
   void set fields(VariableDeclarationList fields);
 
-  /**
-   * Return `true` if the fields are declared to be static.
-   */
+  /// Return `true` if the fields are declared to be static.
   bool get isStatic;
 
-  /**
-   * Return the semicolon terminating the declaration.
-   */
+  /// Return the semicolon terminating the declaration.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the declaration to the given [token].
-   */
+  /// Set the semicolon terminating the declaration to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the token representing the 'static' keyword, or `null` if the fields
-   * are not static.
-   */
+  /// Return the token representing the 'static' keyword, or `null` if the
+  /// fields are not static.
   Token get staticKeyword;
 
-  /**
-   * Set the token representing the 'static' keyword to the given [token].
-   */
+  /// Set the token representing the 'static' keyword to the given [token].
   void set staticKeyword(Token token);
 }
 
-/**
- * A field formal parameter.
- *
- *    fieldFormalParameter ::=
- *        ('final' [TypeAnnotation] | 'const' [TypeAnnotation] | 'var' | [TypeAnnotation])?
- *        'this' '.' [SimpleIdentifier] ([TypeParameterList]? [FormalParameterList])?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FieldFormalParameter extends NormalFormalParameter {
-  /**
-   * Return the token representing either the 'final', 'const' or 'var' keyword,
-   * or `null` if no keyword was used.
-   */
+/// A field formal parameter.
+///
+///    fieldFormalParameter ::=
+///        ('final' [TypeAnnotation] | 'const' [TypeAnnotation] | 'var' | [TypeAnnotation])?
+///        'this' '.' [SimpleIdentifier] ([TypeParameterList]? [FormalParameterList])?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FieldFormalParameter implements NormalFormalParameter {
+  /// Return the token representing either the 'final', 'const' or 'var'
+  /// keyword, or `null` if no keyword was used.
   Token get keyword;
 
-  /**
-   * Set the token representing either the 'final', 'const' or 'var' keyword to
-   * the given [token].
-   */
+  /// Set the token representing either the 'final', 'const' or 'var' keyword to
+  /// the given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the parameters of the function-typed parameter, or `null` if this is
-   * not a function-typed field formal parameter.
-   */
+  /// Return the parameters of the function-typed parameter, or `null` if this
+  /// is not a function-typed field formal parameter.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters of the function-typed parameter to the given
-   * [parameters].
-   */
+  /// Set the parameters of the function-typed parameter to the given
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the token representing the period.
-   */
+  /// Return the token representing the period.
   Token get period;
 
-  /**
-   * Set the token representing the period to the given [token].
-   */
+  /// Set the token representing the period to the given [token].
   void set period(Token token);
 
-  /**
-   * Return the token representing the 'this' keyword.
-   */
+  /// Return the token representing the 'this' keyword.
   Token get thisKeyword;
 
-  /**
-   * Set the token representing the 'this' keyword to the given [token].
-   */
+  /// Set the token representing the 'this' keyword to the given [token].
   void set thisKeyword(Token token);
 
-  /**
-   * Return the declared type of the parameter, or `null` if the parameter does
-   * not have a declared type. Note that if this is a function-typed field
-   * formal parameter this is the return type of the function.
-   */
+  /// Return the declared type of the parameter, or `null` if the parameter does
+  /// not have a declared type. Note that if this is a function-typed field
+  /// formal parameter this is the return type of the function.
   TypeAnnotation get type;
 
-  /**
-   * Set the declared type of the parameter to the given [type].
-   */
+  /// Set the declared type of the parameter to the given [type].
   void set type(TypeAnnotation type);
 
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
+  /// Return the type parameters associated with this method, or `null` if this
+  /// method is not a generic method.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
+  /// Set the type parameters associated with this method to the given
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * The parts of a for-each loop that control the iteration.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for-each loop that control the iteration.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForEachParts implements ForLoopParts {
-  /**
-   * Return the token representing the 'in' keyword.
-   */
+  /// Return the token representing the 'in' keyword.
   Token get inKeyword;
 
-  /**
-   * Return the expression evaluated to produce the iterator.
-   */
+  /// Return the expression evaluated to produce the iterator.
   Expression get iterable;
 }
 
-/**
- * The parts of a for-each loop that control the iteration when the loop
- * variable is declared as part of the for loop.
- *
- *   forLoopParts ::=
- *       [DeclaredIdentifier] 'in' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for-each loop that control the iteration when the loop
+/// variable is declared as part of the for loop.
+///
+///   forLoopParts ::=
+///       [DeclaredIdentifier] 'in' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForEachPartsWithDeclaration implements ForEachParts {
-  /**
-   * Return the declaration of the loop variable.
-   */
+  /// Return the declaration of the loop variable.
   DeclaredIdentifier get loopVariable;
 }
 
-/**
- * The parts of a for-each loop that control the iteration when the loop
- * variable is declared outside of the for loop.
- *
- *   forLoopParts ::=
- *       [SimpleIdentifier] 'in' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for-each loop that control the iteration when the loop
+/// variable is declared outside of the for loop.
+///
+///   forLoopParts ::=
+///       [SimpleIdentifier] 'in' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForEachPartsWithIdentifier implements ForEachParts {
-  /**
-   * Return the loop variable.
-   */
+  /// Return the loop variable.
   SimpleIdentifier get identifier;
 }
 
-/**
- * A for-each statement.
- *
- *    forEachStatement ::=
- *        'await'? 'for' '(' [DeclaredIdentifier] 'in' [Expression] ')' [Block]
- *      | 'await'? 'for' '(' [SimpleIdentifier] 'in' [Expression] ')' [Block]
- *
- * This is the class that is used to represent a for-each loop when neither the
- * 'control-flow-collections' nor 'spread-collections' experiments are enabled.
- * If either of those experiments are enabled, then [ForStatement2] will be
- * used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ForEachStatement extends Statement {
-  /**
-   * Return the token representing the 'await' keyword, or `null` if there is no
-   * 'await' keyword.
-   */
+/// A for-each statement.
+///
+///    forEachStatement ::=
+///        'await'? 'for' '(' [DeclaredIdentifier] 'in' [Expression] ')' [Block]
+///      | 'await'? 'for' '(' [SimpleIdentifier] 'in' [Expression] ')' [Block]
+///
+/// This is the class that is used to represent a for-each loop when neither the
+/// 'control-flow-collections' nor 'spread-collections' experiments are enabled.
+/// If either of those experiments are enabled, then [ForStatement2] will be
+/// used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ForEachStatement implements Statement {
+  /// Return the token representing the 'await' keyword, or `null` if there is
+  /// no 'await' keyword.
   Token get awaitKeyword;
 
-  /**
-   * Set the token representing the 'await' keyword to the given [token].
-   */
+  /// Set the token representing the 'await' keyword to the given [token].
   void set awaitKeyword(Token token);
 
-  /**
-   * Return the body of the loop.
-   */
+  /// Return the body of the loop.
   Statement get body;
 
-  /**
-   * Set the body of the loop to the given [statement].
-   */
+  /// Set the body of the loop to the given [statement].
   void set body(Statement statement);
 
-  /**
-   * Return the token representing the 'for' keyword.
-   */
+  /// Return the token representing the 'for' keyword.
   Token get forKeyword;
 
-  /**
-   * Set the token representing the 'for' keyword to the given [token].
-   */
+  /// Set the token representing the 'for' keyword to the given [token].
   void set forKeyword(Token token);
 
-  /**
-   * Return the loop variable, or `null` if the loop variable is declared in the
-   * 'for'.
-   */
+  /// Return the loop variable, or `null` if the loop variable is declared in
+  /// the 'for'.
   SimpleIdentifier get identifier;
 
-  /**
-   * Set the loop variable to the given [identifier].
-   */
+  /// Set the loop variable to the given [identifier].
   void set identifier(SimpleIdentifier identifier);
 
-  /**
-   * Return the token representing the 'in' keyword.
-   */
+  /// Return the token representing the 'in' keyword.
   Token get inKeyword;
 
-  /**
-   * Set the token representing the 'in' keyword to the given [token].
-   */
+  /// Set the token representing the 'in' keyword to the given [token].
   void set inKeyword(Token token);
 
-  /**
-   * Return the expression evaluated to produce the iterator.
-   */
+  /// Return the expression evaluated to produce the iterator.
   Expression get iterable;
 
-  /**
-   * Set the expression evaluated to produce the iterator to the given
-   * [expression].
-   */
+  /// Set the expression evaluated to produce the iterator to the given
+  /// [expression].
   void set iterable(Expression expression);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the declaration of the loop variable, or `null` if the loop variable
-   * is a simple identifier.
-   */
+  /// Return the declaration of the loop variable, or `null` if the loop
+  /// variable is a simple identifier.
   DeclaredIdentifier get loopVariable;
 
-  /**
-   * Set the declaration of the loop variable to the given [variable].
-   */
+  /// Set the declaration of the loop variable to the given [variable].
   void set loopVariable(DeclaredIdentifier variable);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 }
 
-/**
- * The basic structure of a for element.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ForElement<E> implements AstNode {
-  /**
-   * Return the token representing the 'await' keyword, or `null` if there was
-   * no 'await' keyword.
-   */
+/// The basic structure of a for element.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ForElement implements CollectionElement {
+  /// Return the token representing the 'await' keyword, or `null` if there was
+  /// no 'await' keyword.
   Token get awaitKeyword;
 
-  /**
-   * Return the body of the loop.
-   */
-  E get body;
+  /// Return the body of the loop.
+  CollectionElement get body;
 
-  /**
-   * Return the token representing the 'for' keyword.
-   */
+  /// Return the token representing the 'for' keyword.
   Token get forKeyword;
 
-  /**
-   * Return the parts of the for element that control the iteration.
-   */
+  /// Return the parts of the for element that control the iteration.
   ForLoopParts get forLoopParts;
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 }
 
-/**
- * The parts of a for or for-each loop that control the iteration.
- *
- *   forLoopParts ::=
- *       [VariableDeclaration] ';' [Expression]? ';' expressionList?
- *     | [Expression]? ';' [Expression]? ';' expressionList?
- *     | [DeclaredIdentifier] 'in' [Expression]
- *     | [SimpleIdentifier] 'in' [Expression]
- *
- *   expressionList ::=
- *       [Expression] (',' [Expression])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for or for-each loop that control the iteration.
+///
+///   forLoopParts ::=
+///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
+///     | [Expression]? ';' [Expression]? ';' expressionList?
+///     | [DeclaredIdentifier] 'in' [Expression]
+///     | [SimpleIdentifier] 'in' [Expression]
+///
+///   expressionList ::=
+///       [Expression] (',' [Expression])*
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForLoopParts implements AstNode {}
 
-/**
- * A node representing a parameter to a function.
- *
- *    formalParameter ::=
- *        [NormalFormalParameter]
- *      | [DefaultFormalParameter]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FormalParameter extends AstNode {
-  /**
-   * The 'covariant' keyword, or `null` if the keyword was not used.
-   */
+/// A node representing a parameter to a function.
+///
+///    formalParameter ::=
+///        [NormalFormalParameter]
+///      | [DefaultFormalParameter]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FormalParameter implements AstNode {
+  /// The 'covariant' keyword, or `null` if the keyword was not used.
   Token get covariantKeyword;
 
-  /**
-   * Return the element representing this parameter, or `null` if this parameter
-   * has not been resolved.
-   */
+  /// Return the element representing this parameter, or `null` if this
+  /// parameter has not been resolved.
   ParameterElement get declaredElement;
 
-  /**
-   * Return the element representing this parameter, or `null` if this parameter
-   * has not been resolved.
-   */
+  /// Return the element representing this parameter, or `null` if this
+  /// parameter has not been resolved.
   @deprecated
   ParameterElement get element;
 
-  /**
-   * Return the name of the parameter being declared.
-   */
+  /// Return the name of the parameter being declared.
   SimpleIdentifier get identifier;
 
-  /**
-   * Return `true` if this parameter was declared with the 'const' modifier.
-   */
+  /// Return `true` if this parameter was declared with the 'const' modifier.
   bool get isConst;
 
-  /**
-   * Return `true` if this parameter was declared with the 'final' modifier.
-   * Parameters that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
+  /// Return `true` if this parameter was declared with the 'final' modifier.
+  /// Parameters that are declared with the 'const' modifier will return `false`
+  /// 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 are
+  /// always optional, even when they are annotated with the `@required`
+  /// annotation.
   bool get isNamed;
 
-  /**
-   * Return `true` if this parameter is an optional parameter. Optional
-   * parameters can either be positional or named.
-   */
+  /// 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 positional
-   * parameter.
-   */
+  /// Return `true` if this parameter is both an optional and positional
+  /// parameter.
   bool get isOptionalPositional;
 
-  /**
-   * Return `true` if this parameter is a positional parameter. Positional
-   * parameters can either be required or optional.
-   */
+  /// Return `true` if this parameter is a positional parameter. Positional
+  /// parameters can either be required or optional.
   bool get isPositional;
 
-  /**
-   * Return `true` if this parameter is a required parameter. Required
-   * parameters are always positional.
-   *
-   * Note: this will return `false` for a named parameter that is annotated with
-   * the `@required` annotation.
-   */
+  /// Return `true` if this parameter is a required parameter. Required
+  /// parameters are always positional.
+  ///
+  /// Note: this will return `false` for a named parameter that is annotated with
+  /// the `@required` annotation.
   bool get isRequired;
 
-  /**
-   * Return the kind of this parameter.
-   */
+  /// Return the kind of this parameter.
   @deprecated
   ParameterKind get kind;
 
-  /**
-   * Return the annotations associated with this parameter.
-   */
+  /// Return the annotations associated with this parameter.
   NodeList<Annotation> get metadata;
 }
 
-/**
- * The formal parameter list of a method declaration, function declaration, or
- * function type alias.
- *
- * While the grammar requires all optional formal parameters to follow all of
- * the normal formal parameters and at most one grouping of optional formal
- * parameters, this class does not enforce those constraints. All parameters are
- * flattened into a single list, which can have any or all kinds of parameters
- * (normal, named, and positional) in any order.
- *
- *    formalParameterList ::=
- *        '(' ')'
- *      | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
- *      | '(' optionalFormalParameters ')'
- *
- *    normalFormalParameters ::=
- *        [NormalFormalParameter] (',' [NormalFormalParameter])*
- *
- *    optionalFormalParameters ::=
- *        optionalPositionalFormalParameters
- *      | namedFormalParameters
- *
- *    optionalPositionalFormalParameters ::=
- *        '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']'
- *
- *    namedFormalParameters ::=
- *        '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FormalParameterList extends AstNode {
-  /**
-   * Return the left square bracket ('[') or left curly brace ('{') introducing
-   * the optional parameters, or `null` if there are no optional parameters.
-   */
+/// The formal parameter list of a method declaration, function declaration, or
+/// function type alias.
+///
+/// While the grammar requires all optional formal parameters to follow all of
+/// the normal formal parameters and at most one grouping of optional formal
+/// parameters, this class does not enforce those constraints. All parameters
+/// are flattened into a single list, which can have any or all kinds of
+/// parameters (normal, named, and positional) in any order.
+///
+///    formalParameterList ::=
+///        '(' ')'
+///      | '(' normalFormalParameters (',' optionalFormalParameters)? ')'
+///      | '(' optionalFormalParameters ')'
+///
+///    normalFormalParameters ::=
+///        [NormalFormalParameter] (',' [NormalFormalParameter])*
+///
+///    optionalFormalParameters ::=
+///        optionalPositionalFormalParameters
+///      | namedFormalParameters
+///
+///    optionalPositionalFormalParameters ::=
+///        '[' [DefaultFormalParameter] (',' [DefaultFormalParameter])* ']'
+///
+///    namedFormalParameters ::=
+///        '{' [DefaultFormalParameter] (',' [DefaultFormalParameter])* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FormalParameterList implements AstNode {
+  /// Return the left square bracket ('[') or left curly brace ('{') introducing
+  /// the optional parameters, or `null` if there are no optional parameters.
   Token get leftDelimiter;
 
-  /**
-   * Set the left square bracket ('[') or left curly brace ('{') introducing
-   * the optional parameters to the given [token].
-   */
+  /// Set the left square bracket ('[') or left curly brace ('{') introducing
+  /// the optional parameters to the given [token].
   void set leftDelimiter(Token token);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return a list containing the elements representing the parameters in this
-   * list. The list will contain `null`s if the parameters in this list have not
-   * been resolved.
-   */
+  /// Return a list containing the elements representing the parameters in this
+  /// list. The list will contain `null`s if the parameters in this list have
+  /// not been resolved.
   List<ParameterElement> get parameterElements;
 
-  /**
-   * Return the parameters associated with the method.
-   */
+  /// Return the parameters associated with the method.
   NodeList<FormalParameter> get parameters;
 
-  /**
-   * Return the right square bracket (']') or right curly brace ('}') terminating the
-   * optional parameters, or `null` if there are no optional parameters.
-   */
+  /// Return the right square bracket (']') or right curly brace ('}')
+  /// terminating the optional parameters, or `null` if there are no optional
+  /// parameters.
   Token get rightDelimiter;
 
-  /**
-   * Set the right square bracket (']') or right curly brace ('}') terminating the
-   * optional parameters to the given [token].
-   */
+  /// Set the right square bracket (']') or right curly brace ('}') terminating
+  /// the optional parameters to the given [token].
   void set rightDelimiter(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 }
 
-/**
- * The parts of a for loop that control the iteration.
- *
- *   forLoopParts ::=
- *       [VariableDeclaration] ';' [Expression]? ';' expressionList?
- *     | [Expression]? ';' [Expression]? ';' expressionList?
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for loop that control the iteration.
+///
+///   forLoopParts ::=
+///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
+///     | [Expression]? ';' [Expression]? ';' expressionList?
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForParts implements ForLoopParts {
-  /**
-   * Return the condition used to determine when to terminate the loop, or
-   * `null` if there is no condition.
-   */
+  /// Return the condition used to determine when to terminate the loop, or
+  /// `null` if there is no condition.
   Expression get condition;
 
-  /**
-   * Return the semicolon separating the initializer and the condition.
-   */
+  /// Return the semicolon separating the initializer and the condition.
   Token get leftSeparator;
 
-  /**
-   * Return the semicolon separating the condition and the updater.
-   */
+  /// Return the semicolon separating the condition and the updater.
   Token get rightSeparator;
 
-  /**
-   * Return the list of expressions run after each execution of the loop body.
-   */
+  /// Return the list of expressions run after each execution of the loop body.
   NodeList<Expression> get updaters;
 }
 
-/**
- * The parts of a for loop that control the iteration when there are one or more
- * variable declarations as part of the for loop.
- *
- *   forLoopParts ::=
- *       [VariableDeclarationList] ';' [Expression]? ';' expressionList?
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for loop that control the iteration when there are one or
+/// more variable declarations as part of the for loop.
+///
+///   forLoopParts ::=
+///       [VariableDeclarationList] ';' [Expression]? ';' expressionList?
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForPartsWithDeclarations implements ForParts {
-  /**
-   * Return the declaration of the loop variables.
-   */
+  /// Return the declaration of the loop variables.
   VariableDeclarationList get variables;
 }
 
-/**
- * The parts of a for loop that control the iteration when there are no variable
- * declarations as part of the for loop.
- *
- *   forLoopParts ::=
- *       [Expression]? ';' [Expression]? ';' expressionList?
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// The parts of a for loop that control the iteration when there are no
+/// variable declarations as part of the for loop.
+///
+///   forLoopParts ::=
+///       [Expression]? ';' [Expression]? ';' expressionList?
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class ForPartsWithExpression implements ForParts {
-  /**
-   * Return the initialization expression, or `null` if there is no
-   * initialization expression.
-   */
+  /// Return the initialization expression, or `null` if there is no
+  /// initialization expression.
   Expression get initialization;
 }
 
-/**
- * A for statement.
- *
- *    forStatement ::=
- *        'for' '(' forLoopParts ')' [Statement]
- *
- *    forLoopParts ::=
- *        forInitializerStatement ';' [Expression]? ';' [Expression]?
- *
- *    forInitializerStatement ::=
- *        [DefaultFormalParameter]
- *      | [Expression]?
- *
- * This is the class that is used to represent a for loop when neither the
- * 'control-flow-collections' nor 'spread-collections' experiments are enabled.
- * If either of those experiments are enabled, then [ForStatement2] will be
- * used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ForStatement extends Statement {
-  /**
-   * Return the body of the loop.
-   */
+/// A for statement.
+///
+///    forStatement ::=
+///        'for' '(' forLoopParts ')' [Statement]
+///
+///    forLoopParts ::=
+///        forInitializerStatement ';' [Expression]? ';' [Expression]?
+///
+///    forInitializerStatement ::=
+///        [DefaultFormalParameter]
+///      | [Expression]?
+///
+/// This is the class that is used to represent a for loop when neither the
+/// 'control-flow-collections' nor 'spread-collections' experiments are enabled.
+/// If either of those experiments are enabled, then [ForStatement2] will be
+/// used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ForStatement implements Statement {
+  /// Return the body of the loop.
   Statement get body;
 
-  /**
-   * Set the body of the loop to the given [statement].
-   */
+  /// Set the body of the loop to the given [statement].
   void set body(Statement statement);
 
-  /**
-   * Return the condition used to determine when to terminate the loop, or
-   * `null` if there is no condition.
-   */
+  /// Return the condition used to determine when to terminate the loop, or
+  /// `null` if there is no condition.
   Expression get condition;
 
-  /**
-   * Set the condition used to determine when to terminate the loop to the given
-   * [expression].
-   */
+  /// Set the condition used to determine when to terminate the loop to the
+  /// given [expression].
   void set condition(Expression expression);
 
-  /**
-   * Return the token representing the 'for' keyword.
-   */
+  /// Return the token representing the 'for' keyword.
   Token get forKeyword;
 
-  /**
-   * Set the token representing the 'for' keyword to the given [token].
-   */
+  /// Set the token representing the 'for' keyword to the given [token].
   void set forKeyword(Token token);
 
-  /**
-   * Return the initialization expression, or `null` if there is no
-   * initialization expression.
-   */
+  /// Return the initialization expression, or `null` if there is no
+  /// initialization expression.
   Expression get initialization;
 
-  /**
-   * Set the initialization expression to the given [expression].
-   */
+  /// Set the initialization expression to the given [expression].
   void set initialization(Expression initialization);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the semicolon separating the initializer and the condition.
-   */
+  /// Return the semicolon separating the initializer and the condition.
   Token get leftSeparator;
 
-  /**
-   * Set the semicolon separating the initializer and the condition to the given
-   * [token].
-   */
+  /// Set the semicolon separating the initializer and the condition to the
+  /// given [token].
   void set leftSeparator(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the semicolon separating the condition and the updater.
-   */
+  /// Return the semicolon separating the condition and the updater.
   Token get rightSeparator;
 
-  /**
-   * Set the semicolon separating the condition and the updater to the given
-   * [token].
-   */
+  /// Set the semicolon separating the condition and the updater to the given
+  /// [token].
   void set rightSeparator(Token token);
 
-  /**
-   * Return the list of expressions run after each execution of the loop body.
-   */
+  /// Return the list of expressions run after each execution of the loop body.
   NodeList<Expression> get updaters;
 
-  /**
-   * Return the declaration of the loop variables, or `null` if there are no
-   * variables.
-   */
+  /// Return the declaration of the loop variables, or `null` if there are no
+  /// variables.
   VariableDeclarationList get variables;
 
-  /**
-   * Set the declaration of the loop variables to the given [variableList].
-   */
+  /// Set the declaration of the loop variables to the given [variableList].
   void set variables(VariableDeclarationList variableList);
 }
 
-/**
- * A for or for-each statement.
- *
- *    forStatement ::=
- *        'for' '(' forLoopParts ')' [Statement]
- *
- *    forLoopParts ::=
- *       [VariableDeclaration] ';' [Expression]? ';' expressionList?
- *     | [Expression]? ';' [Expression]? ';' expressionList?
- *     | [DeclaredIdentifier] 'in' [Expression]
- *     | [SimpleIdentifier] 'in' [Expression]
- *
- * This is the class that is used to represent a for loop when either the
- * 'control-flow-collections' or 'spread-collections' experiments are enabled.
- * If neither of those experiments are enabled, then either [ForStatement] or
- * [ForEachStatement] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ForStatement2 extends Statement {
-  /**
-   * Return the token representing the 'await' keyword, or `null` if there is no
-   * 'await' keyword.
-   */
+/// A for or for-each statement.
+///
+///    forStatement ::=
+///        'for' '(' forLoopParts ')' [Statement]
+///
+///    forLoopParts ::=
+///       [VariableDeclaration] ';' [Expression]? ';' expressionList?
+///     | [Expression]? ';' [Expression]? ';' expressionList?
+///     | [DeclaredIdentifier] 'in' [Expression]
+///     | [SimpleIdentifier] 'in' [Expression]
+///
+/// This is the class that is used to represent a for loop when either the
+/// 'control-flow-collections' or 'spread-collections' experiments are enabled.
+/// If neither of those experiments are enabled, then either [ForStatement] or
+/// [ForEachStatement] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ForStatement2 implements Statement {
+  /// Return the token representing the 'await' keyword, or `null` if there is
+  /// no 'await' keyword.
   Token get awaitKeyword;
 
-  /**
-   * Return the body of the loop.
-   */
+  /// Return the body of the loop.
   Statement get body;
 
-  /**
-   * Return the token representing the 'for' keyword.
-   */
+  /// Return the token representing the 'for' keyword.
   Token get forKeyword;
 
-  /**
-   * Return the parts of the for element that control the iteration.
-   */
+  /// Return the parts of the for element that control the iteration.
   ForLoopParts get forLoopParts;
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 }
 
-/**
- * A node representing the body of a function or method.
- *
- *    functionBody ::=
- *        [BlockFunctionBody]
- *      | [EmptyFunctionBody]
- *      | [ExpressionFunctionBody]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionBody extends AstNode {
-  /**
-   * Return `true` if this function body is asynchronous.
-   */
+/// A node representing the body of a function or method.
+///
+///    functionBody ::=
+///        [BlockFunctionBody]
+///      | [EmptyFunctionBody]
+///      | [ExpressionFunctionBody]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionBody implements AstNode {
+  /// Return `true` if this function body is asynchronous.
   bool get isAsynchronous;
 
-  /**
-   * Return `true` if this function body is a generator.
-   */
+  /// Return `true` if this function body is a generator.
   bool get isGenerator;
 
-  /**
-   * Return `true` if this function body is synchronous.
-   */
+  /// Return `true` if this function body is synchronous.
   bool get isSynchronous;
 
-  /**
-   * Return the token representing the 'async' or 'sync' keyword, or `null` if
-   * there is no such keyword.
-   */
+  /// Return the token representing the 'async' or 'sync' keyword, or `null` if
+  /// there is no such keyword.
   Token get keyword;
 
-  /**
-   * Return the star following the 'async' or 'sync' keyword, or `null` if there
-   * is no star.
-   */
+  /// Return the star following the 'async' or 'sync' keyword, or `null` if
+  /// there is no star.
   Token get star;
 
-  /**
-   * If [variable] is a local variable or parameter declared anywhere within
-   * the top level function or method containing this [FunctionBody], return a
-   * boolean indicating whether [variable] is potentially mutated within a
-   * local function other than the function in which it is declared.
-   *
-   * If [variable] is not a local variable or parameter declared within the top
-   * level function or method containing this [FunctionBody], return `false`.
-   *
-   * Throws an exception if resolution has not yet been performed.
-   */
+  /// If [variable] is a local variable or parameter declared anywhere within
+  /// the top level function or method containing this [FunctionBody], return a
+  /// boolean indicating whether [variable] is potentially mutated within a
+  /// local function other than the function in which it is declared.
+  ///
+  /// If [variable] is not a local variable or parameter declared within the top
+  /// level function or method containing this [FunctionBody], return `false`.
+  ///
+  /// Throws an exception if resolution has not yet been performed.
   bool isPotentiallyMutatedInClosure(VariableElement variable);
 
-  /**
-   * If [variable] is a local variable or parameter declared anywhere within
-   * the top level function or method containing this [FunctionBody], return a
-   * boolean indicating whether [variable] is potentially mutated within the
-   * scope of its declaration.
-   *
-   * If [variable] is not a local variable or parameter declared within the top
-   * level function or method containing this [FunctionBody], return `false`.
-   *
-   * Throws an exception if resolution has not yet been performed.
-   */
+  /// If [variable] is a local variable or parameter declared anywhere within
+  /// the top level function or method containing this [FunctionBody], return a
+  /// boolean indicating whether [variable] is potentially mutated within the
+  /// scope of its declaration.
+  ///
+  /// If [variable] is not a local variable or parameter declared within the top
+  /// level function or method containing this [FunctionBody], return `false`.
+  ///
+  /// Throws an exception if resolution has not yet been performed.
   bool isPotentiallyMutatedInScope(VariableElement variable);
 }
 
-/**
- * A top-level declaration.
- *
- *    functionDeclaration ::=
- *        'external' functionSignature
- *      | functionSignature [FunctionBody]
- *
- *    functionSignature ::=
- *        [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionDeclaration extends NamedCompilationUnitMember {
+/// A top-level function declaration.
+///
+///    functionDeclaration ::=
+///        'external' functionSignature
+///      | functionSignature [FunctionBody]
+///
+///    functionSignature ::=
+///        [Type]? ('get' | 'set')? [SimpleIdentifier] [FormalParameterList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionDeclaration implements NamedCompilationUnitMember {
   @override
   ExecutableElement get declaredElement;
 
@@ -3749,688 +2699,487 @@
   @override
   ExecutableElement get element;
 
-  /**
-   * Return the token representing the 'external' keyword, or `null` if this is
-   * not an external function.
-   */
+  /// Return the token representing the 'external' keyword, or `null` if this is
+  /// not an external function.
   Token get externalKeyword;
 
-  /**
-   * Set the token representing the 'external' keyword to the given [token].
-   */
+  /// Set the token representing the 'external' keyword to the given [token].
   void set externalKeyword(Token token);
 
-  /**
-   * Return the function expression being wrapped.
-   */
+  /// Return the function expression being wrapped.
   FunctionExpression get functionExpression;
 
-  /**
-   * Set the function expression being wrapped to the given
-   * [functionExpression].
-   */
+  /// Set the function expression being wrapped to the given
+  /// [functionExpression].
   void set functionExpression(FunctionExpression functionExpression);
 
-  /**
-   * Return `true` if this function declares a getter.
-   */
+  /// Return `true` if this function declares a getter.
   bool get isGetter;
 
-  /**
-   * Return `true` if this function declares a setter.
-   */
+  /// Return `true` if this function declares a setter.
   bool get isSetter;
 
-  /**
-   * Return the token representing the 'get' or 'set' keyword, or `null` if this
-   * is a function declaration rather than a property declaration.
-   */
+  /// Return the token representing the 'get' or 'set' keyword, or `null` if
+  /// this is a function declaration rather than a property declaration.
   Token get propertyKeyword;
 
-  /**
-   * Set the token representing the 'get' or 'set' keyword to the given [token].
-   */
+  /// Set the token representing the 'get' or 'set' keyword to the given
+  /// [token].
   void set propertyKeyword(Token token);
 
-  /**
-   * Return the return type of the function, or `null` if no return type was
-   * declared.
-   */
+  /// Return the return type of the function, or `null` if no return type was
+  /// declared.
   TypeAnnotation get returnType;
 
-  /**
-   * Set the return type of the function to the given [type].
-   */
+  /// Set the return type of the function to the given [type].
   void set returnType(TypeAnnotation type);
 }
 
-/**
- * A [FunctionDeclaration] used as a statement.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionDeclarationStatement extends Statement {
-  /**
-   * Return the function declaration being wrapped.
-   */
+/// A [FunctionDeclaration] used as a statement.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionDeclarationStatement implements Statement {
+  /// Return the function declaration being wrapped.
   FunctionDeclaration get functionDeclaration;
 
-  /**
-   * Set the function declaration being wrapped to the given
-   * [functionDeclaration].
-   */
+  /// Set the function declaration being wrapped to the given
+  /// [functionDeclaration].
   void set functionDeclaration(FunctionDeclaration functionDeclaration);
 }
 
-/**
- * A function expression.
- *
- *    functionExpression ::=
- *        [TypeParameterList]? [FormalParameterList] [FunctionBody]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionExpression extends Expression {
-  /**
-   * Return the body of the function, or `null` if this is an external function.
-   */
+/// A function expression.
+///
+///    functionExpression ::=
+///        [TypeParameterList]? [FormalParameterList] [FunctionBody]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionExpression implements Expression {
+  /// Return the body of the function, or `null` if this is an external
+  /// function.
   FunctionBody get body;
 
-  /**
-   * Set the body of the function to the given [functionBody].
-   */
+  /// Set the body of the function to the given [functionBody].
   void set body(FunctionBody functionBody);
 
-  /**
-   * Return the element associated with the function, or `null` if the AST
-   * structure has not been resolved.
-   */
+  /// Return the element associated with the function, or `null` if the AST
+  /// structure has not been resolved.
   ExecutableElement get declaredElement;
 
-  /**
-   * Return the element associated with the function, or `null` if the AST
-   * structure has not been resolved.
-   */
+  /// Return the element associated with the function, or `null` if the AST
+  /// structure has not been resolved.
   @deprecated
   ExecutableElement get element;
 
-  /**
-   * Set the element associated with the function to the given [element].
-   */
+  /// Set the element associated with the function to the given [element].
   void set element(ExecutableElement element);
 
-  /**
-   * Return the parameters associated with the function.
-   */
+  /// Return the parameters associated with the function.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters associated with the function to the given list of
-   * [parameters].
-   */
+  /// Set the parameters associated with the function to the given list of
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
+  /// Return the type parameters associated with this method, or `null` if this
+  /// method is not a generic method.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
+  /// Set the type parameters associated with this method to the given
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * The invocation of a function resulting from evaluating an expression.
- * Invocations of methods and other forms of functions are represented by
- * [MethodInvocation] nodes. Invocations of getters and setters are represented
- * by either [PrefixedIdentifier] or [PropertyAccess] nodes.
- *
- *    functionExpressionInvocation ::=
- *        [Expression] [TypeArgumentList]? [ArgumentList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionExpressionInvocation extends InvocationExpression {
-  /**
-   * Set the list of arguments to the method to the given [argumentList].
-   */
+/// The invocation of a function resulting from evaluating an expression.
+/// Invocations of methods and other forms of functions are represented by
+/// [MethodInvocation] nodes. Invocations of getters and setters are represented
+/// by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+///
+///    functionExpressionInvocation ::=
+///        [Expression] [TypeArgumentList]? [ArgumentList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionExpressionInvocation implements InvocationExpression {
+  /// Set the list of arguments to the method to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /**
-   * Return the best element available for the function being invoked. If
-   * resolution was able to find a better element based on type propagation,
-   * that element will be returned. Otherwise, the element found using the
-   * result of static analysis will be returned. If resolution has not been
-   * performed, then `null` will be returned.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Return the best element available for the function being invoked. If
+  /// resolution was able to find a better element based on type propagation,
+  /// that element will be returned. Otherwise, the element found using the
+  /// result of static analysis will be returned. If resolution has not been
+  /// performed, then `null` will be returned.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   ExecutableElement get bestElement;
 
-  /**
-   * Return the expression producing the function being invoked.
-   */
+  /// Return the expression producing the function being invoked.
   @override
   Expression get function;
 
-  /**
-   * Set the expression producing the function being invoked to the given
-   * [expression].
-   */
+  /// Set the expression producing the function being invoked to the given
+  /// [expression].
   void set function(Expression expression);
 
-  /**
-   * Return the element associated with the function being invoked based on
-   * propagated type information, or `null` if the AST structure has not been
-   * resolved or the function could not be resolved.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Return the element associated with the function being invoked based on
+  /// propagated type information, or `null` if the AST structure has not been
+  /// resolved or the function could not be resolved.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   ExecutableElement get propagatedElement;
 
-  /**
-   * Set the element associated with the function being invoked based on
-   * propagated type information to the given [element].
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Set the element associated with the function being invoked based on
+  /// propagated type information to the given [element].
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   void set propagatedElement(ExecutableElement element);
 
-  /**
-   * Return the element associated with the function being invoked based on
-   * static type information, or `null` if the AST structure has not been
-   * resolved or the function could not be resolved.
-   */
+  /// Return the element associated with the function being invoked based on
+  /// static type information, or `null` if the AST structure has not been
+  /// resolved or the function could not be resolved.
   ExecutableElement get staticElement;
 
-  /**
-   * Set the element associated with the function being invoked based on static
-   * type information to the given [element].
-   */
+  /// Set the element associated with the function being invoked based on static
+  /// type information to the given [element].
   void set staticElement(ExecutableElement element);
 
-  /**
-   * Set the type arguments to be applied to the method being invoked to the
-   * given [typeArguments].
-   */
+  /// Set the type arguments to be applied to the method being invoked to the
+  /// given [typeArguments].
   void set typeArguments(TypeArgumentList typeArguments);
 }
 
-/**
- * A function type alias.
- *
- *    functionTypeAlias ::=
- *        functionPrefix [TypeParameterList]? [FormalParameterList] ';'
- *
- *    functionPrefix ::=
- *        [TypeAnnotation]? [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionTypeAlias extends TypeAlias {
-  /**
-   * Return the parameters associated with the function type.
-   */
+/// A function type alias.
+///
+///    functionTypeAlias ::=
+///        functionPrefix [TypeParameterList]? [FormalParameterList] ';'
+///
+///    functionPrefix ::=
+///        [TypeAnnotation]? [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionTypeAlias implements TypeAlias {
+  /// Return the parameters associated with the function type.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters associated with the function type to the given list of
-   * [parameters].
-   */
+  /// Set the parameters associated with the function type to the given list of
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the return type of the function type being defined, or `null` if no
-   * return type was given.
-   */
+  /// Return the return type of the function type being defined, or `null` if no
+  /// return type was given.
   TypeAnnotation get returnType;
 
-  /**
-   * Set the return type of the function type being defined to the given [type].
-   */
+  /// Set the return type of the function type being defined to the given
+  /// [type].
   void set returnType(TypeAnnotation type);
 
-  /**
-   * Return the type parameters for the function type, or `null` if the function
-   * type does not have any type parameters.
-   */
+  /// Return the type parameters for the function type, or `null` if the
+  /// function type does not have any type parameters.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters for the function type to the given list of
-   * [typeParameters].
-   */
+  /// Set the type parameters for the function type to the given list of
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * A function-typed formal parameter.
- *
- *    functionSignature ::=
- *        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class FunctionTypedFormalParameter extends NormalFormalParameter {
-  /**
-   * Return the parameters of the function-typed parameter.
-   */
+/// A function-typed formal parameter.
+///
+///    functionSignature ::=
+///        [TypeAnnotation]? [SimpleIdentifier] [TypeParameterList]? [FormalParameterList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class FunctionTypedFormalParameter implements NormalFormalParameter {
+  /// Return the parameters of the function-typed parameter.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters of the function-typed parameter to the given
-   * [parameters].
-   */
+  /// Set the parameters of the function-typed parameter to the given
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the return type of the function, or `null` if the function does not
-   * have a return type.
-   */
+  /// Return the return type of the function, or `null` if the function does not
+  /// have a return type.
   TypeAnnotation get returnType;
 
-  /**
-   * Set the return type of the function to the given [type].
-   */
+  /// Set the return type of the function to the given [type].
   void set returnType(TypeAnnotation type);
 
-  /**
-   * Return the type parameters associated with this function, or `null` if
-   * this function is not a generic function.
-   */
+  /// Return the type parameters associated with this function, or `null` if
+  /// this function is not a generic function.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
+  /// Set the type parameters associated with this method to the given
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * An anonymous function type.
- *
- *    functionType ::=
- *        [TypeAnnotation]? 'Function' [TypeParameterList]?
- *        [FormalParameterList] '?'?
- *
- * where the FormalParameterList is being used to represent the following
- * grammar, despite the fact that FormalParameterList can represent a much
- * larger grammar than the one below. This is done in order to simplify the
- * implementation.
- *
- *    parameterTypeList ::=
- *        () |
- *        ( normalParameterTypes ,? ) |
- *        ( normalParameterTypes , optionalParameterTypes ) |
- *        ( optionalParameterTypes )
- *    namedParameterTypes ::=
- *        { namedParameterType (, namedParameterType)* ,? }
- *    namedParameterType ::=
- *        [TypeAnnotation]? [SimpleIdentifier]
- *    normalParameterTypes ::=
- *        normalParameterType (, normalParameterType)*
- *    normalParameterType ::=
- *        [TypeAnnotation] [SimpleIdentifier]?
- *    optionalParameterTypes ::=
- *        optionalPositionalParameterTypes | namedParameterTypes
- *    optionalPositionalParameterTypes ::=
- *        [ normalParameterTypes ,? ]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class GenericFunctionType extends TypeAnnotation {
-  /**
-   * Return the keyword 'Function'.
-   */
+/// An anonymous function type.
+///
+///    functionType ::=
+///        [TypeAnnotation]? 'Function' [TypeParameterList]?
+///        [FormalParameterList] '?'?
+///
+/// where the FormalParameterList is being used to represent the following
+/// grammar, despite the fact that FormalParameterList can represent a much
+/// larger grammar than the one below. This is done in order to simplify the
+/// implementation.
+///
+///    parameterTypeList ::=
+///        () |
+///        ( normalParameterTypes ,? ) |
+///        ( normalParameterTypes , optionalParameterTypes ) |
+///        ( optionalParameterTypes )
+///    namedParameterTypes ::=
+///        { namedParameterType (, namedParameterType)* ,? }
+///    namedParameterType ::=
+///        [TypeAnnotation]? [SimpleIdentifier]
+///    normalParameterTypes ::=
+///        normalParameterType (, normalParameterType)*
+///    normalParameterType ::=
+///        [TypeAnnotation] [SimpleIdentifier]?
+///    optionalParameterTypes ::=
+///        optionalPositionalParameterTypes | namedParameterTypes
+///    optionalPositionalParameterTypes ::=
+///        [ normalParameterTypes ,? ]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class GenericFunctionType implements TypeAnnotation {
+  /// Return the keyword 'Function'.
   Token get functionKeyword;
 
-  /**
-   * Set the keyword 'Function' to the given [token].
-   */
+  /// Set the keyword 'Function' to the given [token].
   void set functionKeyword(Token token);
 
-  /**
-   * Return the parameters associated with the function type.
-   */
+  /// Return the parameters associated with the function type.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters associated with the function type to the given list of
-   * [parameters].
-   */
+  /// Set the parameters associated with the function type to the given list of
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * The question mark indicating that the type is nullable, or `null` if there
-   * is no question mark.
-   */
-  Token get question;
-
-  /**
-   * Set the question mark indicating that the type is nullable to the given
-   * [token].
-   */
+  /// Set the question mark indicating that the type is nullable to the given
+  /// [token].
   void set question(Token token);
 
-  /**
-   * Return the return type of the function type being defined, or `null` if
-   * no return type was given.
-   */
+  /// Return the return type of the function type being defined, or `null` if
+  /// no return type was given.
   TypeAnnotation get returnType;
 
-  /**
-   * Set the return type of the function type being defined to the given[type].
-   */
+  /// Set the return type of the function type being defined to the given[type].
   void set returnType(TypeAnnotation type);
 
-  /**
-   * Return the type parameters for the function type, or `null` if the function
-   * type does not have any type parameters.
-   */
+  /// Return the type parameters for the function type, or `null` if the
+  /// function type does not have any type parameters.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters for the function type to the given list of
-   * [typeParameters].
-   */
+  /// Set the type parameters for the function type to the given list of
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * A generic type alias.
- *
- *    functionTypeAlias ::=
- *        metadata 'typedef' [SimpleIdentifier] [TypeParameterList]? = [FunctionType] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class GenericTypeAlias extends TypeAlias {
-  /**
-     * Return the equal sign separating the name being defined from the function
-     * type.
-     */
+/// A generic type alias.
+///
+///    functionTypeAlias ::=
+///        metadata 'typedef' [SimpleIdentifier] [TypeParameterList]? = [FunctionType] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class GenericTypeAlias implements TypeAlias {
+  /// Return the equal sign separating the name being defined from the function
+  /// type.
   Token get equals;
 
-  /**
-     * Set the equal sign separating the name being defined from the function type
-     * to the given [token].
-     */
+  /// Set the equal sign separating the name being defined from the function
+  /// type to the given [token].
   void set equals(Token token);
 
-  /**
-     * Return the type of function being defined by the alias.
-     */
+  /// Return the type of function being defined by the alias.
   GenericFunctionType get functionType;
 
-  /**
-     * Set the type of function being defined by the alias to the given
-     * [functionType].
-     */
+  /// Set the type of function being defined by the alias to the given
+  /// [functionType].
   void set functionType(GenericFunctionType functionType);
 
-  /**
-     * Return the type parameters for the function type, or `null` if the function
-     * type does not have any type parameters.
-     */
+  /// Return the type parameters for the function type, or `null` if the
+  /// function type does not have any type parameters.
   TypeParameterList get typeParameters;
 
-  /**
-     * Set the type parameters for the function type to the given list of
-     * [typeParameters].
-     */
+  /// Set the type parameters for the function type to the given list of
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * A combinator that restricts the names being imported to those that are not in
- * a given list.
- *
- *    hideCombinator ::=
- *        'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class HideCombinator extends Combinator {
-  /**
-   * Return the list of names from the library that are hidden by this
-   * combinator.
-   */
+/// A combinator that restricts the names being imported to those that are not
+/// in a given list.
+///
+///    hideCombinator ::=
+///        'hide' [SimpleIdentifier] (',' [SimpleIdentifier])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class HideCombinator implements Combinator {
+  /// Return the list of names from the library that are hidden by this
+  /// combinator.
   NodeList<SimpleIdentifier> get hiddenNames;
 }
 
-/**
- * A node that represents an identifier.
- *
- *    identifier ::=
- *        [SimpleIdentifier]
- *      | [PrefixedIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Identifier extends Expression {
-  /**
-   * Return the best element available for this operator. If resolution was able
-   * to find a better element based on type propagation, that element will be
-   * returned. Otherwise, the element found using the result of static analysis
-   * will be returned. If resolution has not been performed, then `null` will be
-   * returned.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+/// A node that represents an identifier.
+///
+///    identifier ::=
+///        [SimpleIdentifier]
+///      | [PrefixedIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Identifier implements Expression {
+  /// Return the best element available for this operator. If resolution was
+  /// able to find a better element based on type propagation, that element will
+  /// be returned. Otherwise, the element found using the result of static
+  /// analysis will be returned. If resolution has not been performed, then
+  /// `null` will be returned.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   Element get bestElement;
 
-  /**
-   * Return the lexical representation of the identifier.
-   */
+  /// Return the lexical representation of the identifier.
   String get name;
 
-  /**
-   * Return the element associated with this identifier based on propagated type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved. One example of the latter case is an
-   * identifier that is not defined within the scope in which it appears.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Return the element associated with this identifier based on propagated
+  /// type information, or `null` if the AST structure has not been resolved or
+  /// if this identifier could not be resolved. One example of the latter case
+  /// is an identifier that is not defined within the scope in which it appears.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   Element get propagatedElement;
 
-  /**
-   * Return the element associated with this identifier based on static type
-   * information, or `null` if the AST structure has not been resolved or if
-   * this identifier could not be resolved. One example of the latter case is an
-   * identifier that is not defined within the scope in which it appears
-   */
+  /// Return the element associated with this identifier based on static type
+  /// information, or `null` if the AST structure has not been resolved or if
+  /// this identifier could not be resolved. One example of the latter case is
+  /// an identifier that is not defined within the scope in which it appears.
   Element get staticElement;
 
-  /**
-   * Return `true` if the given [name] is visible only within the library in
-   * which it is declared.
-   */
+  /// Return `true` if the given [name] is visible only within the library in
+  /// which it is declared.
   static bool isPrivateName(String name) =>
       StringUtilities.startsWithChar(name, 0x5F); // '_'
 }
 
-/**
- * The basic structure of an if element.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class IfElement<E> implements AstNode {
-  /**
-   * Return the condition used to determine which of the statements is executed
-   * next.
-   */
+/// The basic structure of an if element.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class IfElement implements CollectionElement {
+  /// Return the condition used to determine which of the statements is executed
+  /// next.
   Expression get condition;
 
-  /**
-   * Return the statement that is executed if the condition evaluates to
-   * `false`, or `null` if there is no else statement.
-   */
-  E get elseElement;
+  /// Return the statement that is executed if the condition evaluates to
+  /// `false`, or `null` if there is no else statement.
+  CollectionElement get elseElement;
 
-  /**
-   * Return the token representing the 'else' keyword, or `null` if there is no
-   * else statement.
-   */
+  /// Return the token representing the 'else' keyword, or `null` if there is no
+  /// else statement.
   Token get elseKeyword;
 
-  /**
-   * Return the token representing the 'if' keyword.
-   */
+  /// Return the token representing the 'if' keyword.
   Token get ifKeyword;
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Return the statement that is executed if the condition evaluates to `true`.
-   */
-  E get thenElement;
+  /// Return the statement that is executed if the condition evaluates to
+  /// `true`.
+  CollectionElement get thenElement;
 }
 
-/**
- * An if statement.
- *
- *    ifStatement ::=
- *        'if' '(' [Expression] ')' [Statement] ('else' [Statement])?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class IfStatement extends Statement {
-  /**
-   * Return the condition used to determine which of the statements is executed
-   * next.
-   */
+/// An if statement.
+///
+///    ifStatement ::=
+///        'if' '(' [Expression] ')' [Statement] ('else' [Statement])?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class IfStatement implements Statement {
+  /// Return the condition used to determine which of the statements is executed
+  /// next.
   Expression get condition;
 
-  /**
-   * Set the condition used to determine which of the statements is executed
-   * next to the given [expression].
-   */
+  /// Set the condition used to determine which of the statements is executed
+  /// next to the given [expression].
   void set condition(Expression expression);
 
-  /**
-   * Return the token representing the 'else' keyword, or `null` if there is no
-   * else statement.
-   */
+  /// Return the token representing the 'else' keyword, or `null` if there is no
+  /// else statement.
   Token get elseKeyword;
 
-  /**
-   * Set the token representing the 'else' keyword to the given [token].
-   */
+  /// Set the token representing the 'else' keyword to the given [token].
   void set elseKeyword(Token token);
 
-  /**
-   * Return the statement that is executed if the condition evaluates to
-   * `false`, or `null` if there is no else statement.
-   */
+  /// Return the statement that is executed if the condition evaluates to
+  /// `false`, or `null` if there is no else statement.
   Statement get elseStatement;
 
-  /**
-   * Set the statement that is executed if the condition evaluates to `false`
-   * to the given [statement].
-   */
+  /// Set the statement that is executed if the condition evaluates to `false`
+  /// to the given [statement].
   void set elseStatement(Statement statement);
 
-  /**
-   * Return the token representing the 'if' keyword.
-   */
+  /// Return the token representing the 'if' keyword.
   Token get ifKeyword;
 
-  /**
-   * Set the token representing the 'if' keyword to the given [token].
-   */
+  /// Set the token representing the 'if' keyword to the given [token].
   void set ifKeyword(Token token);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the statement that is executed if the condition evaluates to `true`.
-   */
+  /// Return the statement that is executed if the condition evaluates to
+  /// `true`.
   Statement get thenStatement;
 
-  /**
-   * Set the statement that is executed if the condition evaluates to `true` to
-   * the given [statement].
-   */
+  /// Set the statement that is executed if the condition evaluates to `true` to
+  /// the given [statement].
   void set thenStatement(Statement statement);
 }
 
-/**
- * The "implements" clause in an class declaration.
- *
- *    implementsClause ::=
- *        'implements' [TypeName] (',' [TypeName])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ImplementsClause extends AstNode {
-  /**
-   * Return the token representing the 'implements' keyword.
-   */
+/// The "implements" clause in an class declaration.
+///
+///    implementsClause ::=
+///        'implements' [TypeName] (',' [TypeName])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ImplementsClause implements AstNode {
+  /// Return the token representing the 'implements' keyword.
   Token get implementsKeyword;
 
-  /**
-   * Set the token representing the 'implements' keyword to the given [token].
-   */
+  /// Set the token representing the 'implements' keyword to the given [token].
   void set implementsKeyword(Token token);
 
-  /**
-   * Return the list of the interfaces that are being implemented.
-   */
+  /// Return the list of the interfaces that are being implemented.
   NodeList<TypeName> get interfaces;
 }
 
-/**
- * An import directive.
- *
- *    importDirective ::=
- *        [Annotation] 'import' [StringLiteral] ('as' identifier)? [Combinator]* ';'
- *      | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ImportDirective extends NamespaceDirective {
+/// An import directive.
+///
+///    importDirective ::=
+///        [Annotation] 'import' [StringLiteral] ('as' identifier)? [Combinator]* ';'
+///      | [Annotation] 'import' [StringLiteral] 'deferred' 'as' identifier [Combinator]* ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ImportDirective implements NamespaceDirective {
   static Comparator<ImportDirective> COMPARATOR =
       (ImportDirective import1, ImportDirective import2) {
     //
@@ -4536,859 +3285,592 @@
     }
     return 0;
   };
-  /**
-   * Return the token representing the 'as' keyword, or `null` if the imported
-   * names are not prefixed.
-   */
+
+  /// Return the token representing the 'as' keyword, or `null` if the imported
+  /// names are not prefixed.
   Token get asKeyword;
 
-  /**
-   * Set the token representing the 'as' keyword to the given [token].
-   */
+  /// Set the token representing the 'as' keyword to the given [token].
   void set asKeyword(Token token);
 
-  /**
-   * Return the token representing the 'deferred' keyword, or `null` if the
-   * imported URI is not deferred.
-   */
+  /// Return the token representing the 'deferred' keyword, or `null` if the
+  /// imported URI is not deferred.
   Token get deferredKeyword;
 
-  /**
-   * Set the token representing the 'deferred' keyword to the given [token].
-   */
+  /// Set the token representing the 'deferred' keyword to the given [token].
   void set deferredKeyword(Token token);
 
-  /**
-   * Return the prefix to be used with the imported names, or `null` if the
-   * imported names are not prefixed.
-   */
+  /// Return the prefix to be used with the imported names, or `null` if the
+  /// imported names are not prefixed.
   SimpleIdentifier get prefix;
 
-  /**
-   * Set the prefix to be used with the imported names to the given [identifier].
-   */
+  /// Set the prefix to be used with the imported names to the given
+  /// [identifier].
   void set prefix(SimpleIdentifier identifier);
 }
 
-/**
- * An index expression.
- *
- *    indexExpression ::=
- *        [Expression] '[' [Expression] ']'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class IndexExpression extends Expression
-    implements MethodReferenceExpression {
-  /**
-   * Return the auxiliary elements associated with this identifier, or `null` if
-   * this identifier is not in both a getter and setter context. The auxiliary
-   * elements hold the static and propagated elements associated with the getter
-   * context.
-   */
+/// An index expression.
+///
+///    indexExpression ::=
+///        [Expression] '[' [Expression] ']'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class IndexExpression
+    implements Expression, MethodReferenceExpression {
+  /// Return the auxiliary elements associated with this identifier, or `null`
+  /// if this identifier is not in both a getter and setter context. The
+  /// auxiliary elements hold the static and propagated elements associated with
+  /// the getter context.
   // TODO(brianwilkerson) Replace this API.
   AuxiliaryElements get auxiliaryElements;
 
-  /**
-   * Set the auxiliary elements associated with this identifier to the given
-   * [elements].
-   */
+  /// Set the auxiliary elements associated with this identifier to the given
+  /// [elements].
   // TODO(brianwilkerson) Replace this API.
   void set auxiliaryElements(AuxiliaryElements elements);
 
-  /**
-   * Return the expression used to compute the index.
-   */
+  /// Return the expression used to compute the index.
   Expression get index;
 
-  /**
-   * Set the expression used to compute the index to the given [expression].
-   */
+  /// Set the expression used to compute the index to the given [expression].
   void set index(Expression expression);
 
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
+  /// Return `true` if this expression is cascaded. If it is, then the target of
+  /// this expression is not stored locally but is stored in the nearest
+  /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
-  /**
-   * Return the left square bracket.
-   */
+  /// Return the left square bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left square bracket to the given [token].
-   */
+  /// Set the left square bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the period ("..") before a cascaded index expression, or `null` if
-   * this index expression is not part of a cascade expression.
-   */
+  /// Return the period ("..") before a cascaded index expression, or `null` if
+  /// this index expression is not part of a cascade expression.
   Token get period;
 
-  /**
-   * Set the period ("..") before a cascaded index expression to the given
-   * [token].
-   */
+  /// Set the period ("..") before a cascaded index expression to the given
+  /// [token].
   void set period(Token token);
 
-  /**
-   * Return the expression used to compute the object being indexed. If this
-   * index expression is not part of a cascade expression, then this is the same
-   * as [target]. If this index expression is part of a cascade expression, then
-   * the target expression stored with the cascade expression is returned.
-   */
+  /// Return the expression used to compute the object being indexed. If this
+  /// index expression is not part of a cascade expression, then this is the
+  /// same as [target]. If this index expression is part of a cascade
+  /// expression, then the target expression stored with the cascade expression
+  /// is returned.
   Expression get realTarget;
 
-  /**
-   * Return the right square bracket.
-   */
+  /// Return the right square bracket.
   Token get rightBracket;
 
-  /**
-   * Return the expression used to compute the object being indexed, or `null`
-   * if this index expression is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
+  /// Return the expression used to compute the object being indexed, or `null`
+  /// if this index expression is part of a cascade expression.
+  ///
+  /// Use [realTarget] to get the target independent of whether this is part of
+  /// a cascade expression.
   Expression get target;
 
-  /**
-   * Set the expression used to compute the object being indexed to the given
-   * [expression].
-   */
+  /// Set the expression used to compute the object being indexed to the given
+  /// [expression].
   void set target(Expression expression);
 
-  /**
-   * Return `true` if this expression is computing a right-hand value (that is,
-   * if this expression is in a context where the operator '[]' will be
-   * invoked).
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
+  /// Return `true` if this expression is computing a right-hand value (that is,
+  /// if this expression is in a context where the operator '[]' will be
+  /// invoked).
+  ///
+  /// Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+  /// are they mutually exclusive. In other words, it is possible for both
+  /// methods to return `true` when invoked on the same node.
   // TODO(brianwilkerson) Convert this to a getter.
   bool inGetterContext();
 
-  /**
-   * Return `true` if this expression is computing a left-hand value (that is,
-   * if this expression is in a context where the operator '[]=' will be
-   * invoked).
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
+  /// Return `true` if this expression is computing a left-hand value (that is,
+  /// if this expression is in a context where the operator '[]=' will be
+  /// invoked).
+  ///
+  /// Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+  /// are they mutually exclusive. In other words, it is possible for both
+  /// methods to return `true` when invoked on the same node.
   // TODO(brianwilkerson) Convert this to a getter.
   bool inSetterContext();
 }
 
-/**
- * An instance creation expression.
- *
- *    newExpression ::=
- *        ('new' | 'const')? [TypeName] ('.' [SimpleIdentifier])? [ArgumentList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class InstanceCreationExpression extends Expression
-    implements ConstructorReferenceNode {
-  /**
-   * Return the list of arguments to the constructor.
-   */
+/// An instance creation expression.
+///
+///    newExpression ::=
+///        ('new' | 'const')? [TypeName] ('.' [SimpleIdentifier])? [ArgumentList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class InstanceCreationExpression
+    implements Expression, ConstructorReferenceNode {
+  /// Return the list of arguments to the constructor.
   ArgumentList get argumentList;
 
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
+  /// Set the list of arguments to the constructor to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /**
-   * Return the name of the constructor to be invoked.
-   */
+  /// Return the name of the constructor to be invoked.
   ConstructorName get constructorName;
 
-  /**
-   * Set the name of the constructor to be invoked to the given [name].
-   */
+  /// Set the name of the constructor to be invoked to the given [name].
   void set constructorName(ConstructorName name);
 
-  /**
-   * Return `true` if this creation expression is used to invoke a constant
-   * constructor, either because the keyword `const` was explicitly provided or
-   * because no keyword was provided and this expression is in a constant
-   * context.
-   */
+  /// Return `true` if this creation expression is used to invoke a constant
+  /// constructor, either because the keyword `const` was explicitly provided or
+  /// because no keyword was provided and this expression is in a constant
+  /// context.
   bool get isConst;
 
-  /**
-   * Return the 'new' or 'const' keyword used to indicate how an object should
-   * be created, or `null` if the keyword was not explicitly provided.
-   */
+  /// Return the 'new' or 'const' keyword used to indicate how an object should
+  /// be created, or `null` if the keyword was not explicitly provided.
   Token get keyword;
 
-  /**
-   * Set the 'new' or 'const' keyword used to indicate how an object should be
-   * created to the given [token].
-   */
+  /// Set the 'new' or 'const' keyword used to indicate how an object should be
+  /// created to the given [token].
   void set keyword(Token token);
 }
 
-/**
- * An integer literal expression.
- *
- *    integerLiteral ::=
- *        decimalIntegerLiteral
- *      | hexadecimalIntegerLiteral
- *
- *    decimalIntegerLiteral ::=
- *        decimalDigit+
- *
- *    hexadecimalIntegerLiteral ::=
- *        '0x' hexadecimalDigit+
- *      | '0X' hexadecimalDigit+
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class IntegerLiteral extends Literal {
-  /**
-   * Return the token representing the literal.
-   */
+/// An integer literal expression.
+///
+///    integerLiteral ::=
+///        decimalIntegerLiteral
+///      | hexadecimalIntegerLiteral
+///
+///    decimalIntegerLiteral ::=
+///        decimalDigit+
+///
+///    hexadecimalIntegerLiteral ::=
+///        '0x' hexadecimalDigit+
+///      | '0X' hexadecimalDigit+
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class IntegerLiteral implements Literal {
+  /// Return the token representing the literal.
   Token get literal;
 
-  /**
-   * Set the token representing the literal to the given [token].
-   */
+  /// Set the token representing the literal to the given [token].
   void set literal(Token token);
 
-  /**
-   * Return the value of the literal.
-   */
+  /// Return the value of the literal.
   int get value;
 
-  /**
-   * Set the value of the literal to the given [value].
-   */
+  /// Set the value of the literal to the given [value].
   void set value(int value);
 }
 
-/**
- * A node within a [StringInterpolation].
- *
- *    interpolationElement ::=
- *        [InterpolationExpression]
- *      | [InterpolationString]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class InterpolationElement extends AstNode {}
+/// A node within a [StringInterpolation].
+///
+///    interpolationElement ::=
+///        [InterpolationExpression]
+///      | [InterpolationString]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class InterpolationElement implements AstNode {}
 
-/**
- * An expression embedded in a string interpolation.
- *
- *    interpolationExpression ::=
- *        '$' [SimpleIdentifier]
- *      | '$' '{' [Expression] '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class InterpolationExpression extends InterpolationElement {
-  /**
-   * Return the expression to be evaluated for the value to be converted into a
-   * string.
-   */
+/// An expression embedded in a string interpolation.
+///
+///    interpolationExpression ::=
+///        '$' [SimpleIdentifier]
+///      | '$' '{' [Expression] '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class InterpolationExpression implements InterpolationElement {
+  /// Return the expression to be evaluated for the value to be converted into a
+  /// string.
   Expression get expression;
 
-  /**
-   * Set the expression to be evaluated for the value to be converted into a
-   * string to the given [expression].
-   */
+  /// Set the expression to be evaluated for the value to be converted into a
+  /// string to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the token used to introduce the interpolation expression; either '$'
-   * if the expression is a simple identifier or '${' if the expression is a
-   * full expression.
-   */
+  /// Return the token used to introduce the interpolation expression; either
+  /// '$' if the expression is a simple identifier or '${' if the expression is
+  /// a full expression.
   Token get leftBracket;
 
-  /**
-   * Set the token used to introduce the interpolation expression; either '$'
-   * if the expression is a simple identifier or '${' if the expression is a
-   * full expression to the given [token].
-   */
+  /// Set the token used to introduce the interpolation expression; either '$'
+  /// if the expression is a simple identifier or '${' if the expression is a
+  /// full expression to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket, or `null` if the expression is an
-   * identifier without brackets.
-   */
+  /// Return the right curly bracket, or `null` if the expression is an
+  /// identifier without brackets.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A non-empty substring of an interpolated string.
- *
- *    interpolationString ::=
- *        characters
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class InterpolationString extends InterpolationElement {
-  /**
-   * Return the characters that will be added to the string.
-   */
+/// A non-empty substring of an interpolated string.
+///
+///    interpolationString ::=
+///        characters
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class InterpolationString implements InterpolationElement {
+  /// Return the characters that will be added to the string.
   Token get contents;
 
-  /**
-   * Set the characters that will be added to the string to the given [token].
-   */
+  /// Set the characters that will be added to the string to the given [token].
   void set contents(Token token);
 
-  /**
-   * Return the offset of the after-last contents character.
-   */
+  /// Return the offset of the after-last contents character.
   int get contentsEnd;
 
-  /**
-   * Return the offset of the first contents character.
-   */
+  /// Return the offset of the first contents character.
   int get contentsOffset;
 
-  /**
-   * Return the value of the literal.
-   */
+  /// Return the value of the literal.
   String get value;
 
-  /**
-   * Set the value of the literal to the given [value].
-   */
+  /// Set the value of the literal to the given [value].
   void set value(String value);
 }
 
-/**
- * The invocation of a function or method; either a
- * [FunctionExpressionInvocation] or a [MethodInvocation].
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class InvocationExpression extends Expression {
-  /**
-   * Return the list of arguments to the method.
-   */
+/// The invocation of a function or method; either a
+/// [FunctionExpressionInvocation] or a [MethodInvocation].
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class InvocationExpression implements Expression {
+  /// Return the list of arguments to the method.
   ArgumentList get argumentList;
 
-  /**
-   * The expression that identifies the function or method being invoked.
-   * For example:
-   *
-   *     (o.m)<TArgs>(args); // target will be `o.m`
-   *     o.m<TArgs>(args);   // target will be `m`
-   *
-   * In either case, the [function.staticType] will be the
-   * [staticInvokeType] before applying type arguments `TArgs`.
-   */
+  /// The expression that identifies the function or method being invoked.
+  /// For example:
+  ///
+  ///     (o.m)<TArgs>(args); // target will be `o.m`
+  ///     o.m<TArgs>(args);   // target will be `m`
+  ///
+  /// In either case, the [function.staticType] will be the
+  /// [staticInvokeType] before applying type arguments `TArgs`.
   Expression get function;
 
-  /**
-   * Return the function type of the invocation based on the propagated type
-   * information, or `null` if the AST structure has not been resolved, or if
-   * the invoke could not be resolved.
-   *
-   * This will usually be a [FunctionType], but it can also be an
-   * [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
-   * interface type that implements `Function`.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticInvokeType] instead.
-   */
+  /// Return the function type of the invocation based on the propagated type
+  /// information, or `null` if the AST structure has not been resolved, or if
+  /// the invoke could not be resolved.
+  ///
+  /// This will usually be a [FunctionType], but it can also be an
+  /// [InterfaceType] with a `call` method, `dynamic`, `Function`, or a `@proxy`
+  /// interface type that implements `Function`.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticInvokeType] instead.
   @deprecated
   DartType get propagatedInvokeType;
 
-  /**
-   * Sets the function type of the invocation based on the propagated type
-   * information.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticInvokeType] instead.
-   */
+  /// Sets the function type of the invocation based on the propagated type
+  /// information.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticInvokeType] instead.
   @deprecated
   void set propagatedInvokeType(DartType value);
 
-  /**
-   * Return the function type of the invocation based on the static type
-   * information, or `null` if the AST structure has not been resolved, or if
-   * the invoke could not be resolved.
-   *
-   * This will usually be a [FunctionType], but it can also be `dynamic` or
-   * `Function`. In the case of interface types that have a `call` method, we
-   * store the type of that `call` method here as parameterized.
-   */
+  /// Return the function type of the invocation based on the static type
+  /// information, or `null` if the AST structure has not been resolved, or if
+  /// the invoke could not be resolved.
+  ///
+  /// This will usually be a [FunctionType], but it can also be `dynamic` or
+  /// `Function`. In the case of interface types that have a `call` method, we
+  /// store the type of that `call` method here as parameterized.
   DartType get staticInvokeType;
 
-  /**
-   * Sets the function type of the invocation based on the static type
-   * information.
-   */
+  /// Sets the function type of the invocation based on the static type
+  /// information.
   void set staticInvokeType(DartType value);
 
-  /**
-   * Return the type arguments to be applied to the method being invoked, or
-   * `null` if no type arguments were provided.
-   */
+  /// Return the type arguments to be applied to the method being invoked, or
+  /// `null` if no type arguments were provided.
   TypeArgumentList get typeArguments;
 }
 
-/**
- * An is expression.
- *
- *    isExpression ::=
- *        [Expression] 'is' '!'? [TypeAnnotation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class IsExpression extends Expression {
-  /**
-   * Return the expression used to compute the value whose type is being tested.
-   */
+/// An is expression.
+///
+///    isExpression ::=
+///        [Expression] 'is' '!'? [TypeAnnotation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class IsExpression implements Expression {
+  /// Return the expression used to compute the value whose type is being
+  /// tested.
   Expression get expression;
 
-  /**
-   * Set the expression used to compute the value whose type is being tested to
-   * the given [expression].
-   */
+  /// Set the expression used to compute the value whose type is being tested to
+  /// the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the is operator.
-   */
+  /// Return the is operator.
   Token get isOperator;
 
-  /**
-   * Set the is operator to the given [token].
-   */
+  /// Set the is operator to the given [token].
   void set isOperator(Token token);
 
-  /**
-   * Return the not operator, or `null` if the sense of the test is not negated.
-   */
+  /// Return the not operator, or `null` if the sense of the test is not
+  /// negated.
   Token get notOperator;
 
-  /**
-   * Set the not operator to the given [token].
-   */
+  /// Set the not operator to the given [token].
   void set notOperator(Token token);
 
-  /**
-   * Return the type being tested for.
-   */
+  /// Return the type being tested for.
   TypeAnnotation get type;
 
-  /**
-   * Set the type being tested for to the given [type].
-   */
+  /// Set the type being tested for to the given [type].
   void set type(TypeAnnotation type);
 }
 
-/**
- * A label on either a [LabeledStatement] or a [NamedExpression].
- *
- *    label ::=
- *        [SimpleIdentifier] ':'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Label extends AstNode {
-  /**
-   * Return the colon that separates the label from the statement.
-   */
+/// A label on either a [LabeledStatement] or a [NamedExpression].
+///
+///    label ::=
+///        [SimpleIdentifier] ':'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Label implements AstNode {
+  /// Return the colon that separates the label from the statement.
   Token get colon;
 
-  /**
-   * Set the colon that separates the label from the statement to the given
-   * [token].
-   */
+  /// Set the colon that separates the label from the statement to the given
+  /// [token].
   void set colon(Token token);
 
-  /**
-   * Return the label being associated with the statement.
-   */
+  /// Return the label being associated with the statement.
   SimpleIdentifier get label;
 
-  /**
-   * Set the label being associated with the statement to the given [label].
-   */
+  /// Set the label being associated with the statement to the given [label].
   void set label(SimpleIdentifier label);
 }
 
-/**
- * A statement that has a label associated with them.
- *
- *    labeledStatement ::=
- *       [Label]+ [Statement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class LabeledStatement extends Statement {
-  /**
-   * Return the labels being associated with the statement.
-   */
+/// A statement that has a label associated with them.
+///
+///    labeledStatement ::=
+///       [Label]+ [Statement]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class LabeledStatement implements Statement {
+  /// Return the labels being associated with the statement.
   NodeList<Label> get labels;
 
-  /**
-   * Return the statement with which the labels are being associated.
-   */
+  /// Return the statement with which the labels are being associated.
   Statement get statement;
 
-  /**
-   * Set the statement with which the labels are being associated to the given
-   * [statement].
-   */
+  /// Set the statement with which the labels are being associated to the given
+  /// [statement].
   void set statement(Statement statement);
 }
 
-/**
- * A library directive.
- *
- *    libraryDirective ::=
- *        [Annotation] 'library' [Identifier] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class LibraryDirective extends Directive {
-  /**
-   * Return the token representing the 'library' keyword.
-   */
+/// A library directive.
+///
+///    libraryDirective ::=
+///        [Annotation] 'library' [Identifier] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class LibraryDirective implements Directive {
+  /// Return the token representing the 'library' keyword.
   Token get libraryKeyword;
 
-  /**
-   * Set the token representing the 'library' keyword to the given [token].
-   */
+  /// Set the token representing the 'library' keyword to the given [token].
   void set libraryKeyword(Token token);
 
-  /**
-   * Return the name of the library being defined.
-   */
+  /// Return the name of the library being defined.
   LibraryIdentifier get name;
 
-  /**
-   * Set the name of the library being defined to the given [name].
-   */
+  /// Set the name of the library being defined to the given [name].
   void set name(LibraryIdentifier name);
 
-  /**
-   * Return the semicolon terminating the directive.
-   */
+  /// Return the semicolon terminating the directive.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the directive to the given [token].
-   */
+  /// Set the semicolon terminating the directive to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * The identifier for a library.
- *
- *    libraryIdentifier ::=
- *        [SimpleIdentifier] ('.' [SimpleIdentifier])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class LibraryIdentifier extends Identifier {
-  /**
-   * Return the components of the identifier.
-   */
+/// The identifier for a library.
+///
+///    libraryIdentifier ::=
+///        [SimpleIdentifier] ('.' [SimpleIdentifier])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class LibraryIdentifier implements Identifier {
+  /// Return the components of the identifier.
   NodeList<SimpleIdentifier> get components;
 }
 
-/**
- * A list literal.
- *
- *    listLiteral ::=
- *        'const'? ('<' [TypeAnnotation] '>')? '[' ([Expression] ','?)? ']'
- *
- * This is the class that is used to represent a list literal when neither the
- * 'control-flow-collections' nor 'spread-collections' experiments are enabled.
- * If either of those experiments are enabled, then [ListLiteral2] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ListLiteral extends TypedLiteral {
-  /**
-   * Return the expressions used to compute the elements of the list.
-   */
+/// A list literal.
+///
+///    listLiteral ::=
+///        'const'? ('<' [TypeAnnotation] '>')? '[' ([Expression] ','?)? ']'
+///
+/// This is the class that is used to represent a list literal when neither the
+/// 'control-flow-collections' nor 'spread-collections' experiments are enabled.
+/// If either of those experiments are enabled, then [ListLiteral2] will be
+/// used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ListLiteral implements TypedLiteral {
+  /// Return the expressions used to compute the elements of the list.
   NodeList<Expression> get elements;
 
-  /**
-   * Return the left square bracket.
-   */
+  /// Return the left square bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left square bracket to the given [token].
-   */
+  /// Set the left square bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right square bracket.
-   */
+  /// Return the right square bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right square bracket to the given [token].
-   */
+  /// Set the right square bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A list literal.
- *
- *    listLiteral ::=
- *        'const'? ('<' [TypeAnnotation] '>')?
- *        '[' ([CollectionElement] ','?)? ']'
- *
- * This is the class that is used to represent a list literal when either the
- * 'control-flow-collections' or 'spread-collections' experiments are enabled.
- * If neither of those experiments are enabled, then [ListLiteral] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ListLiteral2 extends TypedLiteral {
-  /**
-   * Return the expressions used to compute the elements of the list.
-   */
+/// A list literal.
+///
+///    listLiteral ::=
+///        'const'? ('<' [TypeAnnotation] '>')?
+///        '[' ([CollectionElement] ','?)? ']'
+///
+/// This is the class that is used to represent a list literal when either the
+/// 'control-flow-collections' or 'spread-collections' experiments are enabled.
+/// If neither of those experiments are enabled, then [ListLiteral] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ListLiteral2 implements TypedLiteral {
+  /// Return the expressions used to compute the elements of the list.
   NodeList<CollectionElement> get elements;
 
-  /**
-   * Return the left square bracket.
-   */
+  /// Return the left square bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left square bracket to the given [token].
-   */
+  /// Set the left square bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right square bracket.
-   */
+  /// Return the right square bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right square bracket to the given [token].
-   */
+  /// Set the right square bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A node that represents a literal expression.
- *
- *    literal ::=
- *        [BooleanLiteral]
- *      | [DoubleLiteral]
- *      | [IntegerLiteral]
- *      | [ListLiteral]
- *      | [MapLiteral]
- *      | [NullLiteral]
- *      | [StringLiteral]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Literal extends Expression {}
+/// A node that represents a literal expression.
+///
+///    literal ::=
+///        [BooleanLiteral]
+///      | [DoubleLiteral]
+///      | [IntegerLiteral]
+///      | [ListLiteral]
+///      | [MapLiteral]
+///      | [NullLiteral]
+///      | [StringLiteral]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Literal implements Expression {}
 
-/**
- * An element in a literal map.
- *
- *    mapElement ::=
- *        [Expression]
- *      | [IfElement<MapElement>]
- *      | [ForElement<MapElement>]
- *      | [SpreadElement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapElement implements AstNode {}
-
-/**
- * A for element in a literal map.
- *
- *    forElement ::=
- *        'await'? 'for' '(' [ForLoopParts] ')' [CollectionElement | MapElement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapForElement implements ForElement<MapElement>, MapElement {}
-
-/**
- * An if element in a map in a literal map.
- *
- *    ifElement ::=
- *        'if' '(' [Expression] ')' [MapElement] ( 'else' [MapElement] )?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapIfElement implements IfElement<MapElement>, MapElement {}
-
-/**
- * A literal map.
- *
- *    mapLiteral ::=
- *        'const'? ('<' [TypeAnnotation] (',' [TypeAnnotation])* '>')?
- *        '{' ([MapLiteralEntry] (',' [MapLiteralEntry])* ','?)? '}'
- *
- * This is the class that is used to represent a map literal when neither the
- * 'control-flow-collections' nor 'spread-collections' experiments are enabled.
- * If either of those experiments are enabled, then [MapLiteral2] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapLiteral extends TypedLiteral {
-  /**
-   * Return the entries in the map.
-   */
+/// A literal map.
+///
+///    mapLiteral ::=
+///        'const'? ('<' [TypeAnnotation] (',' [TypeAnnotation])* '>')?
+///        '{' ([MapLiteralEntry] (',' [MapLiteralEntry])* ','?)? '}'
+///
+/// This is the class that is used to represent a map literal when neither the
+/// 'control-flow-collections' nor 'spread-collections' experiments are enabled.
+/// If either of those experiments are enabled, then [MapLiteral2] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MapLiteral implements TypedLiteral {
+  /// Return the entries in the map.
   NodeList<MapLiteralEntry> get entries;
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A literal map.
- *
- *    mapLiteral ::=
- *        'const'? ('<' [TypeAnnotation] (',' [TypeAnnotation])* '>')?
- *        '{' ([MapElement] (',' [MapElement])* ','?)? '}'
- *
- * This is the class that is used to represent a map literal when either the
- * 'control-flow-collections' or 'spread-collections' experiments are enabled.
- * If neither of those experiments are enabled, then [MapLiteral] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapLiteral2 extends TypedLiteral {
-  /**
-   * Return the entries in the map.
-   */
-  NodeList<MapElement> get entries;
+/// A literal map.
+///
+///    mapLiteral ::=
+///        'const'? ('<' [TypeAnnotation] (',' [TypeAnnotation])* '>')?
+///        '{' ([MapElement] (',' [MapElement])* ','?)? '}'
+///
+/// This is the class that is used to represent a map literal when either the
+/// 'control-flow-collections' or 'spread-collections' experiments are enabled.
+/// If neither of those experiments are enabled, then [MapLiteral] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MapLiteral2 implements TypedLiteral {
+  /// Return the entries in the map.
+  NodeList<CollectionElement> get entries;
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A single key/value pair in a map literal.
- *
- *    mapLiteralEntry ::=
- *        [Expression] ':' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MapLiteralEntry implements MapElement {
-  /**
-   * Return the expression computing the key with which the value will be
-   * associated.
-   */
+/// A single key/value pair in a map literal.
+///
+///    mapLiteralEntry ::=
+///        [Expression] ':' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MapLiteralEntry implements CollectionElement {
+  /// Return the expression computing the key with which the value will be
+  /// associated.
   Expression get key;
 
-  /**
-   * Set the expression computing the key with which the value will be
-   * associated to the given [string].
-   */
+  /// Set the expression computing the key with which the value will be
+  /// associated to the given [string].
   void set key(Expression string);
 
-  /**
-   * Return the colon that separates the key from the value.
-   */
+  /// Return the colon that separates the key from the value.
   Token get separator;
 
-  /**
-   * Set the colon that separates the key from the value to the given [token].
-   */
+  /// Set the colon that separates the key from the value to the given [token].
   void set separator(Token token);
 
-  /**
-   * Return the expression computing the value that will be associated with the
-   * key.
-   */
+  /// Return the expression computing the value that will be associated with the
+  /// key.
   Expression get value;
 
-  /**
-   * Set the expression computing the value that will be associated with the key
-   * to the given [expression].
-   */
+  /// Set the expression computing the value that will be associated with the
+  /// key to the given [expression].
   void set value(Expression expression);
 }
 
-/**
- * A method declaration.
- *
- *    methodDeclaration ::=
- *        methodSignature [FunctionBody]
- *
- *    methodSignature ::=
- *        'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
- *        methodName [TypeParameterList] [FormalParameterList]
- *
- *    methodName ::=
- *        [SimpleIdentifier]
- *      | 'operator' [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MethodDeclaration extends ClassMember {
-  /**
-   * Return the body of the method.
-   */
+/// A method declaration.
+///
+///    methodDeclaration ::=
+///        methodSignature [FunctionBody]
+///
+///    methodSignature ::=
+///        'external'? ('abstract' | 'static')? [Type]? ('get' | 'set')?
+///        methodName [TypeParameterList] [FormalParameterList]
+///
+///    methodName ::=
+///        [SimpleIdentifier]
+///      | 'operator' [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MethodDeclaration implements ClassMember {
+  /// Return the body of the method.
   FunctionBody get body;
 
-  /**
-   * Set the body of the method to the given [functionBody].
-   */
+  /// Set the body of the method to the given [functionBody].
   void set body(FunctionBody functionBody);
 
   @override
@@ -5398,2180 +3880,1530 @@
   @override
   ExecutableElement get element;
 
-  /**
-   * Return the token for the 'external' keyword, or `null` if the constructor
-   * is not external.
-   */
+  /// Return the token for the 'external' keyword, or `null` if the constructor
+  /// is not external.
   Token get externalKeyword;
 
-  /**
-   * Set the token for the 'external' keyword to the given [token].
-   */
+  /// Set the token for the 'external' keyword to the given [token].
   void set externalKeyword(Token token);
 
-  /**
-   * Return `true` if this method is declared to be an abstract method.
-   */
+  /// Return `true` if this method is declared to be an abstract method.
   bool get isAbstract;
 
-  /**
-   * Return `true` if this method declares a getter.
-   */
+  /// Return `true` if this method declares a getter.
   bool get isGetter;
 
-  /**
-   * Return `true` if this method declares an operator.
-   */
+  /// Return `true` if this method declares an operator.
   bool get isOperator;
 
-  /**
-   * Return `true` if this method declares a setter.
-   */
+  /// Return `true` if this method declares a setter.
   bool get isSetter;
 
-  /**
-   * Return `true` if this method is declared to be a static method.
-   */
+  /// Return `true` if this method is declared to be a static method.
   bool get isStatic;
 
-  /**
-   * Return the token representing the 'abstract' or 'static' keyword, or `null`
-   * if neither modifier was specified.
-   */
+  /// Return the token representing the 'abstract' or 'static' keyword, or
+  /// `null` if neither modifier was specified.
   Token get modifierKeyword;
 
-  /**
-   * Set the token representing the 'abstract' or 'static' keyword to the given
-   * [token].
-   */
+  /// Set the token representing the 'abstract' or 'static' keyword to the given
+  /// [token].
   void set modifierKeyword(Token token);
 
-  /**
-   * Return the name of the method.
-   */
+  /// Return the name of the method.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the method to the given [identifier].
-   */
+  /// Set the name of the method to the given [identifier].
   void set name(SimpleIdentifier identifier);
 
-  /**
-   * Return the token representing the 'operator' keyword, or `null` if this
-   * method does not declare an operator.
-   */
+  /// Return the token representing the 'operator' keyword, or `null` if this
+  /// method does not declare an operator.
   Token get operatorKeyword;
 
-  /**
-   * Set the token representing the 'operator' keyword to the given [token].
-   */
+  /// Set the token representing the 'operator' keyword to the given [token].
   void set operatorKeyword(Token token);
 
-  /**
-   * Return the parameters associated with the method, or `null` if this method
-   * declares a getter.
-   */
+  /// Return the parameters associated with the method, or `null` if this method
+  /// declares a getter.
   FormalParameterList get parameters;
 
-  /**
-   * Set the parameters associated with the method to the given list of
-   * [parameters].
-   */
+  /// Set the parameters associated with the method to the given list of
+  /// [parameters].
   void set parameters(FormalParameterList parameters);
 
-  /**
-   * Return the token representing the 'get' or 'set' keyword, or `null` if this
-   * is a method declaration rather than a property declaration.
-   */
+  /// Return the token representing the 'get' or 'set' keyword, or `null` if
+  /// this is a method declaration rather than a property declaration.
   Token get propertyKeyword;
 
-  /**
-   * Set the token representing the 'get' or 'set' keyword to the given [token].
-   */
+  /// Set the token representing the 'get' or 'set' keyword to the given
+  /// [token].
   void set propertyKeyword(Token token);
 
-  /**
-   * Return the return type of the method, or `null` if no return type was
-   * declared.
-   */
+  /// Return the return type of the method, or `null` if no return type was
+  /// declared.
   TypeAnnotation get returnType;
 
-  /**
-   * Set the return type of the method to the given [type].
-   */
+  /// Set the return type of the method to the given [type].
   void set returnType(TypeAnnotation type);
 
-  /**
-   * Return the type parameters associated with this method, or `null` if this
-   * method is not a generic method.
-   */
+  /// Return the type parameters associated with this method, or `null` if this
+  /// method is not a generic method.
   TypeParameterList get typeParameters;
 
-  /**
-   * Set the type parameters associated with this method to the given
-   * [typeParameters].
-   */
+  /// Set the type parameters associated with this method to the given
+  /// [typeParameters].
   void set typeParameters(TypeParameterList typeParameters);
 }
 
-/**
- * The invocation of either a function or a method. Invocations of functions
- * resulting from evaluating an expression are represented by
- * [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
- * represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
- *
- *    methodInvocation ::=
- *        ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MethodInvocation extends InvocationExpression {
-  /**
-   * Set the list of arguments to the method to the given [argumentList].
-   */
+/// The invocation of either a function or a method. Invocations of functions
+/// resulting from evaluating an expression are represented by
+/// [FunctionExpressionInvocation] nodes. Invocations of getters and setters are
+/// represented by either [PrefixedIdentifier] or [PropertyAccess] nodes.
+///
+///    methodInvocation ::=
+///        ([Expression] '.')? [SimpleIdentifier] [TypeArgumentList]? [ArgumentList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MethodInvocation implements InvocationExpression {
+  /// Set the list of arguments to the method to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
+  /// Return `true` if this expression is cascaded. If it is, then the target of
+  /// this expression is not stored locally but is stored in the nearest
+  /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
-  /**
-   * Return the name of the method being invoked.
-   */
+  /// Return the name of the method being invoked.
   SimpleIdentifier get methodName;
 
-  /**
-   * Set the name of the method being invoked to the given [identifier].
-   */
+  /// Set the name of the method being invoked to the given [identifier].
   void set methodName(SimpleIdentifier identifier);
 
-  /**
-   * Return the operator that separates the target from the method name, or
-   * `null` if there is no target. In an ordinary method invocation this will be
-   *  * period ('.'). In a cascade section this will be the cascade operator
-   * ('..').
-   */
+  /// Return the operator that separates the target from the method name, or
+  /// `null` if there is no target. In an ordinary method invocation this will
+  /// be period ('.'). In a cascade section this will be the cascade operator
+  /// ('..').
   Token get operator;
 
-  /**
-   * Set the operator that separates the target from the method name to the
-   * given [token].
-   */
+  /// Set the operator that separates the target from the method name to the
+  /// given [token].
   void set operator(Token token);
 
-  /**
-   * Return the expression used to compute the receiver of the invocation. If
-   * this invocation is not part of a cascade expression, then this is the same
-   * as [target]. If this invocation is part of a cascade expression, then the
-   * target stored with the cascade expression is returned.
-   */
+  /// Return the expression used to compute the receiver of the invocation. If
+  /// this invocation is not part of a cascade expression, then this is the same
+  /// as [target]. If this invocation is part of a cascade expression, then the
+  /// target stored with the cascade expression is returned.
   Expression get realTarget;
 
-  /**
-   * Return the expression producing the object on which the method is defined,
-   * or `null` if there is no target (that is, the target is implicitly `this`)
-   * or if this method invocation is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
+  /// Return the expression producing the object on which the method is defined,
+  /// or `null` if there is no target (that is, the target is implicitly `this`)
+  /// or if this method invocation is part of a cascade expression.
+  ///
+  /// Use [realTarget] to get the target independent of whether this is part of
+  /// a cascade expression.
   Expression get target;
 
-  /**
-   * Set the expression producing the object on which the method is defined to
-   * the given [expression].
-   */
+  /// Set the expression producing the object on which the method is defined to
+  /// the given [expression].
   void set target(Expression expression);
 
-  /**
-   * Set the type arguments to be applied to the method being invoked to the
-   * given [typeArguments].
-   */
+  /// Set the type arguments to be applied to the method being invoked to the
+  /// given [typeArguments].
   void set typeArguments(TypeArgumentList typeArguments);
 }
 
-/**
- * An expression that implicitly makes reference to a method.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// An expression that implicitly makes reference to a method.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class MethodReferenceExpression implements AstNode {
-  /**
-   * Return the best element available for this expression. If resolution was
-   * able to find a better element based on type propagation, that element will
-   * be returned. Otherwise, the element found using the result of static
-   * analysis will be returned. If resolution has not been performed, then
-   * `null` will be returned.
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Return the best element available for this expression. If resolution was
+  /// able to find a better element based on type propagation, that element will
+  /// be returned. Otherwise, the element found using the result of static
+  /// analysis will be returned. If resolution has not been performed, then
+  /// `null` will be returned.
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   MethodElement get bestElement;
 
-  /**
-   * Return the element associated with the expression based on propagated
-   * types, or `null` if the AST structure has not been resolved, or there is
-   * no meaningful propagated element to return (e.g. because this is a
-   * non-compound assignment expression, or because the method referred to could
-   * not be resolved).
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Return the element associated with the expression based on propagated
+  /// types, or `null` if the AST structure has not been resolved, or there is
+  /// no meaningful propagated element to return (e.g. because this is a
+  /// non-compound assignment expression, or because the method referred to
+  /// could not be resolved).
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   MethodElement get propagatedElement;
 
-  /**
-   * Set the element associated with the expression based on propagated types to
-   * the given [element].
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Set the element associated with the expression based on propagated types
+  /// to the given [element].
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   void set propagatedElement(MethodElement element);
 
-  /**
-   * Return the element associated with the expression based on the static
-   * types, or `null` if the AST structure has not been resolved, or there is no
-   * meaningful static element to return (e.g. because this is a non-compound
-   * assignment expression, or because the method referred to could not be
-   * resolved).
-   */
+  /// Return the element associated with the expression based on the static
+  /// types, or `null` if the AST structure has not been resolved, or there is
+  /// no meaningful static element to return (e.g. because this is a
+  /// non-compound assignment expression, or because the method referred to
+  /// could not be resolved).
   MethodElement get staticElement;
 
-  /**
-   * Set the element associated with the expression based on static types to the
-   * given [element].
-   */
+  /// Set the element associated with the expression based on static types to
+  /// the given [element].
   void set staticElement(MethodElement element);
 }
 
-/**
- * The declaration of a mixin.
- *
- *    mixinDeclaration ::=
- *        metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
- *        [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class MixinDeclaration extends ClassOrMixinDeclaration {
-  /**
-   * Return the token representing the 'mixin' keyword.
-   */
+/// The declaration of a mixin.
+///
+///    mixinDeclaration ::=
+///        metadata? 'mixin' [SimpleIdentifier] [TypeParameterList]?
+///        [OnClause]? [ImplementsClause]? '{' [ClassMember]* '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class MixinDeclaration implements ClassOrMixinDeclaration {
+  /// Return the token representing the 'mixin' keyword.
   Token get mixinKeyword;
 
-  /**
-   * Return the on clause for the mixin, or `null` if the mixin does not have
-   * any superclass constraints.
-   */
+  /// Return the on clause for the mixin, or `null` if the mixin does not have
+  /// any superclass constraints.
   OnClause get onClause;
 }
 
-/**
- * A node that declares a single name within the scope of a compilation unit.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NamedCompilationUnitMember extends CompilationUnitMember {
-  /**
-   * Return the name of the member being declared.
-   */
+/// A node that declares a single name within the scope of a compilation unit.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NamedCompilationUnitMember implements CompilationUnitMember {
+  /// Return the name of the member being declared.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the member being declared to the given [identifier].
-   */
+  /// Set the name of the member being declared to the given [identifier].
   void set name(SimpleIdentifier identifier);
 }
 
-/**
- * An expression that has a name associated with it. They are used in method
- * invocations when there are named parameters.
- *
- *    namedExpression ::=
- *        [Label] [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NamedExpression extends Expression {
-  /**
-   * Return the element representing the parameter being named by this
-   * expression, or `null` if the AST structure has not been resolved or if
-   * there is no parameter with the same name as this expression.
-   */
+/// An expression that has a name associated with it. They are used in method
+/// invocations when there are named parameters.
+///
+///    namedExpression ::=
+///        [Label] [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NamedExpression implements Expression {
+  /// Return the element representing the parameter being named by this
+  /// expression, or `null` if the AST structure has not been resolved or if
+  /// there is no parameter with the same name as this expression.
   ParameterElement get element;
 
-  /**
-   * Return the expression with which the name is associated.
-   */
+  /// Return the expression with which the name is associated.
   Expression get expression;
 
-  /**
-   * Set the expression with which the name is associated to the given
-   * [expression].
-   */
+  /// Set the expression with which the name is associated to the given
+  /// [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the name associated with the expression.
-   */
+  /// Return the name associated with the expression.
   Label get name;
 
-  /**
-   * Set the name associated with the expression to the given [identifier].
-   */
+  /// Set the name associated with the expression to the given [identifier].
   void set name(Label identifier);
 }
 
-/**
- * A named type, which can optionally include type arguments.
- *
- *    namedType ::=
- *        [Identifier] typeArguments?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NamedType extends TypeAnnotation {
-  /**
-   * Return `true` if this type is a deferred type.
-   *
-   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
-   * </i>p.T</i> where <i>p</i> is a deferred prefix.
-   */
+/// A named type, which can optionally include type arguments.
+///
+///    namedType ::=
+///        [Identifier] typeArguments?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NamedType implements TypeAnnotation {
+  /// Return `true` if this type is a deferred type.
+  ///
+  /// 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
+  /// </i>p.T</i> where <i>p</i> is a deferred prefix.
   bool get isDeferred;
 
-  /**
-   * Return the name of the type.
-   */
+  /// Return the name of the type.
   Identifier get name;
 
-  /**
-   * Set the name of the type to the given [identifier].
-   */
+  /// Set the name of the type to the given [identifier].
   void set name(Identifier identifier);
 
-  /**
-   * The question mark indicating that the type is nullable, or `null` if there
-   * is no question mark.
-   */
-  Token get question;
-
-  /**
-   * Set the question mark indicating that the type is nullable to the given
-   * [token].
-   */
+  /// Set the question mark indicating that the type is nullable to the given
+  /// [token].
   void set question(Token token);
 
-  /**
-   * Set the type being named to the given [type].
-   */
+  /// Set the type being named to the given [type].
   void set type(DartType type);
 
-  /**
-   * Return the type arguments associated with the type, or `null` if there are
-   * no type arguments.
-   */
+  /// Return the type arguments associated with the type, or `null` if there are
+  /// no type arguments.
   TypeArgumentList get typeArguments;
 
-  /**
-   * Set the type arguments associated with the type to the given
-   * [typeArguments].
-   */
+  /// Set the type arguments associated with the type to the given
+  /// [typeArguments].
   void set typeArguments(TypeArgumentList typeArguments);
 }
 
-/**
- * A node that represents a directive that impacts the namespace of a library.
- *
- *    directive ::=
- *        [ExportDirective]
- *      | [ImportDirective]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NamespaceDirective extends UriBasedDirective {
-  /**
-   * Return the combinators used to control how names are imported or exported.
-   */
+/// A node that represents a directive that impacts the namespace of a library.
+///
+///    directive ::=
+///        [ExportDirective]
+///      | [ImportDirective]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NamespaceDirective implements UriBasedDirective {
+  /// Return the combinators used to control how names are imported or exported.
   NodeList<Combinator> get combinators;
 
-  /**
-   * Return the configurations used to control which library will actually be
-   * loaded at run-time.
-   */
+  /// Return the configurations used to control which library will actually be
+  /// loaded at run-time.
   NodeList<Configuration> get configurations;
 
-  /**
-   * Set the token representing the keyword that introduces this directive
-   * ('import', 'export', 'library' or 'part') to the given [token].
-   */
+  /// Set the token representing the keyword that introduces this directive
+  /// ('import', 'export', 'library' or 'part') to the given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the source that was selected based on the declared variables. This
-   * will be the source from the first configuration whose condition is true, or
-   * the [uriSource] if either there are no configurations or if there are no
-   * configurations whose condition is true.
-   */
+  /// Return the source that was selected based on the declared variables. This
+  /// will be the source from the first configuration whose condition is true,
+  /// or the [uriSource] if either there are no configurations or if there are
+  /// no configurations whose condition is true.
   Source get selectedSource;
 
-  /**
-   * Return the content of the URI that was selected based on the declared
-   * variables. This will be the URI from the first configuration whose
-   * condition is true, or the [uriContent] if either there are no
-   * configurations or if there are no configurations whose condition is true.
-   */
+  /// Return the content of the URI that was selected based on the declared
+  /// variables. This will be the URI from the first configuration whose
+  /// condition is true, or the [uriContent] if either there are no
+  /// configurations or if there are no configurations whose condition is true.
   String get selectedUriContent;
 
-  /**
-   * Return the semicolon terminating the directive.
-   */
+  /// Return the semicolon terminating the directive.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the directive to the given [token].
-   */
+  /// Set the semicolon terminating the directive to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * The "native" clause in an class declaration.
- *
- *    nativeClause ::=
- *        'native' [StringLiteral]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NativeClause extends AstNode {
-  /**
-   * Return the name of the native object that implements the class.
-   */
+/// The "native" clause in an class declaration.
+///
+///    nativeClause ::=
+///        'native' [StringLiteral]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NativeClause implements AstNode {
+  /// Return the name of the native object that implements the class.
   StringLiteral get name;
 
-  /**
-   * Set the name of the native object that implements the class to the given
-   * [name].
-   */
+  /// Set the name of the native object that implements the class to the given
+  /// [name].
   void set name(StringLiteral name);
 
-  /**
-   * Return the token representing the 'native' keyword.
-   */
+  /// Return the token representing the 'native' keyword.
   Token get nativeKeyword;
 
-  /**
-   * Set the token representing the 'native' keyword to the given [token].
-   */
+  /// Set the token representing the 'native' keyword to the given [token].
   void set nativeKeyword(Token token);
 }
 
-/**
- * A function body that consists of a native keyword followed by a string
- * literal.
- *
- *    nativeFunctionBody ::=
- *        'native' [SimpleStringLiteral] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NativeFunctionBody extends FunctionBody {
-  /**
-   * Return the token representing 'native' that marks the start of the function
-   * body.
-   */
+/// A function body that consists of a native keyword followed by a string
+/// literal.
+///
+///    nativeFunctionBody ::=
+///        'native' [SimpleStringLiteral] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NativeFunctionBody implements FunctionBody {
+  /// Return the token representing 'native' that marks the start of the
+  /// function body.
   Token get nativeKeyword;
 
-  /**
-   * Set the token representing 'native' that marks the start of the function
-   * body to the given [token].
-   */
+  /// Set the token representing 'native' that marks the start of the function
+  /// body to the given [token].
   void set nativeKeyword(Token token);
 
-  /**
-   * Return the token representing the semicolon that marks the end of the
-   * function body.
-   */
+  /// Return the token representing the semicolon that marks the end of the
+  /// function body.
   Token get semicolon;
 
-  /**
-   * Set the token representing the semicolon that marks the end of the
-   * function body to the given [token].
-   */
+  /// Set the token representing the semicolon that marks the end of the
+  /// function body to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the string literal representing the string after the 'native' token.
-   */
+  /// Return the string literal representing the string after the 'native'
+  /// token.
   StringLiteral get stringLiteral;
 
-  /**
-   * Set the string literal representing the string after the 'native' token to
-   * the given [stringLiteral].
-   */
+  /// Set the string literal representing the string after the 'native' token to
+  /// the given [stringLiteral].
   void set stringLiteral(StringLiteral stringLiteral);
 }
 
-/**
- * A list of AST nodes that have a common parent.
- *
- * Clients may not extend, implement or mix-in this class.
- */
+/// A list of AST nodes that have a common parent.
+///
+/// Clients may not extend, implement or mix-in this class.
 abstract class NodeList<E extends AstNode> implements List<E> {
-  /**
-   * Return the first token included in this node list's source range, or `null`
-   * if the list is empty.
-   */
+  /// Return the first token included in this node list's source range, or
+  /// `null` if the list is empty.
   Token get beginToken;
 
-  /**
-   * Return the last token included in this node list's source range, or `null`
-   * if the list is empty.
-   */
+  /// Return the last token included in this node list's source range, or `null`
+  /// if the list is empty.
   Token get endToken;
 
-  /**
-   * Return the node that is the parent of each of the elements in the list.
-   */
+  /// Return the node that is the parent of each of the elements in the list.
   AstNode get owner;
 
-  /**
-   * Set the node that is the parent of each of the elements in the list to the
-   * given [node].
-   */
+  /// Set the node that is the parent of each of the elements in the list to the
+  /// given [node].
   @deprecated // Never intended for public use.
   void set owner(AstNode node);
 
-  /**
-   * Return the node at the given [index] in the list or throw a [RangeError] if
-   * [index] is out of bounds.
-   */
+  /// Return the node at the given [index] in the list or throw a [RangeError]
+  /// if [index] is out of bounds.
   @override
   E operator [](int index);
 
-  /**
-   * Set the node at the given [index] in the list to the given [node] or throw
-   * a [RangeError] if [index] is out of bounds.
-   */
+  /// Set the node at the given [index] in the list to the given [node] or throw
+  /// a [RangeError] if [index] is out of bounds.
   @override
   void operator []=(int index, E node);
 
-  /**
-   * Use the given [visitor] to visit each of the nodes in this list.
-   */
+  /// Use the given [visitor] to visit each of the nodes in this list.
   accept(AstVisitor visitor);
 }
 
-/**
- * A formal parameter that is required (is not optional).
- *
- *    normalFormalParameter ::=
- *        [FunctionTypedFormalParameter]
- *      | [FieldFormalParameter]
- *      | [SimpleFormalParameter]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NormalFormalParameter extends FormalParameter {
-  /**
-   * Set the token for the 'covariant' keyword to the given [token].
-   */
+/// A formal parameter that is required (is not optional).
+///
+///    normalFormalParameter ::=
+///        [FunctionTypedFormalParameter]
+///      | [FieldFormalParameter]
+///      | [SimpleFormalParameter]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NormalFormalParameter implements FormalParameter {
+  /// Set the token for the 'covariant' keyword to the given [token].
   void set covariantKeyword(Token token);
 
-  /**
-   * Return the documentation comment associated with this parameter, or `null`
-   * if this parameter does not have a documentation comment associated with it.
-   */
+  /// Return the documentation comment associated with this parameter, or `null`
+  /// if this parameter does not have a documentation comment associated with
+  /// it.
   Comment get documentationComment;
 
-  /**
-   * Set the documentation comment associated with this parameter to the given
-   * [comment].
-   */
+  /// Set the documentation comment associated with this parameter to the given
+  /// [comment].
   void set documentationComment(Comment comment);
 
-  /**
-   * Set the name of the parameter being declared to the given [identifier].
-   */
+  /// Set the name of the parameter being declared to the given [identifier].
   void set identifier(SimpleIdentifier identifier);
 
-  /**
-   * Set the metadata associated with this node to the given [metadata].
-   */
+  /// Set the metadata associated with this node to the given [metadata].
   void set metadata(List<Annotation> metadata);
 
-  /**
-   * Return a list containing the comment and annotations associated with this
-   * parameter, sorted in lexical order.
-   */
+  /// Return a list containing the comment and annotations associated with this
+  /// parameter, sorted in lexical order.
   List<AstNode> get sortedCommentAndAnnotations;
 }
 
-/**
- * A null literal expression.
- *
- *    nullLiteral ::=
- *        'null'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class NullLiteral extends Literal {
-  /**
-   * Return the token representing the literal.
-   */
+/// A null literal expression.
+///
+///    nullLiteral ::=
+///        'null'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class NullLiteral implements Literal {
+  /// Return the token representing the literal.
   Token get literal;
 
-  /**
-   * Set the token representing the literal to the given [token].
-   */
+  /// Set the token representing the literal to the given [token].
   void set literal(Token token);
 }
 
-/**
- * The "on" clause in a mixin declaration.
- *
- *    onClause ::=
- *        'on' [TypeName] (',' [TypeName])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class OnClause extends AstNode {
-  /**
-   * Return the token representing the 'on' keyword.
-   */
+/// The "on" clause in a mixin declaration.
+///
+///    onClause ::=
+///        'on' [TypeName] (',' [TypeName])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class OnClause implements AstNode {
+  /// Return the token representing the 'on' keyword.
   Token get onKeyword;
 
-  /**
-   * Return the list of the classes are superclass constraints for the mixin.
-   */
+  /// Return the list of the classes are superclass constraints for the mixin.
   NodeList<TypeName> get superclassConstraints;
 }
 
-/**
- * A parenthesized expression.
- *
- *    parenthesizedExpression ::=
- *        '(' [Expression] ')'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ParenthesizedExpression extends Expression {
-  /**
-   * Return the expression within the parentheses.
-   */
+/// A parenthesized expression.
+///
+///    parenthesizedExpression ::=
+///        '(' [Expression] ')'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ParenthesizedExpression implements Expression {
+  /// Return the expression within the parentheses.
   Expression get expression;
 
-  /**
-   * Set the expression within the parentheses to the given [expression].
-   */
+  /// Set the expression within the parentheses to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 }
 
-/**
- * A part directive.
- *
- *    partDirective ::=
- *        [Annotation] 'part' [StringLiteral] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PartDirective extends UriBasedDirective {
-  /**
-   * Return the token representing the 'part' keyword.
-   */
+/// A part directive.
+///
+///    partDirective ::=
+///        [Annotation] 'part' [StringLiteral] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PartDirective implements UriBasedDirective {
+  /// Return the token representing the 'part' keyword.
   Token get partKeyword;
 
-  /**
-   * Set the token representing the 'part' keyword to the given [token].
-   */
+  /// Set the token representing the 'part' keyword to the given [token].
   void set partKeyword(Token token);
 
-  /**
-   * Return the semicolon terminating the directive.
-   */
+  /// Return the semicolon terminating the directive.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the directive to the given [token].
-   */
+  /// Set the semicolon terminating the directive to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * A part-of directive.
- *
- *    partOfDirective ::=
- *        [Annotation] 'part' 'of' [Identifier] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PartOfDirective extends Directive {
-  /**
-   * Return the name of the library that the containing compilation unit is part
-   * of.
-   */
+/// A part-of directive.
+///
+///    partOfDirective ::=
+///        [Annotation] 'part' 'of' [Identifier] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PartOfDirective implements Directive {
+  /// Return the name of the library that the containing compilation unit is
+  /// part of.
   LibraryIdentifier get libraryName;
 
-  /**
-   * Set the name of the library that the containing compilation unit is part of
-   * to the given [libraryName].
-   */
+  /// Set the name of the library that the containing compilation unit is part
+  /// of to the given [libraryName].
   void set libraryName(LibraryIdentifier libraryName);
 
-  /**
-   * Return the token representing the 'of' keyword.
-   */
+  /// Return the token representing the 'of' keyword.
   Token get ofKeyword;
 
-  /**
-   * Set the token representing the 'of' keyword to the given [token].
-   */
+  /// Set the token representing the 'of' keyword to the given [token].
   void set ofKeyword(Token token);
 
-  /**
-   * Return the token representing the 'part' keyword.
-   */
+  /// Return the token representing the 'part' keyword.
   Token get partKeyword;
 
-  /**
-   * Set the token representing the 'part' keyword to the given [token].
-   */
+  /// Set the token representing the 'part' keyword to the given [token].
   void set partKeyword(Token token);
 
-  /**
-   * Return the semicolon terminating the directive.
-   */
+  /// Return the semicolon terminating the directive.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the directive to the given [token].
-   */
+  /// Set the semicolon terminating the directive to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the URI of the library that the containing compilation unit is part
-   * of, or `null` if no URI was given (typically because a library name was
-   * provided).
-   */
+  /// Return the URI of the library that the containing compilation unit is part
+  /// of, or `null` if no URI was given (typically because a library name was
+  /// provided).
   StringLiteral get uri;
 
-  /**
-   * Return the URI of the library that the containing compilation unit is part
-   * of, or `null` if no URI was given (typically because a library name was
-   * provided).
-   */
+  /// Return the URI of the library that the containing compilation unit is part
+  /// of, or `null` if no URI was given (typically because a library name was
+  /// provided).
   void set uri(StringLiteral uri);
 }
 
-/**
- * A postfix unary expression.
- *
- *    postfixExpression ::=
- *        [Expression] [Token]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PostfixExpression extends Expression
-    implements MethodReferenceExpression {
-  /**
-   * Return the expression computing the operand for the operator.
-   */
+/// A postfix unary expression.
+///
+///    postfixExpression ::=
+///        [Expression] [Token]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PostfixExpression
+    implements Expression, MethodReferenceExpression {
+  /// Return the expression computing the operand for the operator.
   Expression get operand;
 
-  /**
-   * Set the expression computing the operand for the operator to the given
-   * [expression].
-   */
+  /// Set the expression computing the operand for the operator to the given
+  /// [expression].
   void set operand(Expression expression);
 
-  /**
-   * Return the postfix operator being applied to the operand.
-   */
+  /// Return the postfix operator being applied to the operand.
   Token get operator;
 
-  /**
-   * Set the postfix operator being applied to the operand to the given [token].
-   */
+  /// Set the postfix operator being applied to the operand to the given
+  /// [token].
   void set operator(Token token);
 }
 
-/**
- * An identifier that is prefixed or an access to an object property where the
- * target of the property access is a simple identifier.
- *
- *    prefixedIdentifier ::=
- *        [SimpleIdentifier] '.' [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PrefixedIdentifier extends Identifier {
-  /**
-   * Return the identifier being prefixed.
-   */
+/// An identifier that is prefixed or an access to an object property where the
+/// target of the property access is a simple identifier.
+///
+///    prefixedIdentifier ::=
+///        [SimpleIdentifier] '.' [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PrefixedIdentifier implements Identifier {
+  /// Return the identifier being prefixed.
   SimpleIdentifier get identifier;
 
-  /**
-   * Set the identifier being prefixed to the given [identifier].
-   */
+  /// Set the identifier being prefixed to the given [identifier].
   void set identifier(SimpleIdentifier identifier);
 
-  /**
-   * Return `true` if this type is a deferred type. If the AST structure has not
-   * been resolved, then return `false`.
-   *
-   * 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
-   * </i>p.T</i> where <i>p</i> is a deferred prefix.
-   */
+  /// Return `true` if this type is a deferred type. If the AST structure has
+  /// not been resolved, then return `false`.
+  ///
+  /// 15.1 Static Types: A type <i>T</i> is deferred iff it is of the form
+  /// </i>p.T</i> where <i>p</i> is a deferred prefix.
   bool get isDeferred;
 
-  /**
-   * Return the period used to separate the prefix from the identifier.
-   */
+  /// Return the period used to separate the prefix from the identifier.
   Token get period;
 
-  /**
-   * Set the period used to separate the prefix from the identifier to the given
-   * [token].
-   */
+  /// Set the period used to separate the prefix from the identifier to the
+  /// given [token].
   void set period(Token token);
 
-  /**
-   * Return the prefix associated with the library in which the identifier is
-   * defined.
-   */
+  /// Return the prefix associated with the library in which the identifier is
+  /// defined.
   SimpleIdentifier get prefix;
 
-  /**
-   * Set the prefix associated with the library in which the identifier is
-   * defined to the given [identifier].
-   */
+  /// Set the prefix associated with the library in which the identifier is
+  /// defined to the given [identifier].
   void set prefix(SimpleIdentifier identifier);
 }
 
-/**
- * A prefix unary expression.
- *
- *    prefixExpression ::=
- *        [Token] [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PrefixExpression extends Expression
-    implements MethodReferenceExpression {
-  /**
-   * Return the expression computing the operand for the operator.
-   */
+/// A prefix unary expression.
+///
+///    prefixExpression ::=
+///        [Token] [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PrefixExpression
+    implements Expression, MethodReferenceExpression {
+  /// Return the expression computing the operand for the operator.
   Expression get operand;
 
-  /**
-   * Set the expression computing the operand for the operator to the given
-   * [expression].
-   */
+  /// Set the expression computing the operand for the operator to the given
+  /// [expression].
   void set operand(Expression expression);
 
-  /**
-   * Return the prefix operator being applied to the operand.
-   */
+  /// Return the prefix operator being applied to the operand.
   Token get operator;
 
-  /**
-   * Set the prefix operator being applied to the operand to the given [token].
-   */
+  /// Set the prefix operator being applied to the operand to the given [token].
   void set operator(Token token);
 }
 
-/**
- * The access of a property of an object.
- *
- * Note, however, that accesses to properties of objects can also be represented
- * as [PrefixedIdentifier] nodes in cases where the target is also a simple
- * identifier.
- *
- *    propertyAccess ::=
- *        [Expression] '.' [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class PropertyAccess extends Expression {
-  /**
-   * Return `true` if this expression is cascaded. If it is, then the target of
-   * this expression is not stored locally but is stored in the nearest ancestor
-   * that is a [CascadeExpression].
-   */
+/// The access of a property of an object.
+///
+/// Note, however, that accesses to properties of objects can also be
+/// represented as [PrefixedIdentifier] nodes in cases where the target is also
+/// a simple identifier.
+///
+///    propertyAccess ::=
+///        [Expression] '.' [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class PropertyAccess implements Expression {
+  /// Return `true` if this expression is cascaded. If it is, then the target of
+  /// this expression is not stored locally but is stored in the nearest
+  /// ancestor that is a [CascadeExpression].
   bool get isCascaded;
 
-  /**
-   * Return the property access operator.
-   */
+  /// Return the property access operator.
   Token get operator;
 
-  /**
-   * Set the property access operator to the given [token].
-   */
+  /// Set the property access operator to the given [token].
   void set operator(Token token);
 
-  /**
-   * Return the name of the property being accessed.
-   */
+  /// Return the name of the property being accessed.
   SimpleIdentifier get propertyName;
 
-  /**
-   * Set the name of the property being accessed to the given [identifier].
-   */
+  /// Set the name of the property being accessed to the given [identifier].
   void set propertyName(SimpleIdentifier identifier);
 
-  /**
-   * Return the expression used to compute the receiver of the invocation. If
-   * this invocation is not part of a cascade expression, then this is the same
-   * as [target]. If this invocation is part of a cascade expression, then the
-   * target stored with the cascade expression is returned.
-   */
+  /// Return the expression used to compute the receiver of the invocation. If
+  /// this invocation is not part of a cascade expression, then this is the same
+  /// as [target]. If this invocation is part of a cascade expression, then the
+  /// target stored with the cascade expression is returned.
   Expression get realTarget;
 
-  /**
-   * Return the expression computing the object defining the property being
-   * accessed, or `null` if this property access is part of a cascade expression.
-   *
-   * Use [realTarget] to get the target independent of whether this is part of a
-   * cascade expression.
-   */
+  /// Return the expression computing the object defining the property being
+  /// accessed, or `null` if this property access is part of a cascade
+  /// expression.
+  ///
+  /// Use [realTarget] to get the target independent of whether this is part of
+  /// a cascade expression.
   Expression get target;
 
-  /**
-   * Set the expression computing the object defining the property being
-   * accessed to the given [expression].
-   */
+  /// Set the expression computing the object defining the property being
+  /// accessed to the given [expression].
   void set target(Expression expression);
 }
 
-/**
- * The invocation of a constructor in the same class from within a constructor's
- * initialization list.
- *
- *    redirectingConstructorInvocation ::=
- *        'this' ('.' identifier)? arguments
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class RedirectingConstructorInvocation extends ConstructorInitializer
-    implements ConstructorReferenceNode {
-  /**
-   * Return the list of arguments to the constructor.
-   */
+/// The invocation of a constructor in the same class from within a
+/// constructor's initialization list.
+///
+///    redirectingConstructorInvocation ::=
+///        'this' ('.' identifier)? arguments
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class RedirectingConstructorInvocation
+    implements ConstructorInitializer, ConstructorReferenceNode {
+  /// Return the list of arguments to the constructor.
   ArgumentList get argumentList;
 
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
+  /// Set the list of arguments to the constructor to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /**
-   * Return the name of the constructor that is being invoked, or `null` if the
-   * unnamed constructor is being invoked.
-   */
+  /// Return the name of the constructor that is being invoked, or `null` if the
+  /// unnamed constructor is being invoked.
   SimpleIdentifier get constructorName;
 
-  /**
-   * Set the name of the constructor that is being invoked to the given
-   * [identifier].
-   */
+  /// Set the name of the constructor that is being invoked to the given
+  /// [identifier].
   void set constructorName(SimpleIdentifier identifier);
 
-  /**
-   * Return the token for the period before the name of the constructor that is
-   * being invoked, or `null` if the unnamed constructor is being invoked.
-   */
+  /// Return the token for the period before the name of the constructor that is
+  /// being invoked, or `null` if the unnamed constructor is being invoked.
   Token get period;
 
-  /**
-   * Set the token for the period before the name of the constructor that is
-   * being invoked to the given [token].
-   */
+  /// Set the token for the period before the name of the constructor that is
+  /// being invoked to the given [token].
   void set period(Token token);
 
-  /**
-   * Return the token for the 'this' keyword.
-   */
+  /// Return the token for the 'this' keyword.
   Token get thisKeyword;
 
-  /**
-   * Set the token for the 'this' keyword to the given [token].
-   */
+  /// Set the token for the 'this' keyword to the given [token].
   void set thisKeyword(Token token);
 }
 
-/**
- * A rethrow expression.
- *
- *    rethrowExpression ::=
- *        'rethrow'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class RethrowExpression extends Expression {
-  /**
-   * Return the token representing the 'rethrow' keyword.
-   */
+/// A rethrow expression.
+///
+///    rethrowExpression ::=
+///        'rethrow'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class RethrowExpression implements Expression {
+  /// Return the token representing the 'rethrow' keyword.
   Token get rethrowKeyword;
 
-  /**
-   * Set the token representing the 'rethrow' keyword to the given [token].
-   */
+  /// Set the token representing the 'rethrow' keyword to the given [token].
   void set rethrowKeyword(Token token);
 }
 
-/**
- * A return statement.
- *
- *    returnStatement ::=
- *        'return' [Expression]? ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ReturnStatement extends Statement {
-  /**
-   * Return the expression computing the value to be returned, or `null` if no
-   * explicit value was provided.
-   */
+/// A return statement.
+///
+///    returnStatement ::=
+///        'return' [Expression]? ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ReturnStatement implements Statement {
+  /// Return the expression computing the value to be returned, or `null` if no
+  /// explicit value was provided.
   Expression get expression;
 
-  /**
-   * Set the expression computing the value to be returned to the given
-   * [expression].
-   */
+  /// Set the expression computing the value to be returned to the given
+  /// [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the token representing the 'return' keyword.
-   */
+  /// Return the token representing the 'return' keyword.
   Token get returnKeyword;
 
-  /**
-   * Set the token representing the 'return' keyword to the given [token].
-   */
+  /// Set the token representing the 'return' keyword to the given [token].
   void set returnKeyword(Token token);
 
-  /**
-   * Return the semicolon terminating the statement.
-   */
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 }
 
-/**
- * A script tag that can optionally occur at the beginning of a compilation unit.
- *
- *    scriptTag ::=
- *        '#!' (~NEWLINE)* NEWLINE
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ScriptTag extends AstNode {
-  /**
-   * Return the token representing this script tag.
-   */
+/// A script tag that can optionally occur at the beginning of a compilation
+/// unit.
+///
+///    scriptTag ::=
+///        '#!' (~NEWLINE)* NEWLINE
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ScriptTag implements AstNode {
+  /// Return the token representing this script tag.
   Token get scriptTag;
 
-  /**
-   * Set the token representing this script tag to the given [token].
-   */
+  /// Set the token representing this script tag to the given [token].
   void set scriptTag(Token token);
 }
 
-/**
- * A literal set.
- *
- *    setLiteral ::=
- *        'const'? ('<' [TypeAnnotation] '>')?
- *        '{' [Expression] (',' [Expression])* ','? '}'
- *      | 'const'? ('<' [TypeAnnotation] '>')? '{' '}'
- *
- * This is the class that is used to represent a set literal when neither the
- * 'control-flow-collections' nor 'spread-collections' experiments are enabled.
- * If either of those experiments are enabled, then [SetLiteral2] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SetLiteral extends TypedLiteral {
-  /**
-   * Return the expressions used to compute the elements of the set.
-   */
+/// A literal set.
+///
+///    setLiteral ::=
+///        'const'? ('<' [TypeAnnotation] '>')?
+///        '{' [Expression] (',' [Expression])* ','? '}'
+///      | 'const'? ('<' [TypeAnnotation] '>')? '{' '}'
+///
+/// This is the class that is used to represent a set literal when neither the
+/// 'control-flow-collections' nor 'spread-collections' experiments are enabled.
+/// If either of those experiments are enabled, then [SetLiteral2] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SetLiteral implements TypedLiteral {
+  /// Return the expressions used to compute the elements of the set.
   NodeList<Expression> get elements;
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A literal set.
- *
- *    setLiteral ::=
- *        'const'? ('<' [TypeAnnotation] '>')?
- *        '{' [CollectionElement] (',' [CollectionElement])* ','? '}'
- *      | 'const'? ('<' [TypeAnnotation] '>')? '{' '}'
- *
- * This is the class that is used to represent a set literal when either the
- * 'control-flow-collections' or 'spread-collections' experiments are enabled.
- * If neither of those experiments are enabled, then [SetLiteral] will be used.
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SetLiteral2 extends TypedLiteral {
-  /**
-   * Return the expressions used to compute the elements of the set.
-   */
+/// A literal set.
+///
+///    setLiteral ::=
+///        'const'? ('<' [TypeAnnotation] '>')?
+///        '{' [CollectionElement] (',' [CollectionElement])* ','? '}'
+///      | 'const'? ('<' [TypeAnnotation] '>')? '{' '}'
+///
+/// This is the class that is used to represent a set literal when either the
+/// 'control-flow-collections' or 'spread-collections' experiments are enabled.
+/// If neither of those experiments are enabled, then [SetLiteral] will be used.
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SetLiteral2 implements TypedLiteral {
+  /// Return the expressions used to compute the elements of the set.
   NodeList<CollectionElement> get elements;
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A combinator that restricts the names being imported to those in a given list.
- *
- *    showCombinator ::=
- *        'show' [SimpleIdentifier] (',' [SimpleIdentifier])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ShowCombinator extends Combinator {
-  /**
-   * Return the list of names from the library that are made visible by this
-   * combinator.
-   */
+/// A combinator that restricts the names being imported to those in a given list.
+///
+///    showCombinator ::=
+///        'show' [SimpleIdentifier] (',' [SimpleIdentifier])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ShowCombinator implements Combinator {
+  /// Return the list of names from the library that are made visible by this
+  /// combinator.
   NodeList<SimpleIdentifier> get shownNames;
 }
 
-/**
- * A simple formal parameter.
- *
- *    simpleFormalParameter ::=
- *        ('final' [TypeAnnotation] | 'var' | [TypeAnnotation])? [SimpleIdentifier]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SimpleFormalParameter extends NormalFormalParameter {
-  /**
-   * Return the token representing either the 'final', 'const' or 'var' keyword,
-   * or `null` if no keyword was used.
-   */
+/// A simple formal parameter.
+///
+///    simpleFormalParameter ::=
+///        ('final' [TypeAnnotation] | 'var' | [TypeAnnotation])? [SimpleIdentifier]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SimpleFormalParameter implements NormalFormalParameter {
+  /// Return the token representing either the 'final', 'const' or 'var'
+  /// keyword, or `null` if no keyword was used.
   Token get keyword;
 
-  /**
-   * Set the token representing either the 'final', 'const' or 'var' keyword to
-   * the given [token].
-   */
+  /// Set the token representing either the 'final', 'const' or 'var' keyword to
+  /// the given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the declared type of the parameter, or `null` if the parameter does
-   * not have a declared type.
-   */
+  /// Return the declared type of the parameter, or `null` if the parameter does
+  /// not have a declared type.
   TypeAnnotation get type;
 
-  /**
-   * Set the declared type of the parameter to the given [type].
-   */
+  /// Set the declared type of the parameter to the given [type].
   void set type(TypeAnnotation type);
 }
 
-/**
- * A simple identifier.
- *
- *    simpleIdentifier ::=
- *        initialCharacter internalCharacter*
- *
- *    initialCharacter ::= '_' | '$' | letter
- *
- *    internalCharacter ::= '_' | '$' | letter | digit
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SimpleIdentifier extends Identifier {
-  /**
-   * Return the auxiliary elements associated with this identifier, or `null` if
-   * this identifier is not in both a getter and setter context. The auxiliary
-   * elements hold the static and propagated elements associated with the getter
-   * context.
-   */
+/// A simple identifier.
+///
+///    simpleIdentifier ::=
+///        initialCharacter internalCharacter*
+///
+///    initialCharacter ::= '_' | '$' | letter
+///
+///    internalCharacter ::= '_' | '$' | letter | digit
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SimpleIdentifier implements Identifier {
+  /// Return the auxiliary elements associated with this identifier, or `null`
+  /// if this identifier is not in both a getter and setter context. The
+  /// auxiliary elements hold the static and propagated elements associated with
+  /// the getter context.
   // TODO(brianwilkerson) Replace this API.
   AuxiliaryElements get auxiliaryElements;
 
-  /**
-   * Set the auxiliary elements associated with this identifier to the given
-   * [elements].
-   */
+  /// Set the auxiliary elements associated with this identifier to the given
+  /// [elements].
   // TODO(brianwilkerson) Replace this API.
   void set auxiliaryElements(AuxiliaryElements elements);
 
-  /**
-   * Return `true` if this identifier is the "name" part of a prefixed
-   * identifier or a method invocation.
-   */
+  /// Return `true` if this identifier is the "name" part of a prefixed
+  /// identifier or a method invocation.
   bool get isQualified;
 
-  /**
-   * Set the element associated with this identifier based on propagated type
-   * information to the given [element].
-   *
-   * Deprecated: The analyzer no longer computes propagated type information.
-   * Use [staticElement] instead.
-   */
+  /// Set the element associated with this identifier based on propagated type
+  /// information to the given [element].
+  ///
+  /// Deprecated: The analyzer no longer computes propagated type information.
+  /// Use [staticElement] instead.
   @deprecated
   void set propagatedElement(Element element);
 
-  /**
-   * Set the element associated with this identifier based on static type
-   * information to the given [element].
-   */
+  /// Set the element associated with this identifier based on static type
+  /// information to the given [element].
   void set staticElement(Element element);
 
-  /**
-   * Return the token representing the identifier.
-   */
+  /// Return the token representing the identifier.
   Token get token;
 
-  /**
-   * Set the token representing the identifier to the given [token].
-   */
+  /// Set the token representing the identifier to the given [token].
   void set token(Token token);
 
-  /**
-   * Return `true` if this identifier is the name being declared in a
-   * declaration.
-   */
+  /// Return `true` if this identifier is the name being declared in a
+  /// declaration.
   // TODO(brianwilkerson) Convert this to a getter.
   bool inDeclarationContext();
 
-  /**
-   * Return `true` if this expression is computing a right-hand value.
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
+  /// Return `true` if this expression is computing a right-hand value.
+  ///
+  /// Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+  /// are they mutually exclusive. In other words, it is possible for both
+  /// methods to return `true` when invoked on the same node.
   // TODO(brianwilkerson) Convert this to a getter.
   bool inGetterContext();
 
-  /**
-   * Return `true` if this expression is computing a left-hand value.
-   *
-   * Note that [inGetterContext] and [inSetterContext] are not opposites, nor
-   * are they mutually exclusive. In other words, it is possible for both
-   * methods to return `true` when invoked on the same node.
-   */
+  /// Return `true` if this expression is computing a left-hand value.
+  ///
+  /// Note that [inGetterContext] and [inSetterContext] are not opposites, nor
+  /// are they mutually exclusive. In other words, it is possible for both
+  /// methods to return `true` when invoked on the same node.
   // TODO(brianwilkerson) Convert this to a getter.
   bool inSetterContext();
 }
 
-/**
- * A string literal expression that does not contain any interpolations.
- *
- *    simpleStringLiteral ::=
- *        rawStringLiteral
- *      | basicStringLiteral
- *
- *    rawStringLiteral ::=
- *        'r' basicStringLiteral
- *
- *    simpleStringLiteral ::=
- *        multiLineStringLiteral
- *      | singleLineStringLiteral
- *
- *    multiLineStringLiteral ::=
- *        "'''" characters "'''"
- *      | '"""' characters '"""'
- *
- *    singleLineStringLiteral ::=
- *        "'" characters "'"
- *      | '"' characters '"'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SimpleStringLiteral extends SingleStringLiteral {
-  /**
-   * Return the token representing the literal.
-   */
+/// A string literal expression that does not contain any interpolations.
+///
+///    simpleStringLiteral ::=
+///        rawStringLiteral
+///      | basicStringLiteral
+///
+///    rawStringLiteral ::=
+///        'r' basicStringLiteral
+///
+///    simpleStringLiteral ::=
+///        multiLineStringLiteral
+///      | singleLineStringLiteral
+///
+///    multiLineStringLiteral ::=
+///        "'''" characters "'''"
+///      | '"""' characters '"""'
+///
+///    singleLineStringLiteral ::=
+///        "'" characters "'"
+///      | '"' characters '"'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SimpleStringLiteral implements SingleStringLiteral {
+  /// Return the token representing the literal.
   Token get literal;
 
-  /**
-   * Set the token representing the literal to the given [token].
-   */
+  /// Set the token representing the literal to the given [token].
   void set literal(Token token);
 
-  /**
-   * Return the value of the literal.
-   */
+  /// Return the value of the literal.
   String get value;
 
-  /**
-   * Set the value of the literal to the given [string].
-   */
+  /// Set the value of the literal to the given [string].
   void set value(String string);
 }
 
-/**
- * A single string literal expression.
- *
- *    singleStringLiteral ::=
- *        [SimpleStringLiteral]
- *      | [StringInterpolation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SingleStringLiteral extends StringLiteral {
-  /**
-   * Return the offset of the after-last contents character.
-   */
+/// A single string literal expression.
+///
+///    singleStringLiteral ::=
+///        [SimpleStringLiteral]
+///      | [StringInterpolation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SingleStringLiteral implements StringLiteral {
+  /// Return the offset of the after-last contents character.
   int get contentsEnd;
 
-  /**
-   * Return the offset of the first contents character.
-   * If the string is multiline, then leading whitespaces are skipped.
-   */
+  /// Return the offset of the first contents character. If the string is
+  /// multiline, then leading whitespaces are skipped.
   int get contentsOffset;
 
-  /**
-   * Return `true` if this string literal is a multi-line string.
-   */
+  /// Return `true` if this string literal is a multi-line string.
   bool get isMultiline;
 
-  /**
-   * Return `true` if this string literal is a raw string.
-   */
+  /// Return `true` if this string literal is a raw string.
   bool get isRaw;
 
-  /**
-   * Return `true` if this string literal uses single quotes (' or ''').
-   * Return `false` if this string literal uses double quotes (" or """).
-   */
+  /// Return `true` if this string literal uses single quotes (' or '''), or
+  /// `false` if this string literal uses double quotes (" or """).
   bool get isSingleQuoted;
 }
 
-/**
- * A spread element.
- *
- *    spreadElement:
- *        ( '...' | '...?' ) [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SpreadElement implements CollectionElement, MapElement {
-  /**
-   * The expression used to compute the collection being spread.
-   */
+/// A spread element.
+///
+///    spreadElement:
+///        ( '...' | '...?' ) [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SpreadElement implements CollectionElement {
+  /// The expression used to compute the collection being spread.
   Expression get expression;
 
-  /**
-   * The spread operator, either '...' or '...?'.
-   */
+  /// The spread operator, either '...' or '...?'.
   Token get spreadOperator;
 }
 
-/**
- * A node that represents a statement.
- *
- *    statement ::=
- *        [Block]
- *      | [VariableDeclarationStatement]
- *      | [ForStatement]
- *      | [ForEachStatement]
- *      | [WhileStatement]
- *      | [DoStatement]
- *      | [SwitchStatement]
- *      | [IfStatement]
- *      | [TryStatement]
- *      | [BreakStatement]
- *      | [ContinueStatement]
- *      | [ReturnStatement]
- *      | [ExpressionStatement]
- *      | [FunctionDeclarationStatement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class Statement extends AstNode {
-  /**
-   * If this is a labeled statement, return the unlabeled portion of the
-   * statement, otherwise return the statement itself.
-   */
+/// A node that represents a statement.
+///
+///    statement ::=
+///        [Block]
+///      | [VariableDeclarationStatement]
+///      | [ForStatement]
+///      | [ForEachStatement]
+///      | [WhileStatement]
+///      | [DoStatement]
+///      | [SwitchStatement]
+///      | [IfStatement]
+///      | [TryStatement]
+///      | [BreakStatement]
+///      | [ContinueStatement]
+///      | [ReturnStatement]
+///      | [ExpressionStatement]
+///      | [FunctionDeclarationStatement]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class Statement implements AstNode {
+  /// If this is a labeled statement, return the unlabeled portion of the
+  /// statement, otherwise return the statement itself.
   Statement get unlabeled;
 }
 
-/**
- * A string interpolation literal.
- *
- *    stringInterpolation ::=
- *        ''' [InterpolationElement]* '''
- *      | '"' [InterpolationElement]* '"'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class StringInterpolation extends SingleStringLiteral {
-  /**
-   * Return the elements that will be composed to produce the resulting string.
-   */
+/// A string interpolation literal.
+///
+///    stringInterpolation ::=
+///        ''' [InterpolationElement]* '''
+///      | '"' [InterpolationElement]* '"'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class StringInterpolation implements SingleStringLiteral {
+  /// Return the elements that will be composed to produce the resulting string.
   NodeList<InterpolationElement> get elements;
 }
 
-/**
- * A string literal expression.
- *
- *    stringLiteral ::=
- *        [SimpleStringLiteral]
- *      | [AdjacentStrings]
- *      | [StringInterpolation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class StringLiteral extends Literal {
-  /**
-   * Return the value of the string literal, or `null` if the string is not a
-   * constant string without any string interpolation.
-   */
+/// A string literal expression.
+///
+///    stringLiteral ::=
+///        [SimpleStringLiteral]
+///      | [AdjacentStrings]
+///      | [StringInterpolation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class StringLiteral implements Literal {
+  /// Return the value of the string literal, or `null` if the string is not a
+  /// constant string without any string interpolation.
   String get stringValue;
 }
 
-/**
- * The invocation of a superclass' constructor from within a constructor's
- * initialization list.
- *
- *    superInvocation ::=
- *        'super' ('.' [SimpleIdentifier])? [ArgumentList]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SuperConstructorInvocation extends ConstructorInitializer
-    implements ConstructorReferenceNode {
-  /**
-   * Return the list of arguments to the constructor.
-   */
+/// The invocation of a superclass' constructor from within a constructor's
+/// initialization list.
+///
+///    superInvocation ::=
+///        'super' ('.' [SimpleIdentifier])? [ArgumentList]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SuperConstructorInvocation
+    implements ConstructorInitializer, ConstructorReferenceNode {
+  /// Return the list of arguments to the constructor.
   ArgumentList get argumentList;
 
-  /**
-   * Set the list of arguments to the constructor to the given [argumentList].
-   */
+  /// Set the list of arguments to the constructor to the given [argumentList].
   void set argumentList(ArgumentList argumentList);
 
-  /**
-   * Return the name of the constructor that is being invoked, or `null` if the
-   * unnamed constructor is being invoked.
-   */
+  /// Return the name of the constructor that is being invoked, or `null` if the
+  /// unnamed constructor is being invoked.
   SimpleIdentifier get constructorName;
 
-  /**
-   * Set the name of the constructor that is being invoked to the given
-   * [identifier].
-   */
+  /// Set the name of the constructor that is being invoked to the given
+  /// [identifier].
   void set constructorName(SimpleIdentifier identifier);
 
-  /**
-   * Return the token for the period before the name of the constructor that is
-   * being invoked, or `null` if the unnamed constructor is being invoked.
-   */
+  /// Return the token for the period before the name of the constructor that is
+  /// being invoked, or `null` if the unnamed constructor is being invoked.
   Token get period;
 
-  /**
-   * Set the token for the period before the name of the constructor that is
-   * being invoked to the given [token].
-   */
+  /// Set the token for the period before the name of the constructor that is
+  /// being invoked to the given [token].
   void set period(Token token);
 
-  /**
-   * Return the token for the 'super' keyword.
-   */
+  /// Return the token for the 'super' keyword.
   Token get superKeyword;
 
-  /**
-   * Set the token for the 'super' keyword to the given [token].
-   */
+  /// Set the token for the 'super' keyword to the given [token].
   void set superKeyword(Token token);
 }
 
-/**
- * A super expression.
- *
- *    superExpression ::=
- *        'super'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SuperExpression extends Expression {
-  /**
-   * Return the token representing the 'super' keyword.
-   */
+/// A super expression.
+///
+///    superExpression ::=
+///        'super'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SuperExpression implements Expression {
+  /// Return the token representing the 'super' keyword.
   Token get superKeyword;
 
-  /**
-   * Set the token representing the 'super' keyword to the given [token].
-   */
+  /// Set the token representing the 'super' keyword to the given [token].
   void set superKeyword(Token token);
 }
 
-/**
- * A case in a switch statement.
- *
- *    switchCase ::=
- *        [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SwitchCase extends SwitchMember {
-  /**
-   * Return the expression controlling whether the statements will be executed.
-   */
+/// A case in a switch statement.
+///
+///    switchCase ::=
+///        [SimpleIdentifier]* 'case' [Expression] ':' [Statement]*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SwitchCase implements SwitchMember {
+  /// Return the expression controlling whether the statements will be executed.
   Expression get expression;
 
-  /**
-   * Set the expression controlling whether the statements will be executed to
-   * the given [expression].
-   */
+  /// Set the expression controlling whether the statements will be executed to
+  /// the given [expression].
   void set expression(Expression expression);
 }
 
-/**
- * The default case in a switch statement.
- *
- *    switchDefault ::=
- *        [SimpleIdentifier]* 'default' ':' [Statement]*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SwitchDefault extends SwitchMember {}
+/// The default case in a switch statement.
+///
+///    switchDefault ::=
+///        [SimpleIdentifier]* 'default' ':' [Statement]*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SwitchDefault implements SwitchMember {}
 
-/**
- * An element within a switch statement.
- *
- *    switchMember ::=
- *        switchCase
- *      | switchDefault
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SwitchMember extends AstNode {
-  /**
-   * Return the colon separating the keyword or the expression from the
-   * statements.
-   */
+/// An element within a switch statement.
+///
+///    switchMember ::=
+///        switchCase
+///      | switchDefault
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SwitchMember implements AstNode {
+  /// Return the colon separating the keyword or the expression from the
+  /// statements.
   Token get colon;
 
-  /**
-   * Set the colon separating the keyword or the expression from the
-   * statements to the given [token].
-   */
+  /// Set the colon separating the keyword or the expression from the
+  /// statements to the given [token].
   void set colon(Token token);
 
-  /**
-   * Return the token representing the 'case' or 'default' keyword.
-   */
+  /// Return the token representing the 'case' or 'default' keyword.
   Token get keyword;
 
-  /**
-   * Set the token representing the 'case' or 'default' keyword to the given
-   * [token].
-   */
+  /// Set the token representing the 'case' or 'default' keyword to the given
+  /// [token].
   void set keyword(Token token);
 
-  /**
-   * Return the labels associated with the switch member.
-   */
+  /// Return the labels associated with the switch member.
   NodeList<Label> get labels;
 
-  /**
-   * Return the statements that will be executed if this switch member is
-   * selected.
-   */
+  /// Return the statements that will be executed if this switch member is
+  /// selected.
   NodeList<Statement> get statements;
 }
 
-/**
- * A switch statement.
- *
- *    switchStatement ::=
- *        'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SwitchStatement extends Statement {
-  /**
-   * Return the expression used to determine which of the switch members will be
-   * selected.
-   */
+/// A switch statement.
+///
+///    switchStatement ::=
+///        'switch' '(' [Expression] ')' '{' [SwitchCase]* [SwitchDefault]? '}'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SwitchStatement implements Statement {
+  /// Return the expression used to determine which of the switch members will
+  /// be selected.
   Expression get expression;
 
-  /**
-   * Set the expression used to determine which of the switch members will be
-   * selected to the given [expression].
-   */
+  /// Set the expression used to determine which of the switch members will be
+  /// selected to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the left curly bracket.
-   */
+  /// Return the left curly bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left curly bracket to the given [token].
-   */
+  /// Set the left curly bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the switch members that can be selected by the expression.
-   */
+  /// Return the switch members that can be selected by the expression.
   NodeList<SwitchMember> get members;
 
-  /**
-   * Return the right curly bracket.
-   */
+  /// Return the right curly bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right curly bracket to the given [token].
-   */
+  /// Set the right curly bracket to the given [token].
   void set rightBracket(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the token representing the 'switch' keyword.
-   */
+  /// Return the token representing the 'switch' keyword.
   Token get switchKeyword;
 
-  /**
-   * Set the token representing the 'switch' keyword to the given [token].
-   */
+  /// Set the token representing the 'switch' keyword to the given [token].
   void set switchKeyword(Token token);
 }
 
-/**
- * A symbol literal expression.
- *
- *    symbolLiteral ::=
- *        '#' (operator | (identifier ('.' identifier)*))
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class SymbolLiteral extends Literal {
-  /**
-   * Return the components of the literal.
-   */
+/// A symbol literal expression.
+///
+///    symbolLiteral ::=
+///        '#' (operator | (identifier ('.' identifier)*))
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class SymbolLiteral implements Literal {
+  /// Return the components of the literal.
   List<Token> get components;
 
-  /**
-   * Return the token introducing the literal.
-   */
+  /// Return the token introducing the literal.
   Token get poundSign;
 
-  /**
-   * Set the token introducing the literal to the given [token].
-   */
+  /// Set the token introducing the literal to the given [token].
   void set poundSign(Token token);
 }
 
-/**
- * A this expression.
- *
- *    thisExpression ::=
- *        'this'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ThisExpression extends Expression {
-  /**
-   * Return the token representing the 'this' keyword.
-   */
+/// A this expression.
+///
+///    thisExpression ::=
+///        'this'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ThisExpression implements Expression {
+  /// Return the token representing the 'this' keyword.
   Token get thisKeyword;
 
-  /**
-   * Set the token representing the 'this' keyword to the given [token].
-   */
+  /// Set the token representing the 'this' keyword to the given [token].
   void set thisKeyword(Token token);
 }
 
-/**
- * A throw expression.
- *
- *    throwExpression ::=
- *        'throw' [Expression]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class ThrowExpression extends Expression {
-  /**
-   * Return the expression computing the exception to be thrown.
-   */
+/// A throw expression.
+///
+///    throwExpression ::=
+///        'throw' [Expression]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class ThrowExpression implements Expression {
+  /// Return the expression computing the exception to be thrown.
   Expression get expression;
 
-  /**
-   * Set the expression computing the exception to be thrown to the given
-   * [expression].
-   */
+  /// Set the expression computing the exception to be thrown to the given
+  /// [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the token representing the 'throw' keyword.
-   */
+  /// Return the token representing the 'throw' keyword.
   Token get throwKeyword;
 
-  /**
-   * Set the token representing the 'throw' keyword to the given [token].
-   */
+  /// Set the token representing the 'throw' keyword to the given [token].
   void set throwKeyword(Token token);
 }
 
-/**
- * The declaration of one or more top-level variables of the same type.
- *
- *    topLevelVariableDeclaration ::=
- *        ('final' | 'const') type? staticFinalDeclarationList ';'
- *      | variableDeclaration ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TopLevelVariableDeclaration extends CompilationUnitMember {
-  /**
-   * Return the semicolon terminating the declaration.
-   */
+/// The declaration of one or more top-level variables of the same type.
+///
+///    topLevelVariableDeclaration ::=
+///        ('final' | 'const') type? staticFinalDeclarationList ';'
+///      | variableDeclaration ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TopLevelVariableDeclaration implements CompilationUnitMember {
+  /// Return the semicolon terminating the declaration.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the declaration to the given [token].
-   */
+  /// Set the semicolon terminating the declaration to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the top-level variables being declared.
-   */
+  /// Return the top-level variables being declared.
   VariableDeclarationList get variables;
 
-  /**
-   * Set the top-level variables being declared to the given list of
-   * [variables].
-   */
+  /// Set the top-level variables being declared to the given list of
+  /// [variables].
   void set variables(VariableDeclarationList variables);
 }
 
-/**
- * A try statement.
- *
- *    tryStatement ::=
- *        'try' [Block] ([CatchClause]+ finallyClause? | finallyClause)
- *
- *    finallyClause ::=
- *        'finally' [Block]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TryStatement extends Statement {
-  /**
-   * Return the body of the statement.
-   */
+/// A try statement.
+///
+///    tryStatement ::=
+///        'try' [Block] ([CatchClause]+ finallyClause? | finallyClause)
+///
+///    finallyClause ::=
+///        'finally' [Block]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TryStatement implements Statement {
+  /// Return the body of the statement.
   Block get body;
 
-  /**
-   * Set the body of the statement to the given [block].
-   */
+  /// Set the body of the statement to the given [block].
   void set body(Block block);
 
-  /**
-   * Return the catch clauses contained in the try statement.
-   */
+  /// Return the catch clauses contained in the try statement.
   NodeList<CatchClause> get catchClauses;
 
-  /**
-   * Return the finally block contained in the try statement, or `null` if the
-   * statement does not contain a finally clause.
-   */
+  /// Return the finally block contained in the try statement, or `null` if the
+  /// statement does not contain a finally clause.
   Block get finallyBlock;
 
-  /**
-   * Set the finally block contained in the try statement to the given [block].
-   */
+  /// Set the finally block contained in the try statement to the given [block].
   void set finallyBlock(Block block);
 
-  /**
-   * Return the token representing the 'finally' keyword, or `null` if the
-   * statement does not contain a finally clause.
-   */
+  /// Return the token representing the 'finally' keyword, or `null` if the
+  /// statement does not contain a finally clause.
   Token get finallyKeyword;
 
-  /**
-   * Set the token representing the 'finally' keyword to the given [token].
-   */
+  /// Set the token representing the 'finally' keyword to the given [token].
   void set finallyKeyword(Token token);
 
-  /**
-   * Return the token representing the 'try' keyword.
-   */
+  /// Return the token representing the 'try' keyword.
   Token get tryKeyword;
 
-  /**
-   * Set the token representing the 'try' keyword to the given [token].
-   */
+  /// Set the token representing the 'try' keyword to the given [token].
   void set tryKeyword(Token token);
 }
 
-/**
- * The declaration of a type alias.
- *
- *    typeAlias ::=
- *        'typedef' typeAliasBody
- *
- *    typeAliasBody ::=
- *        classTypeAlias
- *      | functionTypeAlias
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeAlias extends NamedCompilationUnitMember {
-  /**
-   * Return the semicolon terminating the declaration.
-   */
+/// The declaration of a type alias.
+///
+///    typeAlias ::=
+///        'typedef' typeAliasBody
+///
+///    typeAliasBody ::=
+///        classTypeAlias
+///      | functionTypeAlias
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeAlias implements NamedCompilationUnitMember {
+  /// Return the semicolon terminating the declaration.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the declaration to the given [token].
-   */
+  /// Set the semicolon terminating the declaration to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the token representing the 'typedef' keyword.
-   */
+  /// Return the token representing the 'typedef' keyword.
   Token get typedefKeyword;
 
-  /**
-   * Set the token representing the 'typedef' keyword to the given [token].
-   */
+  /// Set the token representing the 'typedef' keyword to the given [token].
   void set typedefKeyword(Token token);
 }
 
-/**
- * A type annotation.
- *
- *    type ::=
- *        [NamedType]
- *      | [GenericFunctionType]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeAnnotation extends AstNode {
-  /**
-   * Return the type being named, or `null` if the AST structure has not been
-   * resolved.
-   */
+/// A type annotation.
+///
+///    type ::=
+///        [NamedType]
+///      | [GenericFunctionType]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeAnnotation implements AstNode {
+  /// The question mark indicating that the type is nullable, or `null` if there
+  /// is no question mark.
+  Token get question;
+
+  /// Return the type being named, or `null` if the AST structure has not been
+  /// resolved.
   DartType get type;
 }
 
-/**
- * A list of type arguments.
- *
- *    typeArguments ::=
- *        '<' typeName (',' typeName)* '>'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeArgumentList extends AstNode {
-  /**
-   * Return the type arguments associated with the type.
-   */
+/// A list of type arguments.
+///
+///    typeArguments ::=
+///        '<' typeName (',' typeName)* '>'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeArgumentList implements AstNode {
+  /// Return the type arguments associated with the type.
   NodeList<TypeAnnotation> get arguments;
 
-  /**
-   * Return the left bracket.
-   */
+  /// Return the left bracket.
   Token get leftBracket;
 
-  /**
-   * Set the left bracket to the given [token].
-   */
+  /// Set the left bracket to the given [token].
   void set leftBracket(Token token);
 
-  /**
-   * Return the right bracket.
-   */
+  /// Return the right bracket.
   Token get rightBracket;
 
-  /**
-   * Set the right bracket to the given [token].
-   */
+  /// Set the right bracket to the given [token].
   void set rightBracket(Token token);
 }
 
-/**
- * A literal that has a type associated with it.
- *
- *    typedLiteral ::=
- *        [ListLiteral]
- *      | [MapLiteral]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypedLiteral extends Literal {
-  /**
-   * Return the token representing the 'const' keyword, or `null` if the literal
-   * is not a constant.
-   */
+/// A literal that has a type associated with it.
+///
+///    typedLiteral ::=
+///        [ListLiteral]
+///      | [MapLiteral]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypedLiteral implements Literal {
+  /// Return the token representing the 'const' keyword, or `null` if the
+  /// literal is not a constant.
   Token get constKeyword;
 
-  /**
-   * Set the token representing the 'const' keyword to the given [token].
-   */
+  /// Set the token representing the 'const' keyword to the given [token].
   void set constKeyword(Token token);
 
-  /**
-   * Return `true` if this literal is a constant expression, either because the
-   * keyword `const` was explicitly provided or because no keyword was provided
-   * and this expression is in a constant context.
-   */
+  /// Return `true` if this literal is a constant expression, either because the
+  /// keyword `const` was explicitly provided or because no keyword was provided
+  /// and this expression is in a constant context.
   bool get isConst;
 
-  /**
-   * Return the type argument associated with this literal, or `null` if no type
-   * arguments were declared.
-   */
+  /// Return the type argument associated with this literal, or `null` if no
+  /// type arguments were declared.
   TypeArgumentList get typeArguments;
 
-  /**
-   * Set the type argument associated with this literal to the given
-   * [typeArguments].
-   */
+  /// Set the type argument associated with this literal to the given
+  /// [typeArguments].
   void set typeArguments(TypeArgumentList typeArguments);
 }
 
-/**
- * The name of a type, which can optionally include type arguments.
- *
- *    typeName ::=
- *        [Identifier] typeArguments?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeName extends NamedType {}
+/// The name of a type, which can optionally include type arguments.
+///
+///    typeName ::=
+///        [Identifier] typeArguments?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeName implements NamedType {}
 
-/**
- * A type parameter.
- *
- *    typeParameter ::=
- *        [SimpleIdentifier] ('extends' [TypeAnnotation])?
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeParameter extends Declaration {
-  /**
-   * Return the upper bound for legal arguments, or `null` if there is no
-   * explicit upper bound.
-   */
+/// A type parameter.
+///
+///    typeParameter ::=
+///        [SimpleIdentifier] ('extends' [TypeAnnotation])?
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeParameter implements Declaration {
+  /// Return the upper bound for legal arguments, or `null` if there is no
+  /// explicit upper bound.
   TypeAnnotation get bound;
 
-  /**
-   * Set the upper bound for legal arguments to the given [type].
-   */
+  /// Set the upper bound for legal arguments to the given [type].
   void set bound(TypeAnnotation type);
 
-  /**
-   * Return the token representing the 'extends' keyword, or `null` if there is
-   * no explicit upper bound.
-   */
+  /// Return the token representing the 'extends' keyword, or `null` if there is
+  /// no explicit upper bound.
   Token get extendsKeyword;
 
-  /**
-   * Set the token representing the 'extends' keyword to the given [token].
-   */
+  /// Set the token representing the 'extends' keyword to the given [token].
   void set extendsKeyword(Token token);
 
-  /**
-   * Return the name of the type parameter.
-   */
+  /// Return the name of the type parameter.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the type parameter to the given [identifier].
-   */
+  /// Set the name of the type parameter to the given [identifier].
   void set name(SimpleIdentifier identifier);
 }
 
-/**
- * Type parameters within a declaration.
- *
- *    typeParameterList ::=
- *        '<' [TypeParameter] (',' [TypeParameter])* '>'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class TypeParameterList extends AstNode {
-  /**
-   * Return the left angle bracket.
-   */
+/// Type parameters within a declaration.
+///
+///    typeParameterList ::=
+///        '<' [TypeParameter] (',' [TypeParameter])* '>'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class TypeParameterList implements AstNode {
+  /// Return the left angle bracket.
   Token get leftBracket;
 
-  /**
-   * Return the right angle bracket.
-   */
+  /// Return the right angle bracket.
   Token get rightBracket;
 
-  /**
-   * Return the type parameters for the type.
-   */
+  /// Return the type parameters for the type.
   NodeList<TypeParameter> get typeParameters;
 }
 
-/**
- * A directive that references a URI.
- *
- *    uriBasedDirective ::=
- *        [ExportDirective]
- *      | [ImportDirective]
- *      | [PartDirective]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class UriBasedDirective extends Directive {
-  /**
-   * Return the source to which the URI was resolved.
-   */
+/// A directive that references a URI.
+///
+///    uriBasedDirective ::=
+///        [ExportDirective]
+///      | [ImportDirective]
+///      | [PartDirective]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class UriBasedDirective implements Directive {
+  /// Return the source to which the URI was resolved.
   @deprecated
   Source get source;
 
-  /**
-   * Set the source to which the URI was resolved to the given [source].
-   */
+  /// Set the source to which the URI was resolved to the given [source].
   @deprecated
   void set source(Source source);
 
-  /**
-   * Return the URI referenced by this directive.
-   */
+  /// Return the URI referenced by this directive.
   StringLiteral get uri;
 
-  /**
-   * Set the URI referenced by this directive to the given [uri].
-   */
+  /// Set the URI referenced by this directive to the given [uri].
   void set uri(StringLiteral uri);
 
-  /**
-   * Return the content of the [uri].
-   */
+  /// Return the content of the [uri].
   String get uriContent;
 
-  /**
-   * Set the content of the [uri] to the given [content].
-   */
+  /// Set the content of the [uri] to the given [content].
   void set uriContent(String content);
 
-  /**
-   * Return the element associated with the [uri] of this directive, or `null`
-   * if the AST structure has not been resolved or if the URI could not be
-   * resolved. Examples of the latter case include a directive that contains an
-   * invalid URL or a URL that does not exist.
-   */
+  /// Return the element associated with the [uri] of this directive, or `null`
+  /// if the AST structure has not been resolved or if the URI could not be
+  /// resolved. Examples of the latter case include a directive that contains an
+  /// invalid URL or a URL that does not exist.
   Element get uriElement;
 
-  /**
-   * Return the source to which the [uri] was resolved.
-   */
+  /// Return the source to which the [uri] was resolved.
   Source get uriSource;
 
-  /**
-   * Set the source to which the [uri] was resolved to the given [source].
-   */
+  /// Set the source to which the [uri] was resolved to the given [source].
   void set uriSource(Source source);
 }
 
-/**
- * An identifier that has an initial value associated with it. Instances of this
- * class are always children of the class [VariableDeclarationList].
- *
- *    variableDeclaration ::=
- *        [SimpleIdentifier] ('=' [Expression])?
- *
- * TODO(paulberry): the grammar does not allow metadata to be associated with
- * a VariableDeclaration, and currently we don't record comments for it either.
- * Consider changing the class hierarchy so that [VariableDeclaration] does not
- * extend [Declaration].
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class VariableDeclaration extends Declaration {
+/// An identifier that has an initial value associated with it. Instances of
+/// this class are always children of the class [VariableDeclarationList].
+///
+///    variableDeclaration ::=
+///        [SimpleIdentifier] ('=' [Expression])?
+///
+/// TODO(paulberry): the grammar does not allow metadata to be associated with
+/// a VariableDeclaration, and currently we don't record comments for it either.
+/// Consider changing the class hierarchy so that [VariableDeclaration] does not
+/// extend [Declaration].
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class VariableDeclaration implements Declaration {
   @override
   VariableElement get declaredElement;
 
@@ -7579,275 +5411,186 @@
   @override
   VariableElement get element;
 
-  /**
-   * Return the equal sign separating the variable name from the initial value,
-   * or `null` if the initial value was not specified.
-   */
+  /// Return the equal sign separating the variable name from the initial value,
+  /// or `null` if the initial value was not specified.
   Token get equals;
 
-  /**
-   * Set the equal sign separating the variable name from the initial value to
-   * the given [token].
-   */
+  /// Set the equal sign separating the variable name from the initial value to
+  /// the given [token].
   void set equals(Token token);
 
-  /**
-   * Return the expression used to compute the initial value for the variable,
-   * or `null` if the initial value was not specified.
-   */
+  /// Return the expression used to compute the initial value for the variable,
+  /// or `null` if the initial value was not specified.
   Expression get initializer;
 
-  /**
-   * Set the expression used to compute the initial value for the variable to
-   * the given [expression].
-   */
+  /// Set the expression used to compute the initial value for the variable to
+  /// the given [expression].
   void set initializer(Expression expression);
 
-  /**
-   * Return `true` if this variable was declared with the 'const' modifier.
-   */
+  /// Return `true` if this variable was declared with the 'const' modifier.
   bool get isConst;
 
-  /**
-   * Return `true` if this variable was declared with the 'final' modifier.
-   * Variables that are declared with the 'const' modifier will return `false`
-   * even though they are implicitly final.
-   */
+  /// Return `true` if this variable was declared with the 'final' modifier.
+  /// Variables that are declared with the 'const' modifier will return `false`
+  /// even though they are implicitly final.
   bool get isFinal;
 
-  /**
-   * Return the name of the variable being declared.
-   */
+  /// Return the name of the variable being declared.
   SimpleIdentifier get name;
 
-  /**
-   * Set the name of the variable being declared to the given [identifier].
-   */
+  /// Set the name of the variable being declared to the given [identifier].
   void set name(SimpleIdentifier identifier);
 }
 
-/**
- * The declaration of one or more variables of the same type.
- *
- *    variableDeclarationList ::=
- *        finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
- *
- *    finalConstVarOrType ::=
- *      | 'final' [TypeAnnotation]?
- *      | 'const' [TypeAnnotation]?
- *      | 'var'
- *      | [TypeAnnotation]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class VariableDeclarationList extends AnnotatedNode {
-  /**
-   * Return `true` if the variables in this list were declared with the 'const'
-   * modifier.
-   */
+/// The declaration of one or more variables of the same type.
+///
+///    variableDeclarationList ::=
+///        finalConstVarOrType [VariableDeclaration] (',' [VariableDeclaration])*
+///
+///    finalConstVarOrType ::=
+///      | 'final' [TypeAnnotation]?
+///      | 'const' [TypeAnnotation]?
+///      | 'var'
+///      | [TypeAnnotation]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class VariableDeclarationList implements AnnotatedNode {
+  /// Return `true` if the variables in this list were declared with the 'const'
+  /// modifier.
   bool get isConst;
 
-  /**
-   * Return `true` if the variables in this list were declared with the 'final'
-   * modifier. Variables that are declared with the 'const' modifier will return
-   * `false` even though they are implicitly final. (In other words, this is a
-   * syntactic check rather than a semantic check.)
-   */
+  /// Return `true` if the variables in this list were declared with the 'final'
+  /// modifier. Variables that are declared with the 'const' modifier will
+  /// return `false` even though they are implicitly final. (In other words,
+  /// this is a syntactic check rather than a semantic check.)
   bool get isFinal;
 
-  /**
-   * Return the token representing the 'final', 'const' or 'var' keyword, or
-   * `null` if no keyword was included.
-   */
+  /// Return the token representing the 'final', 'const' or 'var' keyword, or
+  /// `null` if no keyword was included.
   Token get keyword;
 
-  /**
-   * Set the token representing the 'final', 'const' or 'var' keyword to the
-   * given [token].
-   */
+  /// Set the token representing the 'final', 'const' or 'var' keyword to the
+  /// given [token].
   void set keyword(Token token);
 
-  /**
-   * Return the type of the variables being declared, or `null` if no type was
-   * provided.
-   */
+  /// Return the type of the variables being declared, or `null` if no type was
+  /// provided.
   TypeAnnotation get type;
 
-  /**
-   * Set the type of the variables being declared to the given [type].
-   */
+  /// Set the type of the variables being declared to the given [type].
   void set type(TypeAnnotation type);
 
-  /**
-   * Return a list containing the individual variables being declared.
-   */
+  /// Return a list containing the individual variables being declared.
   NodeList<VariableDeclaration> get variables;
 }
 
-/**
- * A list of variables that are being declared in a context where a statement is
- * required.
- *
- *    variableDeclarationStatement ::=
- *        [VariableDeclarationList] ';'
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class VariableDeclarationStatement extends Statement {
-  /**
-   * Return the semicolon terminating the statement.
-   */
+/// A list of variables that are being declared in a context where a statement
+/// is required.
+///
+///    variableDeclarationStatement ::=
+///        [VariableDeclarationList] ';'
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class VariableDeclarationStatement implements Statement {
+  /// Return the semicolon terminating the statement.
   Token get semicolon;
 
-  /**
-   * Set the semicolon terminating the statement to the given [token].
-   */
+  /// Set the semicolon terminating the statement to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the variables being declared.
-   */
+  /// Return the variables being declared.
   VariableDeclarationList get variables;
 
-  /**
-   * Set the variables being declared to the given list of [variables].
-   */
+  /// Set the variables being declared to the given list of [variables].
   void set variables(VariableDeclarationList variables);
 }
 
-/**
- * A while statement.
- *
- *    whileStatement ::=
- *        'while' '(' [Expression] ')' [Statement]
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class WhileStatement extends Statement {
-  /**
-   * Return the body of the loop.
-   */
+/// A while statement.
+///
+///    whileStatement ::=
+///        'while' '(' [Expression] ')' [Statement]
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class WhileStatement implements Statement {
+  /// Return the body of the loop.
   Statement get body;
 
-  /**
-   * Set the body of the loop to the given [statement].
-   */
+  /// Set the body of the loop to the given [statement].
   void set body(Statement statement);
 
-  /**
-   * Return the expression used to determine whether to execute the body of the
-   * loop.
-   */
+  /// Return the expression used to determine whether to execute the body of the
+  /// loop.
   Expression get condition;
 
-  /**
-   * Set the expression used to determine whether to execute the body of the
-   * loop to the given [expression].
-   */
+  /// Set the expression used to determine whether to execute the body of the
+  /// loop to the given [expression].
   void set condition(Expression expression);
 
-  /**
-   * Return the left parenthesis.
-   */
+  /// Return the left parenthesis.
   Token get leftParenthesis;
 
-  /**
-   * Set the left parenthesis to the given [token].
-   */
+  /// Set the left parenthesis to the given [token].
   void set leftParenthesis(Token token);
 
-  /**
-   * Return the right parenthesis.
-   */
+  /// Return the right parenthesis.
   Token get rightParenthesis;
 
-  /**
-   * Set the right parenthesis to the given [token].
-   */
+  /// Set the right parenthesis to the given [token].
   void set rightParenthesis(Token token);
 
-  /**
-   * Return the token representing the 'while' keyword.
-   */
+  /// Return the token representing the 'while' keyword.
   Token get whileKeyword;
 
-  /**
-   * Set the token representing the 'while' keyword to the given [token].
-   */
+  /// Set the token representing the 'while' keyword to the given [token].
   void set whileKeyword(Token token);
 }
 
-/**
- * The with clause in a class declaration.
- *
- *    withClause ::=
- *        'with' [TypeName] (',' [TypeName])*
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class WithClause extends AstNode {
-  /**
-   * Return the names of the mixins that were specified.
-   */
+/// The with clause in a class declaration.
+///
+///    withClause ::=
+///        'with' [TypeName] (',' [TypeName])*
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class WithClause implements AstNode {
+  /// Return the names of the mixins that were specified.
   NodeList<TypeName> get mixinTypes;
 
-  /**
-   * Return the token representing the 'with' keyword.
-   */
+  /// Return the token representing the 'with' keyword.
   Token get withKeyword;
 
-  /**
-   * Set the token representing the 'with' keyword to the given [token].
-   */
+  /// Set the token representing the 'with' keyword to the given [token].
   void set withKeyword(Token token);
 }
 
-/**
- * A yield statement.
- *
- *    yieldStatement ::=
- *        'yield' '*'? [Expression] ‘;’
- *
- * Clients may not extend, implement or mix-in this class.
- */
-abstract class YieldStatement extends Statement {
-  /**
-   * Return the expression whose value will be yielded.
-   */
+/// A yield statement.
+///
+///    yieldStatement ::=
+///        'yield' '*'? [Expression] ‘;’
+///
+/// Clients may not extend, implement or mix-in this class.
+abstract class YieldStatement implements Statement {
+  /// Return the expression whose value will be yielded.
   Expression get expression;
 
-  /**
-   * Set the expression whose value will be yielded to the given [expression].
-   */
+  /// Set the expression whose value will be yielded to the given [expression].
   void set expression(Expression expression);
 
-  /**
-   * Return the semicolon following the expression.
-   */
+  /// Return the semicolon following the expression.
   Token get semicolon;
 
-  /**
-   * Return the semicolon following the expression to the given [token].
-   */
+  /// Return the semicolon following the expression to the given [token].
   void set semicolon(Token token);
 
-  /**
-   * Return the star optionally following the 'yield' keyword.
-   */
+  /// Return the star optionally following the 'yield' keyword.
   Token get star;
 
-  /**
-   * Return the star optionally following the 'yield' keyword to the given [token].
-   */
+  /// Return the star optionally following the 'yield' keyword to the given
+  /// [token].
   void set star(Token token);
 
-  /**
-   * Return the 'yield' keyword.
-   */
+  /// Return the 'yield' keyword.
   Token get yieldKeyword;
 
-  /**
-   * Return the 'yield' keyword to the given [token].
-   */
+  /// Return the 'yield' keyword to the given [token].
   void set yieldKeyword(Token token);
 }
diff --git a/pkg/analyzer/lib/dart/ast/ast_factory.dart b/pkg/analyzer/lib/dart/ast/ast_factory.dart
index fee50cb..c888aac 100644
--- a/pkg/analyzer/lib/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/dart/ast/ast_factory.dart
@@ -185,31 +185,6 @@
       Token semicolon);
 
   /**
-   * Returns a newly created for element that can be part of a list or set
-   * literal.
-   */
-  CollectionForElement collectionForElement(
-      {Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      ForLoopParts forLoopParts,
-      Token rightParenthesis,
-      CollectionElement body});
-
-  /**
-   * Returns a newly created if element that can be part of a list or set
-   * literal.
-   */
-  CollectionIfElement collectionIfElement(
-      {Token ifKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token rightParenthesis,
-      CollectionElement thenElement,
-      Token elseKeyword,
-      CollectionElement elseElement});
-
-  /**
    * Returns a newly created reference to a Dart element. The [newKeyword]
    * can be `null` if the reference is not to a constructor.
    */
@@ -543,6 +518,18 @@
       Statement body);
 
   /**
+   * Returns a newly created for element that can be part of a list, map or set
+   * literal.
+   */
+  ForElement forElement(
+      {Token awaitKeyword,
+      Token forKeyword,
+      Token leftParenthesis,
+      ForLoopParts forLoopParts,
+      Token rightParenthesis,
+      CollectionElement body});
+
+  /**
    * Returns a newly created parameter list. The list of [parameters] can be
    * `null` if there are no parameters. The [leftDelimiter] and [rightDelimiter]
    * can be `null` if there are no optional parameters.
@@ -720,6 +707,19 @@
       Token keyword, List<SimpleIdentifier> hiddenNames);
 
   /**
+   * Returns a newly created if element that can be part of a list, map or set
+   * literal.
+   */
+  IfElement ifElement(
+      {Token ifKeyword,
+      Token leftParenthesis,
+      Expression condition,
+      Token rightParenthesis,
+      CollectionElement thenElement,
+      Token elseKeyword,
+      CollectionElement elseElement});
+
+  /**
    * Returns a newly created if statement. The [elseKeyword] and
    * [elseStatement] can be `null` if there is no else clause.
    */
@@ -844,29 +844,6 @@
       Token rightBracket});
 
   /**
-   * Returns a newly created for element that can be part of a map literal.
-   */
-  MapForElement mapForElement(
-      {Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      ForLoopParts forLoopParts,
-      Token rightParenthesis,
-      MapElement body});
-
-  /**
-   * Returns a newly created if element that can be part of a map literal.
-   */
-  MapIfElement mapIfElement(
-      {Token ifKeyword,
-      Token leftParenthesis,
-      Expression condition,
-      Token rightParenthesis,
-      MapElement thenElement,
-      Token elseKeyword,
-      MapElement elseElement});
-
-  /**
    * Returns a newly created map literal. The [constKeyword] can be `null` if
    * the literal is not a constant. The [typeArguments] can be `null` if no type
    * arguments were declared. The [entries] can be `null` if the map is empty.
@@ -881,7 +858,7 @@
       {Token constKeyword,
       TypeArgumentList typeArguments,
       Token leftBracket,
-      List<MapElement> entries,
+      List<CollectionElement> entries,
       Token rightBracket});
 
   /**
diff --git a/pkg/analyzer/lib/dart/ast/visitor.dart b/pkg/analyzer/lib/dart/ast/visitor.dart
index e1c77f4..4c599e8 100644
--- a/pkg/analyzer/lib/dart/ast/visitor.dart
+++ b/pkg/analyzer/lib/dart/ast/visitor.dart
@@ -205,13 +205,7 @@
   @override
   R visitClassTypeAlias(ClassTypeAlias node) => visitTypeAlias(node);
 
-  @override
-  R visitCollectionForElement(CollectionForElement node) =>
-      visitForElement<CollectionElement>(node);
-
-  @override
-  R visitCollectionIfElement(CollectionIfElement node) =>
-      visitIfElement<CollectionElement>(node);
+  R visitCollectionElement(CollectionElement node) => visitNode(node);
 
   R visitCombinator(Combinator node) => visitNode(node);
 
@@ -287,7 +281,7 @@
   @override
   R visitExportDirective(ExportDirective node) => visitNamespaceDirective(node);
 
-  R visitExpression(Expression node) => visitNode(node);
+  R visitExpression(Expression node) => visitCollectionElement(node);
 
   @override
   R visitExpressionFunctionBody(ExpressionFunctionBody node) =>
@@ -319,7 +313,8 @@
   @override
   R visitForEachStatement(ForEachStatement node) => visitStatement(node);
 
-  R visitForElement<E>(ForElement<E> node) => visitNode(node);
+  @override
+  R visitForElement(ForElement node) => visitCollectionElement(node);
 
   R visitFormalParameter(FormalParameter node) => visitNode(node);
 
@@ -378,7 +373,8 @@
 
   R visitIdentifier(Identifier node) => visitExpression(node);
 
-  R visitIfElement<E>(IfElement<E> node) => visitNode(node);
+  @override
+  R visitIfElement(IfElement node) => visitCollectionElement(node);
 
   @override
   R visitIfStatement(IfStatement node) => visitStatement(node);
@@ -436,19 +432,13 @@
   R visitLiteral(Literal node) => visitExpression(node);
 
   @override
-  R visitMapForElement(MapForElement node) => visitForElement<MapElement>(node);
-
-  @override
-  R visitMapIfElement(MapIfElement node) => visitIfElement<MapElement>(node);
-
-  @override
   R visitMapLiteral(MapLiteral node) => visitTypedLiteral(node);
 
   @override
   R visitMapLiteral2(MapLiteral2 node) => visitTypedLiteral(node);
 
   @override
-  R visitMapLiteralEntry(MapLiteralEntry node) => visitNode(node);
+  R visitMapLiteralEntry(MapLiteralEntry node) => visitCollectionElement(node);
 
   @override
   R visitMethodDeclaration(MethodDeclaration node) => visitClassMember(node);
@@ -550,7 +540,7 @@
       visitStringLiteral(node);
 
   @override
-  R visitSpreadElement(SpreadElement node) => visitNode(node);
+  R visitSpreadElement(SpreadElement node) => visitCollectionElement(node);
 
   R visitStatement(Statement node) => visitNode(node);
 
@@ -752,18 +742,6 @@
   }
 
   @override
-  R visitCollectionForElement(CollectionForElement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitCollectionIfElement(CollectionIfElement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
   R visitComment(Comment node) {
     node.visitChildren(this);
     return null;
@@ -926,6 +904,12 @@
   }
 
   @override
+  R visitForElement(ForElement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R visitFormalParameterList(FormalParameterList node) {
     node.visitChildren(this);
     return null;
@@ -1010,6 +994,12 @@
   }
 
   @override
+  R visitIfElement(IfElement node) {
+    node.visitChildren(this);
+    return null;
+  }
+
+  @override
   R visitIfStatement(IfStatement node) {
     node.visitChildren(this);
     return null;
@@ -1100,18 +1090,6 @@
   }
 
   @override
-  R visitMapForElement(MapForElement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
-  R visitMapIfElement(MapIfElement node) {
-    node.visitChildren(this);
-    return null;
-  }
-
-  @override
   R visitMapLiteral(MapLiteral node) {
     node.visitChildren(this);
     return null;
@@ -1474,12 +1452,6 @@
   R visitClassTypeAlias(ClassTypeAlias node) => null;
 
   @override
-  R visitCollectionForElement(CollectionForElement node) => null;
-
-  @override
-  R visitCollectionIfElement(CollectionIfElement node) => null;
-
-  @override
   R visitComment(Comment node) => null;
 
   @override
@@ -1561,6 +1533,9 @@
   R visitForEachStatement(ForEachStatement node) => null;
 
   @override
+  R visitForElement(ForElement node) => null;
+
+  @override
   R visitFormalParameterList(FormalParameterList node) => null;
 
   @override
@@ -1606,6 +1581,9 @@
   R visitHideCombinator(HideCombinator node) => null;
 
   @override
+  R visitIfElement(IfElement node) => null;
+
+  @override
   R visitIfStatement(IfStatement node) => null;
 
   @override
@@ -1651,12 +1629,6 @@
   R visitListLiteral2(ListLiteral2 node) => null;
 
   @override
-  R visitMapForElement(MapForElement node) => null;
-
-  @override
-  R visitMapIfElement(MapIfElement node) => null;
-
-  @override
   R visitMapLiteral(MapLiteral node) => null;
 
   @override
@@ -1872,12 +1844,6 @@
   R visitClassTypeAlias(ClassTypeAlias node) => _throw(node);
 
   @override
-  R visitCollectionForElement(CollectionForElement node) => _throw(node);
-
-  @override
-  R visitCollectionIfElement(CollectionIfElement node) => _throw(node);
-
-  @override
   R visitComment(Comment node) => _throw(node);
 
   @override
@@ -1962,6 +1928,9 @@
   R visitForEachStatement(ForEachStatement node) => _throw(node);
 
   @override
+  R visitForElement(ForElement node) => _throw(node);
+
+  @override
   R visitFormalParameterList(FormalParameterList node) => _throw(node);
 
   @override
@@ -2008,6 +1977,9 @@
   R visitHideCombinator(HideCombinator node) => _throw(node);
 
   @override
+  R visitIfElement(IfElement node) => _throw(node);
+
+  @override
   R visitIfStatement(IfStatement node) => _throw(node);
 
   @override
@@ -2054,12 +2026,6 @@
   R visitListLiteral2(ListLiteral2 node) => _throw(node);
 
   @override
-  R visitMapForElement(MapForElement node) => _throw(node);
-
-  @override
-  R visitMapIfElement(MapIfElement node) => _throw(node);
-
-  @override
   R visitMapLiteral(MapLiteral node) => _throw(node);
 
   @override
@@ -2378,22 +2344,6 @@
   }
 
   @override
-  T visitCollectionForElement(CollectionForElement node) {
-    stopwatch.start();
-    T result = _baseVisitor.visitCollectionForElement(node);
-    stopwatch.stop();
-    return result;
-  }
-
-  @override
-  T visitCollectionIfElement(CollectionIfElement node) {
-    stopwatch.start();
-    T result = _baseVisitor.visitCollectionIfElement(node);
-    stopwatch.stop();
-    return result;
-  }
-
-  @override
   T visitComment(Comment node) {
     stopwatch.start();
     T result = _baseVisitor.visitComment(node);
@@ -2610,6 +2560,14 @@
   }
 
   @override
+  T visitForElement(ForElement node) {
+    stopwatch.start();
+    T result = _baseVisitor.visitForElement(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T visitFormalParameterList(FormalParameterList node) {
     stopwatch.start();
     T result = _baseVisitor.visitFormalParameterList(node);
@@ -2722,6 +2680,14 @@
   }
 
   @override
+  T visitIfElement(IfElement node) {
+    stopwatch.start();
+    T result = _baseVisitor.visitIfElement(node);
+    stopwatch.stop();
+    return result;
+  }
+
+  @override
   T visitIfStatement(IfStatement node) {
     stopwatch.start();
     T result = _baseVisitor.visitIfStatement(node);
@@ -2842,22 +2808,6 @@
   }
 
   @override
-  T visitMapForElement(MapForElement node) {
-    stopwatch.start();
-    T result = _baseVisitor.visitMapForElement(node);
-    stopwatch.stop();
-    return result;
-  }
-
-  @override
-  T visitMapIfElement(MapIfElement node) {
-    stopwatch.start();
-    T result = _baseVisitor.visitMapIfElement(node);
-    stopwatch.stop();
-    return result;
-  }
-
-  @override
   T visitMapLiteral(MapLiteral node) {
     stopwatch.start();
     T result = _baseVisitor.visitMapLiteral(node);
@@ -3324,12 +3274,6 @@
   R visitClassTypeAlias(ClassTypeAlias node) => visitNode(node);
 
   @override
-  R visitCollectionForElement(CollectionForElement node) => visitNode(node);
-
-  @override
-  R visitCollectionIfElement(CollectionIfElement node) => visitNode(node);
-
-  @override
   R visitComment(Comment node) => visitNode(node);
 
   @override
@@ -3415,6 +3359,9 @@
   R visitForEachStatement(ForEachStatement node) => visitNode(node);
 
   @override
+  R visitForElement(ForElement node) => visitNode(node);
+
+  @override
   R visitFormalParameterList(FormalParameterList node) => visitNode(node);
 
   @override
@@ -3461,6 +3408,9 @@
   R visitHideCombinator(HideCombinator node) => visitNode(node);
 
   @override
+  R visitIfElement(IfElement node) => visitNode(node);
+
+  @override
   R visitIfStatement(IfStatement node) => visitNode(node);
 
   @override
@@ -3508,12 +3458,6 @@
   R visitListLiteral2(ListLiteral2 node) => visitNode(node);
 
   @override
-  R visitMapForElement(MapForElement node) => visitNode(node);
-
-  @override
-  R visitMapIfElement(MapIfElement node) => visitNode(node);
-
-  @override
   R visitMapLiteral(MapLiteral node) => visitNode(node);
 
   @override
diff --git a/pkg/analyzer/lib/error/error.dart b/pkg/analyzer/lib/error/error.dart
index 2a13c74..22efc18 100644
--- a/pkg/analyzer/lib/error/error.dart
+++ b/pkg/analyzer/lib/error/error.dart
@@ -299,6 +299,7 @@
   HintCode.INVALID_USE_OF_PROTECTED_MEMBER,
   HintCode.INVALID_USE_OF_VISIBLE_FOR_TEMPLATE_MEMBER,
   HintCode.INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER,
+  HintCode.INVALID_VISIBILITY_ANNOTATION,
   HintCode.IS_DOUBLE,
   HintCode.IS_INT,
   HintCode.IS_NOT_DOUBLE,
diff --git a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
index 220e865..52a6a24 100644
--- a/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/context_locator.dart
@@ -75,7 +75,7 @@
   @override
   List<AnalysisContext> locateContexts(
       {@required List<String> includedPaths,
-      List<String> excludedPaths: null,
+      List<String> excludedPaths: const <String>[],
       String optionsFile: null,
       String packagesFile: null,
       String sdkPath: null}) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/driver.dart b/pkg/analyzer/lib/src/dart/analysis/driver.dart
index 895a8ec..3081077 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 = 77;
+  static const int DATA_VERSION = 78;
 
   /**
    * The number of exception contexts allowed to write. Once this field is
@@ -344,6 +344,13 @@
   LibraryContext _libraryContext;
 
   /**
+   * This function is invoked when the current session is about to be discarded.
+   * The argument represents the path of the resource causing the session
+   * to be discarded or `null` if there are multiple or this is unknown.
+   */
+  void Function(String) onCurrentSessionAboutToBeDiscarded;
+
+  /**
    * Create a new instance of [AnalysisDriver].
    *
    * The given [SourceFactory] is cloned to ensure that it does not contain a
@@ -364,7 +371,7 @@
       : _logger = logger,
         _sourceFactory = sourceFactory.clone(),
         _externalSummaries = externalSummaries {
-    _createNewSession();
+    _createNewSession(null);
     _onResults = _resultController.stream.asBroadcastStream();
     _testView = new AnalysisDriverTestView(this);
     _createFileTracker();
@@ -1329,7 +1336,7 @@
   void resetUriResolution() {
     _fsState.resetUriResolution();
     _fileTracker.scheduleAllAddedFiles();
-    _changeHook();
+    _changeHook(null);
   }
 
   /**
@@ -1345,8 +1352,8 @@
    * Handles a notification from the [FileTracker] that there has been a change
    * of state.
    */
-  void _changeHook() {
-    _createNewSession();
+  void _changeHook(String path) {
+    _createNewSession(path);
     _libraryContext = null;
     _priorityResults.clear();
     _scheduler.notify(this);
@@ -1622,7 +1629,10 @@
   /**
    * Create a new analysis session, so invalidating the current one.
    */
-  void _createNewSession() {
+  void _createNewSession(String path) {
+    if (onCurrentSessionAboutToBeDiscarded != null) {
+      onCurrentSessionAboutToBeDiscarded(path);
+    }
     _currentSession = new AnalysisSessionImpl(this);
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/experiments.dart b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
index 4cdd478..5bf37c7 100644
--- a/pkg/analyzer/lib/src/dart/analysis/experiments.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/experiments.dart
@@ -70,30 +70,30 @@
         IsEnabledByDefault.constant_update_2018,
         IsExpired.constant_update_2018,
         'Q4 2018 Constant Update'),
-    EnableString.set_literals: const ExperimentalFeature(
-        1,
-        EnableString.set_literals,
-        IsEnabledByDefault.set_literals,
-        IsExpired.set_literals,
-        'Set Literals'),
     EnableString.non_nullable: const ExperimentalFeature(
-        2,
+        1,
         EnableString.non_nullable,
         IsEnabledByDefault.non_nullable,
         IsExpired.non_nullable,
         'Non Nullable'),
     EnableString.control_flow_collections: const ExperimentalFeature(
-        3,
+        2,
         EnableString.control_flow_collections,
         IsEnabledByDefault.control_flow_collections,
         IsExpired.control_flow_collections,
         'Control Flow Collections'),
     EnableString.spread_collections: const ExperimentalFeature(
-        4,
+        3,
         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.bogus_disabled: const ExperimentalFeature(
         null,
         EnableString.bogus_disabled,
@@ -120,7 +120,6 @@
       bool spread_collections})
       : _enableFlags = <bool>[
           constant_update_2018 ?? IsEnabledByDefault.constant_update_2018,
-          set_literals ?? IsEnabledByDefault.set_literals,
           non_nullable ?? IsEnabledByDefault.non_nullable,
           control_flow_collections ??
               IsEnabledByDefault.control_flow_collections,
@@ -147,16 +146,16 @@
   bool get constant_update_2018 => _enableFlags[0];
 
   /// Current state for the flag "control_flow_collections"
-  bool get control_flow_collections => _enableFlags[3];
+  bool get control_flow_collections => _enableFlags[2];
 
   /// Current state for the flag "non-nullable"
-  bool get non_nullable => _enableFlags[2];
+  bool get non_nullable => _enableFlags[1];
 
   /// Current state for the flag "set-literals"
-  bool get set_literals => _enableFlags[1];
+  bool get set_literals => true;
 
   /// Current state for the flag "spread_collections"
-  bool get spread_collections => _enableFlags[4];
+  bool get spread_collections => _enableFlags[3];
 
   /// Queries whether the given [feature] is enabled or disabled.
   bool isEnabled(ExperimentalFeature feature) => feature.isExpired
@@ -181,7 +180,7 @@
   static const bool non_nullable = false;
 
   /// Default state of the experiment "set-literals"
-  static const bool set_literals = false;
+  static const bool set_literals = true;
 
   /// Default state of the experiment "spread-collections"
   static const bool spread_collections = false;
@@ -207,7 +206,7 @@
   static const bool non_nullable = false;
 
   /// Expiration status of the experiment "set-literals"
-  static const bool set_literals = false;
+  static const bool set_literals = true;
 
   /// Expiration status of the experiment "spread-collections"
   static const bool spread_collections = false;
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
index 7e4e1aa..8655536 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart
@@ -382,13 +382,6 @@
    * transitive closure of imported / exported files.
    */
   String get transitiveSignature {
-    if (isPart) {
-      var library = this.library;
-      if (library != null) {
-        return library.transitiveSignature;
-      }
-    }
-
     this.libraryCycle; // sets _transitiveSignature
     return _transitiveSignature;
   }
diff --git a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
index f355cc9..1e34697 100644
--- a/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/file_tracker.dart
@@ -10,8 +10,10 @@
 /**
  * Callback used by [FileTracker] to report to its client that files have been
  * added, changed, or removed, and therefore more analysis may be necessary.
+ * [path] is the path of the file that was added, changed, or removed,
+ * or `null` if multiple files were added, changed, or removed.
  */
-typedef void FileTrackerChangeHook();
+typedef void FileTrackerChangeHook(String path);
 
 /**
  * Maintains the file system state needed by the analysis driver, as well as
@@ -147,7 +149,7 @@
     _fsState.markFileForReading(path);
     addedFiles.add(path);
     _pendingFiles.add(path);
-    _changeHook();
+    _changeHook(path);
   }
 
   /**
@@ -156,7 +158,7 @@
   void addFiles(Iterable<String> paths) {
     addedFiles.addAll(paths);
     _pendingFiles.addAll(paths);
-    _changeHook();
+    _changeHook(null);
   }
 
   /**
@@ -168,7 +170,7 @@
       _pendingChangedFiles.add(path);
     }
     _fsState.markFileForReading(path);
-    _changeHook();
+    _changeHook(path);
   }
 
   /**
@@ -207,7 +209,7 @@
     // files seems extreme.
     _fsState.removeFile(path);
     _pendingFiles.addAll(addedFiles);
-    _changeHook();
+    _changeHook(path);
   }
 
   /**
diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
index 8624f12..cb200cb 100644
--- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart
@@ -213,7 +213,9 @@
 
     unit.accept(new BestPracticesVerifier(
         errorReporter, _typeProvider, _libraryElement,
-        typeSystem: _context.typeSystem, resourceProvider: _resourceProvider));
+        typeSystem: _context.typeSystem,
+        resourceProvider: _resourceProvider,
+        analysisOptions: _context.analysisOptions));
 
     unit.accept(new OverrideVerifier(
       _inheritance,
@@ -266,8 +268,8 @@
 
     var nodeRegistry = new NodeLintRegistry(_analysisOptions.enableTiming);
     var visitors = <AstVisitor>[];
-    var context = LinterContextImpl(
-        allUnits, currentUnit, _declaredVariables, _typeProvider, _typeSystem);
+    var context = LinterContextImpl(allUnits, currentUnit, _declaredVariables,
+        _typeProvider, _typeSystem, _analysisOptions);
     for (Linter linter in _analysisOptions.lintRules) {
       linter.reporter = errorReporter;
       if (linter is NodeLintRule) {
diff --git a/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
index d1fe93b..9148fef 100644
--- a/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/referenced_names.dart
@@ -45,6 +45,9 @@
       _addSubtypedName(declaration.superclass);
       _addSubtypedNames(declaration.withClause?.mixinTypes);
       _addSubtypedNames(declaration.implementsClause?.interfaces);
+    } else if (declaration is MixinDeclaration) {
+      _addSubtypedNames(declaration.onClause?.superclassConstraints);
+      _addSubtypedNames(declaration.implementsClause?.interfaces);
     }
   }
 
diff --git a/pkg/analyzer/lib/src/dart/analysis/search.dart b/pkg/analyzer/lib/src/dart/analysis/search.dart
index caa227a..908cc96 100644
--- a/pkg/analyzer/lib/src/dart/analysis/search.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/search.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/ast/visitor.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
 import 'package:analyzer/src/dart/analysis/file_state.dart';
 import 'package:analyzer/src/dart/analysis/index.dart';
@@ -33,6 +34,7 @@
  */
 class Declaration {
   final int fileIndex;
+  final LineInfo lineInfo;
   final String name;
   final DeclarationKind kind;
   final int offset;
@@ -46,6 +48,7 @@
 
   Declaration(
       this.fileIndex,
+      this.lineInfo,
       this.name,
       this.kind,
       this.offset,
@@ -188,6 +191,7 @@
           var location = file.lineInfo.getLocation(offset);
           declarations.add(new Declaration(
               fileIndex,
+              file.lineInfo,
               name,
               kind,
               offset,
diff --git a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
index da33b5a..a05c39c 100644
--- a/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
+++ b/pkg/analyzer/lib/src/dart/analysis/uri_converter.dart
@@ -43,5 +43,5 @@
   }
 
   @override
-  String uriToPath(Uri uri) => driver.sourceFactory.forUri2(uri).fullName;
+  String uriToPath(Uri uri) => driver.sourceFactory.forUri2(uri)?.fullName;
 }
diff --git a/pkg/analyzer/lib/src/dart/ast/ast.dart b/pkg/analyzer/lib/src/dart/ast/ast.dart
index d6abf5e..93bfdfd 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast.dart
@@ -2059,125 +2059,6 @@
 abstract class CollectionElementImpl extends AstNodeImpl
     implements CollectionElement {}
 
-class CollectionForElementImpl extends CollectionElementImpl
-    with ForMixin
-    implements CollectionForElement {
-  /**
-   * The body of the loop.
-   */
-  CollectionElementImpl _body;
-
-  /**
-   * Initialize a newly created for element.
-   */
-  CollectionForElementImpl(
-      Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      ForLoopPartsImpl forLoopParts,
-      Token rightParenthesis,
-      CollectionElementImpl body) {
-    this.awaitKeyword = awaitKeyword;
-    this.forKeyword = forKeyword;
-    this.leftParenthesis = leftParenthesis;
-    _forLoopParts = _becomeParentOf(forLoopParts);
-    this.rightParenthesis = rightParenthesis;
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  CollectionElement get body => _body;
-
-  void set body(CollectionElement statement) {
-    _body = _becomeParentOf(statement as CollectionElementImpl);
-  }
-
-  @override
-  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
-    ..addAll(super.childEntities)
-    ..add(_body);
-
-  @override
-  Token get endToken => _body.endToken;
-
-  @override
-  E accept<E>(AstVisitor<E> visitor) => visitor.visitCollectionForElement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _forLoopParts?.accept(visitor);
-    _body?.accept(visitor);
-  }
-}
-
-class CollectionIfElementImpl extends CollectionElementImpl
-    with IfMixin
-    implements CollectionIfElement {
-  /**
-   * The element to be executed if the condition is `true`.
-   */
-  CollectionElementImpl _thenElement;
-
-  /**
-   * The element to be executed if the condition is `false`, or `null` if there
-   * is no such element.
-   */
-  CollectionElementImpl _elseElement;
-
-  /**
-   * Initialize a newly created for element.
-   */
-  CollectionIfElementImpl(
-      Token ifKeyword,
-      Token leftParenthesis,
-      ExpressionImpl condition,
-      Token rightParenthesis,
-      CollectionElementImpl thenElement,
-      Token elseKeyword,
-      CollectionElementImpl elseElement) {
-    this.ifKeyword = ifKeyword;
-    this.leftParenthesis = leftParenthesis;
-    _condition = _becomeParentOf(condition);
-    this.rightParenthesis = rightParenthesis;
-    _thenElement = _becomeParentOf(thenElement);
-    this.elseKeyword = elseKeyword;
-    _elseElement = _becomeParentOf(elseElement);
-  }
-
-  @override
-  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
-    ..addAll(super.childEntities)
-    ..add(_thenElement)
-    ..add(_elseElement);
-
-  @override
-  CollectionElement get elseElement => _elseElement;
-
-  set elseElement(CollectionElement element) {
-    _elseElement = _becomeParentOf(element as CollectionElementImpl);
-  }
-
-  @override
-  Token get endToken => _elseElement?.endToken ?? _thenElement.endToken;
-
-  @override
-  CollectionElement get thenElement => _thenElement;
-
-  set thenElement(CollectionElement element) {
-    _thenElement = _becomeParentOf(element as CollectionElementImpl);
-  }
-
-  @override
-  E accept<E>(AstVisitor<E> visitor) => visitor.visitCollectionIfElement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _thenElement?.accept(visitor);
-    _elseElement?.accept(visitor);
-  }
-}
-
 /**
  * A combinator associated with an import or export directive.
  *
@@ -4963,6 +4844,57 @@
   }
 }
 
+class ForElementImpl extends CollectionElementImpl
+    with ForMixin
+    implements ForElement {
+  /**
+   * The body of the loop.
+   */
+  CollectionElementImpl _body;
+
+  /**
+   * Initialize a newly created for element.
+   */
+  ForElementImpl(
+      Token awaitKeyword,
+      Token forKeyword,
+      Token leftParenthesis,
+      ForLoopPartsImpl forLoopParts,
+      Token rightParenthesis,
+      CollectionElementImpl body) {
+    this.awaitKeyword = awaitKeyword;
+    this.forKeyword = forKeyword;
+    this.leftParenthesis = leftParenthesis;
+    _forLoopParts = _becomeParentOf(forLoopParts);
+    this.rightParenthesis = rightParenthesis;
+    _body = _becomeParentOf(body);
+  }
+
+  @override
+  CollectionElement get body => _body;
+
+  void set body(CollectionElement statement) {
+    _body = _becomeParentOf(statement as CollectionElementImpl);
+  }
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
+    ..addAll(super.childEntities)
+    ..add(_body);
+
+  @override
+  Token get endToken => _body.endToken;
+
+  @override
+  E accept<E>(AstVisitor<E> visitor) => visitor.visitForElement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    _forLoopParts?.accept(visitor);
+    _body?.accept(visitor);
+  }
+}
+
 abstract class ForLoopPartsImpl extends AstNodeImpl implements ForLoopParts {}
 
 /**
@@ -6445,6 +6377,74 @@
   bool get isAssignable => true;
 }
 
+class IfElementImpl extends CollectionElementImpl
+    with IfMixin
+    implements IfElement {
+  /**
+   * The element to be executed if the condition is `true`.
+   */
+  CollectionElementImpl _thenElement;
+
+  /**
+   * The element to be executed if the condition is `false`, or `null` if there
+   * is no such element.
+   */
+  CollectionElementImpl _elseElement;
+
+  /**
+   * Initialize a newly created for element.
+   */
+  IfElementImpl(
+      Token ifKeyword,
+      Token leftParenthesis,
+      ExpressionImpl condition,
+      Token rightParenthesis,
+      CollectionElementImpl thenElement,
+      Token elseKeyword,
+      CollectionElementImpl elseElement) {
+    this.ifKeyword = ifKeyword;
+    this.leftParenthesis = leftParenthesis;
+    _condition = _becomeParentOf(condition);
+    this.rightParenthesis = rightParenthesis;
+    _thenElement = _becomeParentOf(thenElement);
+    this.elseKeyword = elseKeyword;
+    _elseElement = _becomeParentOf(elseElement);
+  }
+
+  @override
+  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
+    ..addAll(super.childEntities)
+    ..add(_thenElement)
+    ..add(_elseElement);
+
+  @override
+  CollectionElement get elseElement => _elseElement;
+
+  set elseElement(CollectionElement element) {
+    _elseElement = _becomeParentOf(element as CollectionElementImpl);
+  }
+
+  @override
+  Token get endToken => _elseElement?.endToken ?? _thenElement.endToken;
+
+  @override
+  CollectionElement get thenElement => _thenElement;
+
+  set thenElement(CollectionElement element) {
+    _thenElement = _becomeParentOf(element as CollectionElementImpl);
+  }
+
+  @override
+  E accept<E>(AstVisitor<E> visitor) => visitor.visitIfElement(this);
+
+  @override
+  void visitChildren(AstVisitor visitor) {
+    super.visitChildren(visitor);
+    _thenElement?.accept(visitor);
+    _elseElement?.accept(visitor);
+  }
+}
+
 mixin IfMixin on AstNodeImpl {
   Token ifKeyword;
 
@@ -7985,127 +7985,6 @@
       new Set<VariableElement>();
 }
 
-abstract class MapElementImpl extends AstNodeImpl implements MapElement {}
-
-class MapForElementImpl extends MapElementImpl
-    with ForMixin
-    implements MapForElement {
-  /**
-   * The body of the loop.
-   */
-  MapElementImpl _body;
-
-  /**
-   * Initialize a newly created for element.
-   */
-  MapForElementImpl(
-      Token awaitKeyword,
-      Token forKeyword,
-      Token leftParenthesis,
-      ForLoopPartsImpl forLoopParts,
-      Token rightParenthesis,
-      MapElementImpl body) {
-    this.awaitKeyword = awaitKeyword;
-    this.forKeyword = forKeyword;
-    this.leftParenthesis = leftParenthesis;
-    _forLoopParts = _becomeParentOf(forLoopParts);
-    this.rightParenthesis = rightParenthesis;
-    _body = _becomeParentOf(body);
-  }
-
-  @override
-  MapElement get body => _body;
-
-  void set body(MapElement statement) {
-    _body = _becomeParentOf(statement as MapElementImpl);
-  }
-
-  @override
-  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
-    ..addAll(super.childEntities)
-    ..add(_body);
-
-  @override
-  Token get endToken => _body.endToken;
-
-  @override
-  E accept<E>(AstVisitor<E> visitor) => visitor.visitMapForElement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    _forLoopParts?.accept(visitor);
-    _body?.accept(visitor);
-  }
-}
-
-class MapIfElementImpl extends MapElementImpl
-    with IfMixin
-    implements MapIfElement {
-  /**
-   * The element to be executed if the condition is `true`.
-   */
-  MapElementImpl _thenElement;
-
-  /**
-   * The element to be executed if the condition is `false`, or `null` if there
-   * is no such element.
-   */
-  MapElementImpl _elseElement;
-
-  /**
-   * Initialize a newly created for element.
-   */
-  MapIfElementImpl(
-      Token ifKeyword,
-      Token leftParenthesis,
-      ExpressionImpl condition,
-      Token rightParenthesis,
-      MapElementImpl thenElement,
-      Token elseKeyword,
-      MapElementImpl elseElement) {
-    this.ifKeyword = ifKeyword;
-    this.leftParenthesis = leftParenthesis;
-    _condition = _becomeParentOf(condition);
-    this.rightParenthesis = rightParenthesis;
-    _thenElement = _becomeParentOf(thenElement);
-    this.elseKeyword = elseKeyword;
-    _elseElement = _becomeParentOf(elseElement);
-  }
-
-  @override
-  Iterable<SyntacticEntity> get childEntities => new ChildEntities()
-    ..addAll(super.childEntities)
-    ..add(_thenElement)
-    ..add(_elseElement);
-
-  @override
-  MapElement get elseElement => _elseElement;
-
-  set elseElement(MapElement element) {
-    _elseElement = _becomeParentOf(element as MapElementImpl);
-  }
-
-  @override
-  Token get endToken => _elseElement?.endToken ?? _thenElement.endToken;
-
-  @override
-  MapElement get thenElement => _thenElement;
-
-  set thenElement(MapElement element) {
-    _thenElement = _becomeParentOf(element as MapElementImpl);
-  }
-
-  @override
-  E accept<E>(AstVisitor<E> visitor) => visitor.visitMapIfElement(this);
-
-  @override
-  void visitChildren(AstVisitor visitor) {
-    super.visitChildren(visitor);
-    _thenElement?.accept(visitor);
-    _elseElement?.accept(visitor);
-  }
-}
-
 /**
  * A literal map.
  *
@@ -8124,7 +8003,7 @@
   /**
    * The entries in the map.
    */
-  NodeList<MapElement> _entries;
+  NodeList<CollectionElement> _entries;
 
   @override
   Token rightBracket;
@@ -8135,9 +8014,9 @@
    * arguments were declared. The [entries] can be `null` if the map is empty.
    */
   MapLiteral2Impl(Token constKeyword, TypeArgumentListImpl typeArguments,
-      this.leftBracket, List<MapElement> entries, this.rightBracket)
+      this.leftBracket, List<CollectionElement> entries, this.rightBracket)
       : super(constKeyword, typeArguments) {
-    _entries = new NodeListImpl<MapElement>(this, entries);
+    _entries = new NodeListImpl<CollectionElement>(this, entries);
   }
 
   @override
@@ -8163,7 +8042,7 @@
   Token get endToken => rightBracket;
 
   @override
-  NodeList<MapElement> get entries => _entries;
+  NodeList<CollectionElement> get entries => _entries;
 
   @override
   E accept<E>(AstVisitor<E> visitor) => visitor.visitMapLiteral2(this);
@@ -8181,7 +8060,8 @@
  *    mapLiteralEntry ::=
  *        [Expression] ':' [Expression]
  */
-class MapLiteralEntryImpl extends MapElementImpl implements MapLiteralEntry {
+class MapLiteralEntryImpl extends CollectionElementImpl
+    implements MapLiteralEntry {
   /**
    * The expression computing the key with which the value will be associated.
    */
@@ -10868,7 +10748,7 @@
     implements SingleStringLiteral {}
 
 class SpreadElementImpl extends AstNodeImpl
-    implements CollectionElementImpl, MapElementImpl, SpreadElement {
+    implements CollectionElementImpl, SpreadElement {
   Token spreadOperator;
 
   ExpressionImpl _expression;
diff --git a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
index cad9671..4e04999 100644
--- a/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
+++ b/pkg/analyzer/lib/src/dart/ast/ast_factory.dart
@@ -173,29 +173,6 @@
           semicolon);
 
   @override
-  CollectionForElement collectionForElement(
-          {Token awaitKeyword,
-          Token forKeyword,
-          Token leftParenthesis,
-          ForLoopParts forLoopParts,
-          Token rightParenthesis,
-          CollectionElement body}) =>
-      new CollectionForElementImpl(awaitKeyword, forKeyword, leftParenthesis,
-          forLoopParts, rightParenthesis, body);
-
-  @override
-  CollectionIfElement collectionIfElement(
-          {Token ifKeyword,
-          Token leftParenthesis,
-          Expression condition,
-          Token rightParenthesis,
-          CollectionElement thenElement,
-          Token elseKeyword,
-          CollectionElement elseElement}) =>
-      new CollectionIfElementImpl(ifKeyword, leftParenthesis, condition,
-          rightParenthesis, thenElement, elseKeyword, elseElement);
-
-  @override
   CommentReference commentReference(Token newKeyword, Identifier identifier) =>
       new CommentReferenceImpl(newKeyword, identifier);
 
@@ -482,6 +459,17 @@
           body);
 
   @override
+  ForElement forElement(
+          {Token awaitKeyword,
+          Token forKeyword,
+          Token leftParenthesis,
+          ForLoopParts forLoopParts,
+          Token rightParenthesis,
+          CollectionElement body}) =>
+      new ForElementImpl(awaitKeyword, forKeyword, leftParenthesis,
+          forLoopParts, rightParenthesis, body);
+
+  @override
   FormalParameterList formalParameterList(
           Token leftParenthesis,
           List<FormalParameter> parameters,
@@ -640,6 +628,18 @@
       new HideCombinatorImpl(keyword, hiddenNames);
 
   @override
+  IfElement ifElement(
+          {Token ifKeyword,
+          Token leftParenthesis,
+          Expression condition,
+          Token rightParenthesis,
+          CollectionElement thenElement,
+          Token elseKeyword,
+          CollectionElement elseElement}) =>
+      new IfElementImpl(ifKeyword, leftParenthesis, condition, rightParenthesis,
+          thenElement, elseKeyword, elseElement);
+
+  @override
   IfStatement ifStatement(
           Token ifKeyword,
           Token leftParenthesis,
@@ -752,29 +752,6 @@
           constKeyword, typeArguments, leftBracket, elements, rightBracket);
 
   @override
-  MapForElement mapForElement(
-          {Token awaitKeyword,
-          Token forKeyword,
-          Token leftParenthesis,
-          ForLoopParts forLoopParts,
-          Token rightParenthesis,
-          MapElement body}) =>
-      new MapForElementImpl(awaitKeyword, forKeyword, leftParenthesis,
-          forLoopParts, rightParenthesis, body);
-
-  @override
-  MapIfElement mapIfElement(
-          {Token ifKeyword,
-          Token leftParenthesis,
-          Expression condition,
-          Token rightParenthesis,
-          MapElement thenElement,
-          Token elseKeyword,
-          MapElement elseElement}) =>
-      new MapIfElementImpl(ifKeyword, leftParenthesis, condition,
-          rightParenthesis, thenElement, elseKeyword, elseElement);
-
-  @override
   MapLiteral mapLiteral(
           Token constKeyword,
           TypeArgumentList typeArguments,
@@ -789,7 +766,7 @@
           {Token constKeyword,
           TypeArgumentList typeArguments,
           Token leftBracket,
-          List<MapElement> entries,
+          List<CollectionElement> entries,
           Token rightBracket}) =>
       new MapLiteral2Impl(
           constKeyword, typeArguments, leftBracket, entries, rightBracket);
diff --git a/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
new file mode 100644
index 0000000..052c2fe
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/constant_evaluator.dart
@@ -0,0 +1,390 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package: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';
+
+/**
+ * Instances of the class [ConstantEvaluator] evaluate constant expressions to
+ * produce their compile-time value.
+ *
+ * According to the Dart Language Specification:
+ *
+ * > A constant expression is one of the following:
+ * >
+ * > * A literal number.
+ * > * A literal boolean.
+ * > * A literal string where any interpolated expression is a compile-time
+ * >   constant that evaluates to a numeric, string or boolean value or to
+ * >   **null**.
+ * > * A literal symbol.
+ * > * **null**.
+ * > * A qualified reference to a static constant variable.
+ * > * An identifier expression that denotes a constant variable, class or type
+ * >   alias.
+ * > * A constant constructor invocation.
+ * > * A constant list literal.
+ * > * A constant map literal.
+ * > * A simple or qualified identifier denoting a top-level function or a
+ * >   static method.
+ * > * A parenthesized expression _(e)_ where _e_ is a constant expression.
+ * > * <span>
+ * >   An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
+ * >   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions and <i>identical()</i> is statically bound to the predefined
+ * >   dart function <i>identical()</i> discussed above.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
+ * >   or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
+ * >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a
+ * >   numeric, string or boolean value.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
+ * >   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
+ * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions that evaluate to a boolean value.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
+ * >   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
+ * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
+ * >   expressions that evaluate to an integer value or to <b>null</b>.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub>
+ * >   -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub> ~/
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
+ * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
+ * >   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>,
+ * >   <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions
+ * >   that evaluate to a numeric value or to <b>null</b>.
+ * >   </span>
+ * > * <span>
+ * >   An expression of one the form <i>e<sub>1</sub> + e<sub>2</sub></i>,
+ * >   <i>e<sub>1</sub> -e<sub>2</sub></i> where <i>e<sub>1</sub> and
+ * >   e<sub>2</sub></i> are constant expressions that evaluate to a numeric or
+ * >   string value or to <b>null</b>.
+ * >   </span>
+ * > * <span>
+ * >   An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
+ * >   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
+ * >   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
+ * >   evaluates to a boolean value.
+ * >   </span>
+ *
+ * However, this comment is now at least a little bit out of sync with the spec.
+ *
+ * The values returned by instances of this class are therefore `null` and
+ * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
+ * `DartObject`.
+ *
+ * In addition, this class defines several values that can be returned to
+ * indicate various conditions encountered during evaluation. These are
+ * documented with the static fields that define those values.
+ */
+class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
+  /**
+   * The value returned for expressions (or non-expression nodes) that are not
+   * compile-time constant expressions.
+   */
+  static Object NOT_A_CONSTANT = new Object();
+
+  @override
+  Object visitAdjacentStrings(AdjacentStrings node) {
+    StringBuffer buffer = new StringBuffer();
+    for (StringLiteral string in node.strings) {
+      Object value = string.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      buffer.write(value);
+    }
+    return buffer.toString();
+  }
+
+  @override
+  Object visitBinaryExpression(BinaryExpression node) {
+    Object leftOperand = node.leftOperand.accept(this);
+    if (identical(leftOperand, NOT_A_CONSTANT)) {
+      return leftOperand;
+    }
+    Object rightOperand = node.rightOperand.accept(this);
+    if (identical(rightOperand, NOT_A_CONSTANT)) {
+      return rightOperand;
+    }
+    while (true) {
+      if (node.operator.type == TokenType.AMPERSAND) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand & rightOperand;
+        }
+      } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
+        // boolean or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand && rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BANG_EQ) {
+        // numeric, string, boolean, or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand != rightOperand;
+        } else if (leftOperand is num && rightOperand is num) {
+          return leftOperand != rightOperand;
+        } else if (leftOperand is String && rightOperand is String) {
+          return leftOperand != rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BAR) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand | rightOperand;
+        }
+      } else if (node.operator.type == TokenType.BAR_BAR) {
+        // boolean or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand || rightOperand;
+        }
+      } else if (node.operator.type == TokenType.CARET) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand ^ rightOperand;
+        }
+      } else if (node.operator.type == TokenType.EQ_EQ) {
+        // numeric, string, boolean, or {@code null}
+        if (leftOperand is bool && rightOperand is bool) {
+          return leftOperand == rightOperand;
+        } else if (leftOperand is num && rightOperand is num) {
+          return leftOperand == rightOperand;
+        } else if (leftOperand is String && rightOperand is String) {
+          return leftOperand == rightOperand;
+        }
+      } else if (node.operator.type == TokenType.GT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) > 0;
+        }
+      } else if (node.operator.type == TokenType.GT_EQ) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) >= 0;
+        }
+      } else if (node.operator.type == TokenType.GT_GT) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand >> rightOperand;
+        }
+      } else if (node.operator.type == TokenType.LT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) < 0;
+        }
+      } else if (node.operator.type == TokenType.LT_EQ) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.compareTo(rightOperand) <= 0;
+        }
+      } else if (node.operator.type == TokenType.LT_LT) {
+        // integer or {@code null}
+        if (leftOperand is int && rightOperand is int) {
+          return leftOperand << rightOperand;
+        }
+      } else if (node.operator.type == TokenType.MINUS) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand - rightOperand;
+        }
+      } else if (node.operator.type == TokenType.PERCENT) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand.remainder(rightOperand);
+        }
+      } else if (node.operator.type == TokenType.PLUS) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand + rightOperand;
+        }
+        if (leftOperand is String && rightOperand is String) {
+          return leftOperand + rightOperand;
+        }
+      } else if (node.operator.type == TokenType.STAR) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand * rightOperand;
+        }
+      } else if (node.operator.type == TokenType.SLASH) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand / rightOperand;
+        }
+      } else if (node.operator.type == TokenType.TILDE_SLASH) {
+        // numeric or {@code null}
+        if (leftOperand is num && rightOperand is num) {
+          return leftOperand ~/ rightOperand;
+        }
+      }
+      break;
+    }
+    // TODO(brianwilkerson) This doesn't handle numeric conversions.
+    return visitExpression(node);
+  }
+
+  @override
+  Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
+
+  @override
+  Object visitDoubleLiteral(DoubleLiteral node) => node.value;
+
+  @override
+  Object visitIntegerLiteral(IntegerLiteral node) => node.value;
+
+  @override
+  Object visitInterpolationExpression(InterpolationExpression node) {
+    Object value = node.expression.accept(this);
+    if (value == null || value is bool || value is String || value is num) {
+      return value;
+    }
+    return NOT_A_CONSTANT;
+  }
+
+  @override
+  Object visitInterpolationString(InterpolationString node) => node.value;
+
+  @override
+  Object visitListLiteral(ListLiteral node) {
+    List<Object> list = new List<Object>();
+    for (Expression element in node.elements) {
+      Object value = element.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      list.add(value);
+    }
+    return list;
+  }
+
+  @override
+  Object visitMapLiteral(MapLiteral node) {
+    Map<String, Object> map = new HashMap<String, Object>();
+    for (MapLiteralEntry entry in node.entries) {
+      Object key = entry.key.accept(this);
+      Object value = entry.value.accept(this);
+      if (key is String && !identical(value, NOT_A_CONSTANT)) {
+        map[key] = value;
+      } else {
+        return NOT_A_CONSTANT;
+      }
+    }
+    return map;
+  }
+
+  @override
+  Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
+
+  @override
+  Object visitNode(AstNode node) => NOT_A_CONSTANT;
+
+  @override
+  Object visitNullLiteral(NullLiteral node) => null;
+
+  @override
+  Object visitParenthesizedExpression(ParenthesizedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
+      _getConstantValue(null);
+
+  @override
+  Object visitPrefixExpression(PrefixExpression node) {
+    Object operand = node.operand.accept(this);
+    if (identical(operand, NOT_A_CONSTANT)) {
+      return operand;
+    }
+    while (true) {
+      if (node.operator.type == TokenType.BANG) {
+        if (identical(operand, true)) {
+          return false;
+        } else if (identical(operand, false)) {
+          return true;
+        }
+      } else if (node.operator.type == TokenType.TILDE) {
+        if (operand is int) {
+          return ~operand;
+        }
+      } else if (node.operator.type == TokenType.MINUS) {
+        if (operand == null) {
+          return null;
+        } else if (operand is num) {
+          return -operand;
+        }
+      } else {}
+      break;
+    }
+    return NOT_A_CONSTANT;
+  }
+
+  @override
+  Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
+
+  @override
+  Object visitSimpleIdentifier(SimpleIdentifier node) =>
+      _getConstantValue(null);
+
+  @override
+  Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
+
+  @override
+  Object visitStringInterpolation(StringInterpolation node) {
+    StringBuffer buffer = new StringBuffer();
+    for (InterpolationElement element in node.elements) {
+      Object value = element.accept(this);
+      if (identical(value, NOT_A_CONSTANT)) {
+        return value;
+      }
+      buffer.write(value);
+    }
+    return buffer.toString();
+  }
+
+  @override
+  Object visitSymbolLiteral(SymbolLiteral node) {
+    // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
+    StringBuffer buffer = new StringBuffer();
+    for (Token component in node.components) {
+      if (buffer.length > 0) {
+        buffer.writeCharCode(0x2E);
+      }
+      buffer.write(component.lexeme);
+    }
+    return buffer.toString();
+  }
+
+  /**
+   * Return the constant value of the static constant represented by the given
+   * [element].
+   */
+  Object _getConstantValue(Element element) {
+    // TODO(brianwilkerson) Implement this
+//    if (element is FieldElement) {
+//      FieldElement field = element;
+//      if (field.isStatic && field.isConst) {
+//        //field.getConstantValue();
+//      }
+//      //    } else if (element instanceof VariableElement) {
+//      //      VariableElement variable = (VariableElement) element;
+//      //      if (variable.isStatic() && variable.isConst()) {
+//      //        //variable.getConstantValue();
+//      //      }
+//    }
+    return NOT_A_CONSTANT;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/element_locator.dart b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
new file mode 100644
index 0000000..9761144
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/ast/element_locator.dart
@@ -0,0 +1,162 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// An object used to locate the [Element] associated with a given [AstNode].
+class ElementLocator {
+  /// Return the element associated with the given [node], or `null` if there
+  /// is no element associated with the node.
+  static Element locate(AstNode node) {
+    if (node == null) return null;
+
+    var mapper = new _ElementMapper();
+    return node.accept(mapper);
+  }
+}
+
+/// Visitor that maps nodes to elements.
+class _ElementMapper extends GeneralizingAstVisitor<Element> {
+  @override
+  Element visitAnnotation(Annotation node) {
+    return node.element;
+  }
+
+  @override
+  Element visitAssignmentExpression(AssignmentExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitBinaryExpression(BinaryExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitClassDeclaration(ClassDeclaration node) {
+    return node.declaredElement;
+  }
+
+  @override
+  Element visitCompilationUnit(CompilationUnit node) {
+    return node.declaredElement;
+  }
+
+  @override
+  Element visitConstructorDeclaration(ConstructorDeclaration node) {
+    return node.declaredElement;
+  }
+
+  @override
+  Element visitExportDirective(ExportDirective node) {
+    return node.element;
+  }
+
+  @override
+  Element visitFunctionDeclaration(FunctionDeclaration node) {
+    return node.declaredElement;
+  }
+
+  @override
+  Element visitIdentifier(Identifier node) {
+    var parent = node.parent;
+    if (parent is Annotation) {
+      // Type name in Annotation
+      if (identical(parent.name, node) && parent.constructorName == null) {
+        return parent.element;
+      }
+    } else if (parent is ConstructorDeclaration) {
+      // Extra work to map Constructor Declarations to their associated
+      // Constructor Elements
+      var returnType = parent.returnType;
+      if (identical(returnType, node)) {
+        var name = parent.name;
+        if (name != null) {
+          return name.staticElement;
+        }
+        var element = node.staticElement;
+        if (element is ClassElement) {
+          return element.unnamedConstructor;
+        }
+      }
+    } else if (parent is LibraryIdentifier) {
+      var grandParent = parent.parent;
+      if (grandParent is PartOfDirective) {
+        var element = grandParent.element;
+        if (element is LibraryElement) {
+          return element.definingCompilationUnit;
+        }
+      } else if (grandParent is LibraryDirective) {
+        return grandParent.element;
+      }
+    }
+    return node.staticElement;
+  }
+
+  @override
+  Element visitImportDirective(ImportDirective node) {
+    return node.element;
+  }
+
+  @override
+  Element visitIndexExpression(IndexExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitInstanceCreationExpression(InstanceCreationExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitLibraryDirective(LibraryDirective node) {
+    return node.element;
+  }
+
+  @override
+  Element visitMethodDeclaration(MethodDeclaration node) {
+    return node.declaredElement;
+  }
+
+  @override
+  Element visitMethodInvocation(MethodInvocation node) {
+    return node.methodName.staticElement;
+  }
+
+  @override
+  Element visitPartOfDirective(PartOfDirective node) {
+    return node.element;
+  }
+
+  @override
+  Element visitPostfixExpression(PostfixExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitPrefixedIdentifier(PrefixedIdentifier node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitPrefixExpression(PrefixExpression node) {
+    return node.staticElement;
+  }
+
+  @override
+  Element visitStringLiteral(StringLiteral node) {
+    var parent = node.parent;
+    if (parent is UriBasedDirective) {
+      return parent.uriElement;
+    }
+    return null;
+  }
+
+  @override
+  Element visitVariableDeclaration(VariableDeclaration node) {
+    return node.declaredElement;
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/ast/utilities.dart b/pkg/analyzer/lib/src/dart/ast/utilities.dart
index 5d53fc0..59cec6b 100644
--- a/pkg/analyzer/lib/src/dart/ast/utilities.dart
+++ b/pkg/analyzer/lib/src/dart/ast/utilities.dart
@@ -8,7 +8,6 @@
 import 'package:analyzer/dart/ast/standard_ast_factory.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/exception/exception.dart';
 import 'package:analyzer/src/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/token.dart';
@@ -17,6 +16,8 @@
 import 'package:analyzer/src/generated/utilities_collection.dart' show TokenMap;
 import 'package:meta/meta.dart';
 
+export 'package:analyzer/src/dart/ast/constant_evaluator.dart';
+
 /**
  * A function used to handle exceptions that are thrown by delegates while using
  * an [ExceptionHandlingDelegatingAstVisitor].
@@ -248,26 +249,6 @@
   }
 
   @override
-  CollectionForElement visitCollectionForElement(CollectionForElement node) =>
-      astFactory.collectionForElement(
-          forKeyword: cloneToken(node.forKeyword),
-          leftParenthesis: cloneToken(node.leftParenthesis),
-          forLoopParts: cloneNode(node.forLoopParts),
-          rightParenthesis: cloneToken(node.rightParenthesis),
-          body: cloneNode(node.body));
-
-  @override
-  CollectionIfElement visitCollectionIfElement(CollectionIfElement node) =>
-      astFactory.collectionIfElement(
-          ifKeyword: cloneToken(node.ifKeyword),
-          leftParenthesis: cloneToken(node.leftParenthesis),
-          condition: cloneNode(node.condition),
-          rightParenthesis: cloneToken(node.rightParenthesis),
-          thenElement: cloneNode(node.thenElement),
-          elseKeyword: cloneToken(node.elseKeyword),
-          elseElement: cloneNode(node.elseElement));
-
-  @override
   Comment visitComment(Comment node) {
     if (node.isDocumentation) {
       return astFactory.documentationComment(
@@ -531,6 +512,14 @@
   }
 
   @override
+  ForElement visitForElement(ForElement node) => astFactory.forElement(
+      forKeyword: cloneToken(node.forKeyword),
+      leftParenthesis: cloneToken(node.leftParenthesis),
+      forLoopParts: cloneNode(node.forLoopParts),
+      rightParenthesis: cloneToken(node.rightParenthesis),
+      body: cloneNode(node.body));
+
+  @override
   FormalParameterList visitFormalParameterList(FormalParameterList node) =>
       astFactory.formalParameterList(
           cloneToken(node.leftParenthesis),
@@ -660,6 +649,16 @@
           cloneToken(node.keyword), cloneNodeList(node.hiddenNames));
 
   @override
+  IfElement visitIfElement(IfElement node) => astFactory.ifElement(
+      ifKeyword: cloneToken(node.ifKeyword),
+      leftParenthesis: cloneToken(node.leftParenthesis),
+      condition: cloneNode(node.condition),
+      rightParenthesis: cloneToken(node.rightParenthesis),
+      thenElement: cloneNode(node.thenElement),
+      elseKeyword: cloneToken(node.elseKeyword),
+      elseElement: cloneNode(node.elseElement));
+
+  @override
   IfStatement visitIfStatement(IfStatement node) => astFactory.ifStatement(
       cloneToken(node.ifKeyword),
       cloneToken(node.leftParenthesis),
@@ -777,25 +776,6 @@
       rightBracket: cloneToken(node.rightBracket));
 
   @override
-  MapForElement visitMapForElement(MapForElement node) =>
-      astFactory.mapForElement(
-          forKeyword: cloneToken(node.forKeyword),
-          leftParenthesis: cloneToken(node.leftParenthesis),
-          forLoopParts: cloneNode(node.forLoopParts),
-          rightParenthesis: cloneToken(node.rightParenthesis),
-          body: cloneNode(node.body));
-
-  @override
-  MapIfElement visitMapIfElement(MapIfElement node) => astFactory.mapIfElement(
-      ifKeyword: cloneToken(node.ifKeyword),
-      leftParenthesis: cloneToken(node.leftParenthesis),
-      condition: cloneNode(node.condition),
-      rightParenthesis: cloneToken(node.rightParenthesis),
-      thenElement: cloneNode(node.thenElement),
-      elseKeyword: cloneToken(node.elseKeyword),
-      elseElement: cloneNode(node.elseElement));
-
-  @override
   MapLiteral visitMapLiteral(MapLiteral node) => astFactory.mapLiteral(
       cloneToken(node.constKeyword),
       cloneNode(node.typeArguments),
@@ -1449,28 +1429,6 @@
   }
 
   @override
-  bool visitCollectionForElement(CollectionForElement node) {
-    CollectionForElement other = _other as CollectionForElement;
-    return isEqualTokens(node.forKeyword, other.forKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.forLoopParts, other.forLoopParts) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitCollectionIfElement(CollectionIfElement node) {
-    CollectionIfElement other = _other as CollectionIfElement;
-    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.thenElement, other.thenElement) &&
-        isEqualTokens(node.elseKeyword, other.elseKeyword) &&
-        isEqualNodes(node.elseElement, other.elseElement);
-  }
-
-  @override
   bool visitComment(Comment node) {
     Comment other = _other as Comment;
     return _isEqualNodeLists(node.references, other.references);
@@ -1727,6 +1685,16 @@
   }
 
   @override
+  bool visitForElement(ForElement node) {
+    ForElement other = _other as ForElement;
+    return isEqualTokens(node.forKeyword, other.forKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.forLoopParts, other.forLoopParts) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.body, other.body);
+  }
+
+  @override
   bool visitFormalParameterList(FormalParameterList node) {
     FormalParameterList other = _other as FormalParameterList;
     return isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
@@ -1870,6 +1838,18 @@
   }
 
   @override
+  bool visitIfElement(IfElement node) {
+    IfElement other = _other as IfElement;
+    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
+        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
+        isEqualNodes(node.condition, other.condition) &&
+        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
+        isEqualNodes(node.thenElement, other.thenElement) &&
+        isEqualTokens(node.elseKeyword, other.elseKeyword) &&
+        isEqualNodes(node.elseElement, other.elseElement);
+  }
+
+  @override
   bool visitIfStatement(IfStatement node) {
     IfStatement other = _other as IfStatement;
     return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
@@ -2004,28 +1984,6 @@
   }
 
   @override
-  bool visitMapForElement(MapForElement node) {
-    MapForElement other = _other as MapForElement;
-    return isEqualTokens(node.forKeyword, other.forKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.forLoopParts, other.forLoopParts) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.body, other.body);
-  }
-
-  @override
-  bool visitMapIfElement(MapIfElement node) {
-    MapIfElement other = _other as MapIfElement;
-    return isEqualTokens(node.ifKeyword, other.ifKeyword) &&
-        isEqualTokens(node.leftParenthesis, other.leftParenthesis) &&
-        isEqualNodes(node.condition, other.condition) &&
-        isEqualTokens(node.rightParenthesis, other.rightParenthesis) &&
-        isEqualNodes(node.thenElement, other.thenElement) &&
-        isEqualTokens(node.elseKeyword, other.elseKeyword) &&
-        isEqualNodes(node.elseElement, other.elseElement);
-  }
-
-  @override
   bool visitMapLiteral(MapLiteral node) {
     MapLiteral other = _other as MapLiteral;
     return isEqualTokens(node.constKeyword, other.constKeyword) &&
@@ -2510,386 +2468,6 @@
 }
 
 /**
- * Instances of the class [ConstantEvaluator] evaluate constant expressions to
- * produce their compile-time value.
- *
- * According to the Dart Language Specification:
- *
- * > A constant expression is one of the following:
- * >
- * > * A literal number.
- * > * A literal boolean.
- * > * A literal string where any interpolated expression is a compile-time
- * >   constant that evaluates to a numeric, string or boolean value or to
- * >   **null**.
- * > * A literal symbol.
- * > * **null**.
- * > * A qualified reference to a static constant variable.
- * > * An identifier expression that denotes a constant variable, class or type
- * >   alias.
- * > * A constant constructor invocation.
- * > * A constant list literal.
- * > * A constant map literal.
- * > * A simple or qualified identifier denoting a top-level function or a
- * >   static method.
- * > * A parenthesized expression _(e)_ where _e_ is a constant expression.
- * > * <span>
- * >   An expression of the form <i>identical(e<sub>1</sub>, e<sub>2</sub>)</i>
- * >   where <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * >   expressions and <i>identical()</i> is statically bound to the predefined
- * >   dart function <i>identical()</i> discussed above.
- * >   </span>
- * > * <span>
- * >   An expression of one of the forms <i>e<sub>1</sub> == e<sub>2</sub></i>
- * >   or <i>e<sub>1</sub> != e<sub>2</sub></i> where <i>e<sub>1</sub></i> and
- * >   <i>e<sub>2</sub></i> are constant expressions that evaluate to a
- * >   numeric, string or boolean value.
- * >   </span>
- * > * <span>
- * >   An expression of one of the forms <i>!e</i>, <i>e<sub>1</sub> &amp;&amp;
- * >   e<sub>2</sub></i> or <i>e<sub>1</sub> || e<sub>2</sub></i>, where
- * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * >   expressions that evaluate to a boolean value.
- * >   </span>
- * > * <span>
- * >   An expression of one of the forms <i>~e</i>, <i>e<sub>1</sub> ^
- * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &amp; e<sub>2</sub></i>,
- * >   <i>e<sub>1</sub> | e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;&gt;
- * >   e<sub>2</sub></i> or <i>e<sub>1</sub> &lt;&lt; e<sub>2</sub></i>, where
- * >   <i>e</i>, <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant
- * >   expressions that evaluate to an integer value or to <b>null</b>.
- * >   </span>
- * > * <span>
- * >   An expression of one of the forms <i>-e</i>, <i>e<sub>1</sub>
- * >   -e<sub>2</sub></i>, <i>e<sub>1</sub> * e<sub>2</sub></i>,
- * >   <i>e<sub>1</sub> / e<sub>2</sub></i>, <i>e<sub>1</sub> ~/
- * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &gt; e<sub>2</sub></i>,
- * >   <i>e<sub>1</sub> &lt; e<sub>2</sub></i>, <i>e<sub>1</sub> &gt;=
- * >   e<sub>2</sub></i>, <i>e<sub>1</sub> &lt;= e<sub>2</sub></i> or
- * >   <i>e<sub>1</sub> % e<sub>2</sub></i>, where <i>e</i>,
- * >   <i>e<sub>1</sub></i> and <i>e<sub>2</sub></i> are constant expressions
- * >   that evaluate to a numeric value or to <b>null</b>.
- * >   </span>
- * > * <span>
- * >   An expression of one the form <i>e<sub>1</sub> + e<sub>2</sub></i>,
- * >   <i>e<sub>1</sub> -e<sub>2</sub></i> where <i>e<sub>1</sub> and
- * >   e<sub>2</sub></i> are constant expressions that evaluate to a numeric or
- * >   string value or to <b>null</b>.
- * >   </span>
- * > * <span>
- * >   An expression of the form <i>e<sub>1</sub> ? e<sub>2</sub> :
- * >   e<sub>3</sub></i> where <i>e<sub>1</sub></i>, <i>e<sub>2</sub></i> and
- * >   <i>e<sub>3</sub></i> are constant expressions, and <i>e<sub>1</sub></i>
- * >   evaluates to a boolean value.
- * >   </span>
- *
- * However, this comment is now at least a little bit out of sync with the spec.
- *
- * The values returned by instances of this class are therefore `null` and
- * instances of the classes `Boolean`, `BigInteger`, `Double`, `String`, and
- * `DartObject`.
- *
- * In addition, this class defines several values that can be returned to
- * indicate various conditions encountered during evaluation. These are
- * documented with the static fields that define those values.
- */
-class ConstantEvaluator extends GeneralizingAstVisitor<Object> {
-  /**
-   * The value returned for expressions (or non-expression nodes) that are not
-   * compile-time constant expressions.
-   */
-  static Object NOT_A_CONSTANT = new Object();
-
-  @override
-  Object visitAdjacentStrings(AdjacentStrings node) {
-    StringBuffer buffer = new StringBuffer();
-    for (StringLiteral string in node.strings) {
-      Object value = string.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      buffer.write(value);
-    }
-    return buffer.toString();
-  }
-
-  @override
-  Object visitBinaryExpression(BinaryExpression node) {
-    Object leftOperand = node.leftOperand.accept(this);
-    if (identical(leftOperand, NOT_A_CONSTANT)) {
-      return leftOperand;
-    }
-    Object rightOperand = node.rightOperand.accept(this);
-    if (identical(rightOperand, NOT_A_CONSTANT)) {
-      return rightOperand;
-    }
-    while (true) {
-      if (node.operator.type == TokenType.AMPERSAND) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand & rightOperand;
-        }
-      } else if (node.operator.type == TokenType.AMPERSAND_AMPERSAND) {
-        // boolean or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand && rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BANG_EQ) {
-        // numeric, string, boolean, or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand != rightOperand;
-        } else if (leftOperand is num && rightOperand is num) {
-          return leftOperand != rightOperand;
-        } else if (leftOperand is String && rightOperand is String) {
-          return leftOperand != rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BAR) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand | rightOperand;
-        }
-      } else if (node.operator.type == TokenType.BAR_BAR) {
-        // boolean or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand || rightOperand;
-        }
-      } else if (node.operator.type == TokenType.CARET) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand ^ rightOperand;
-        }
-      } else if (node.operator.type == TokenType.EQ_EQ) {
-        // numeric, string, boolean, or {@code null}
-        if (leftOperand is bool && rightOperand is bool) {
-          return leftOperand == rightOperand;
-        } else if (leftOperand is num && rightOperand is num) {
-          return leftOperand == rightOperand;
-        } else if (leftOperand is String && rightOperand is String) {
-          return leftOperand == rightOperand;
-        }
-      } else if (node.operator.type == TokenType.GT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) > 0;
-        }
-      } else if (node.operator.type == TokenType.GT_EQ) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) >= 0;
-        }
-      } else if (node.operator.type == TokenType.GT_GT) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand >> rightOperand;
-        }
-      } else if (node.operator.type == TokenType.LT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) < 0;
-        }
-      } else if (node.operator.type == TokenType.LT_EQ) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.compareTo(rightOperand) <= 0;
-        }
-      } else if (node.operator.type == TokenType.LT_LT) {
-        // integer or {@code null}
-        if (leftOperand is int && rightOperand is int) {
-          return leftOperand << rightOperand;
-        }
-      } else if (node.operator.type == TokenType.MINUS) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand - rightOperand;
-        }
-      } else if (node.operator.type == TokenType.PERCENT) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand.remainder(rightOperand);
-        }
-      } else if (node.operator.type == TokenType.PLUS) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand + rightOperand;
-        }
-        if (leftOperand is String && rightOperand is String) {
-          return leftOperand + rightOperand;
-        }
-      } else if (node.operator.type == TokenType.STAR) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand * rightOperand;
-        }
-      } else if (node.operator.type == TokenType.SLASH) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand / rightOperand;
-        }
-      } else if (node.operator.type == TokenType.TILDE_SLASH) {
-        // numeric or {@code null}
-        if (leftOperand is num && rightOperand is num) {
-          return leftOperand ~/ rightOperand;
-        }
-      }
-      break;
-    }
-    // TODO(brianwilkerson) This doesn't handle numeric conversions.
-    return visitExpression(node);
-  }
-
-  @override
-  Object visitBooleanLiteral(BooleanLiteral node) => node.value ? true : false;
-
-  @override
-  Object visitDoubleLiteral(DoubleLiteral node) => node.value;
-
-  @override
-  Object visitIntegerLiteral(IntegerLiteral node) => node.value;
-
-  @override
-  Object visitInterpolationExpression(InterpolationExpression node) {
-    Object value = node.expression.accept(this);
-    if (value == null || value is bool || value is String || value is num) {
-      return value;
-    }
-    return NOT_A_CONSTANT;
-  }
-
-  @override
-  Object visitInterpolationString(InterpolationString node) => node.value;
-
-  @override
-  Object visitListLiteral(ListLiteral node) {
-    List<Object> list = new List<Object>();
-    for (Expression element in node.elements) {
-      Object value = element.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      list.add(value);
-    }
-    return list;
-  }
-
-  @override
-  Object visitMapLiteral(MapLiteral node) {
-    Map<String, Object> map = new HashMap<String, Object>();
-    for (MapLiteralEntry entry in node.entries) {
-      Object key = entry.key.accept(this);
-      Object value = entry.value.accept(this);
-      if (key is String && !identical(value, NOT_A_CONSTANT)) {
-        map[key] = value;
-      } else {
-        return NOT_A_CONSTANT;
-      }
-    }
-    return map;
-  }
-
-  @override
-  Object visitMethodInvocation(MethodInvocation node) => visitNode(node);
-
-  @override
-  Object visitNode(AstNode node) => NOT_A_CONSTANT;
-
-  @override
-  Object visitNullLiteral(NullLiteral node) => null;
-
-  @override
-  Object visitParenthesizedExpression(ParenthesizedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  Object visitPrefixedIdentifier(PrefixedIdentifier node) =>
-      _getConstantValue(null);
-
-  @override
-  Object visitPrefixExpression(PrefixExpression node) {
-    Object operand = node.operand.accept(this);
-    if (identical(operand, NOT_A_CONSTANT)) {
-      return operand;
-    }
-    while (true) {
-      if (node.operator.type == TokenType.BANG) {
-        if (identical(operand, true)) {
-          return false;
-        } else if (identical(operand, false)) {
-          return true;
-        }
-      } else if (node.operator.type == TokenType.TILDE) {
-        if (operand is int) {
-          return ~operand;
-        }
-      } else if (node.operator.type == TokenType.MINUS) {
-        if (operand == null) {
-          return null;
-        } else if (operand is num) {
-          return -operand;
-        }
-      } else {}
-      break;
-    }
-    return NOT_A_CONSTANT;
-  }
-
-  @override
-  Object visitPropertyAccess(PropertyAccess node) => _getConstantValue(null);
-
-  @override
-  Object visitSimpleIdentifier(SimpleIdentifier node) =>
-      _getConstantValue(null);
-
-  @override
-  Object visitSimpleStringLiteral(SimpleStringLiteral node) => node.value;
-
-  @override
-  Object visitStringInterpolation(StringInterpolation node) {
-    StringBuffer buffer = new StringBuffer();
-    for (InterpolationElement element in node.elements) {
-      Object value = element.accept(this);
-      if (identical(value, NOT_A_CONSTANT)) {
-        return value;
-      }
-      buffer.write(value);
-    }
-    return buffer.toString();
-  }
-
-  @override
-  Object visitSymbolLiteral(SymbolLiteral node) {
-    // TODO(brianwilkerson) This isn't optimal because a Symbol is not a String.
-    StringBuffer buffer = new StringBuffer();
-    for (Token component in node.components) {
-      if (buffer.length > 0) {
-        buffer.writeCharCode(0x2E);
-      }
-      buffer.write(component.lexeme);
-    }
-    return buffer.toString();
-  }
-
-  /**
-   * Return the constant value of the static constant represented by the given
-   * [element].
-   */
-  Object _getConstantValue(Element element) {
-    // TODO(brianwilkerson) Implement this
-//    if (element is FieldElement) {
-//      FieldElement field = element;
-//      if (field.isStatic && field.isConst) {
-//        //field.getConstantValue();
-//      }
-//      //    } else if (element instanceof VariableElement) {
-//      //      VariableElement variable = (VariableElement) element;
-//      //      if (variable.isStatic() && variable.isConst()) {
-//      //        //variable.getConstantValue();
-//      //      }
-//    }
-    return NOT_A_CONSTANT;
-  }
-}
-
-/**
  * A recursive AST visitor that is used to run over [Expression]s to determine
  * whether the expression is composed by at least one deferred
  * [PrefixedIdentifier].
@@ -2920,138 +2498,6 @@
 }
 
 /**
- * An object used to locate the [Element] associated with a given [AstNode].
- */
-class ElementLocator {
-  /**
-   * Return the element associated with the given [node], or `null` if there is
-   * no element associated with the node.
-   */
-  static Element locate(AstNode node) {
-    if (node == null) {
-      return null;
-    }
-    ElementLocator_ElementMapper mapper = new ElementLocator_ElementMapper();
-    return node.accept(mapper);
-  }
-}
-
-/**
- * Visitor that maps nodes to elements.
- */
-class ElementLocator_ElementMapper extends GeneralizingAstVisitor<Element> {
-  @override
-  Element visitAnnotation(Annotation node) => node.element;
-
-  @override
-  Element visitAssignmentExpression(AssignmentExpression node) =>
-      node.staticElement;
-
-  @override
-  Element visitBinaryExpression(BinaryExpression node) => node.staticElement;
-
-  @override
-  Element visitClassDeclaration(ClassDeclaration node) => node.declaredElement;
-
-  @override
-  Element visitCompilationUnit(CompilationUnit node) => node.declaredElement;
-
-  @override
-  Element visitConstructorDeclaration(ConstructorDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  Element visitExportDirective(ExportDirective node) => node.element;
-
-  @override
-  Element visitFunctionDeclaration(FunctionDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  Element visitIdentifier(Identifier node) {
-    AstNode parent = node.parent;
-    if (parent is Annotation) {
-      // Type name in Annotation
-      if (identical(parent.name, node) && parent.constructorName == null) {
-        return parent.element;
-      }
-    } else if (parent is ConstructorDeclaration) {
-      // Extra work to map Constructor Declarations to their associated
-      // Constructor Elements
-      Identifier returnType = parent.returnType;
-      if (identical(returnType, node)) {
-        SimpleIdentifier name = parent.name;
-        if (name != null) {
-          return name.staticElement;
-        }
-        Element element = node.staticElement;
-        if (element is ClassElement) {
-          return element.unnamedConstructor;
-        }
-      }
-    } else if (parent is LibraryIdentifier) {
-      AstNode grandParent = parent.parent;
-      if (grandParent is PartOfDirective) {
-        Element element = grandParent.element;
-        if (element is LibraryElement) {
-          return element.definingCompilationUnit;
-        }
-      } else if (grandParent is LibraryDirective) {
-        return grandParent.element;
-      }
-    }
-    return node.staticElement;
-  }
-
-  @override
-  Element visitImportDirective(ImportDirective node) => node.element;
-
-  @override
-  Element visitIndexExpression(IndexExpression node) => node.staticElement;
-
-  @override
-  Element visitInstanceCreationExpression(InstanceCreationExpression node) =>
-      node.staticElement;
-
-  @override
-  Element visitLibraryDirective(LibraryDirective node) => node.element;
-
-  @override
-  Element visitMethodDeclaration(MethodDeclaration node) =>
-      node.declaredElement;
-
-  @override
-  Element visitMethodInvocation(MethodInvocation node) =>
-      node.methodName.staticElement;
-
-  @override
-  Element visitPartOfDirective(PartOfDirective node) => node.element;
-
-  @override
-  Element visitPostfixExpression(PostfixExpression node) => node.staticElement;
-
-  @override
-  Element visitPrefixedIdentifier(PrefixedIdentifier node) =>
-      node.staticElement;
-
-  @override
-  Element visitPrefixExpression(PrefixExpression node) => node.staticElement;
-
-  @override
-  Element visitStringLiteral(StringLiteral node) {
-    AstNode parent = node.parent;
-    if (parent is UriBasedDirective) {
-      return parent.uriElement;
-    }
-    return null;
-  }
-
-  @override
-  Element visitVariableDeclaration(VariableDeclaration node) =>
-      node.declaredElement;
-}
-
-/**
  * A [DelegatingAstVisitor] that will additionally catch all exceptions from the
  * delegates without stopping the visiting. A function must be provided that
  * will be invoked for each such exception.
@@ -3299,26 +2745,6 @@
           _mapToken(node.semicolon));
 
   @override
-  CollectionForElement visitCollectionForElement(CollectionForElement node) =>
-      astFactory.collectionForElement(
-          forKeyword: _mapToken(node.forKeyword),
-          leftParenthesis: _mapToken(node.leftParenthesis),
-          forLoopParts: _cloneNode(node.forLoopParts),
-          rightParenthesis: _mapToken(node.rightParenthesis),
-          body: _cloneNode(node.body));
-
-  @override
-  CollectionIfElement visitCollectionIfElement(CollectionIfElement node) =>
-      astFactory.collectionIfElement(
-          ifKeyword: _mapToken(node.ifKeyword),
-          leftParenthesis: _mapToken(node.leftParenthesis),
-          condition: _cloneNode(node.condition),
-          rightParenthesis: _mapToken(node.rightParenthesis),
-          thenElement: _cloneNode(node.thenElement),
-          elseKeyword: _mapToken(node.elseKeyword),
-          elseElement: _cloneNode(node.elseElement));
-
-  @override
   Comment visitComment(Comment node) {
     if (node.isDocumentation) {
       return astFactory.documentationComment(
@@ -3574,6 +3000,14 @@
   }
 
   @override
+  ForElement visitForElement(ForElement node) => astFactory.forElement(
+      forKeyword: _mapToken(node.forKeyword),
+      leftParenthesis: _mapToken(node.leftParenthesis),
+      forLoopParts: _cloneNode(node.forLoopParts),
+      rightParenthesis: _mapToken(node.rightParenthesis),
+      body: _cloneNode(node.body));
+
+  @override
   FormalParameterList visitFormalParameterList(FormalParameterList node) =>
       astFactory.formalParameterList(
           _mapToken(node.leftParenthesis),
@@ -3715,6 +3149,16 @@
           _mapToken(node.keyword), _cloneNodeList(node.hiddenNames));
 
   @override
+  IfElement visitIfElement(IfElement node) => astFactory.ifElement(
+      ifKeyword: _mapToken(node.ifKeyword),
+      leftParenthesis: _mapToken(node.leftParenthesis),
+      condition: _cloneNode(node.condition),
+      rightParenthesis: _mapToken(node.rightParenthesis),
+      thenElement: _cloneNode(node.thenElement),
+      elseKeyword: _mapToken(node.elseKeyword),
+      elseElement: _cloneNode(node.elseElement));
+
+  @override
   IfStatement visitIfStatement(IfStatement node) => astFactory.ifStatement(
       _mapToken(node.ifKeyword),
       _mapToken(node.leftParenthesis),
@@ -3860,25 +3304,6 @@
       rightBracket: _mapToken(node.rightBracket));
 
   @override
-  MapForElement visitMapForElement(MapForElement node) =>
-      astFactory.mapForElement(
-          forKeyword: _mapToken(node.forKeyword),
-          leftParenthesis: _mapToken(node.leftParenthesis),
-          forLoopParts: _cloneNode(node.forLoopParts),
-          rightParenthesis: _mapToken(node.rightParenthesis),
-          body: _cloneNode(node.body));
-
-  @override
-  MapIfElement visitMapIfElement(MapIfElement node) => astFactory.mapIfElement(
-      ifKeyword: _mapToken(node.ifKeyword),
-      leftParenthesis: _mapToken(node.leftParenthesis),
-      condition: _cloneNode(node.condition),
-      rightParenthesis: _mapToken(node.rightParenthesis),
-      thenElement: _cloneNode(node.thenElement),
-      elseKeyword: _mapToken(node.elseKeyword),
-      elseElement: _cloneNode(node.elseElement));
-
-  @override
   MapLiteral visitMapLiteral(MapLiteral node) {
     MapLiteral copy = astFactory.mapLiteral(
         _mapToken(node.constKeyword),
@@ -4777,36 +4202,6 @@
   }
 
   @override
-  bool visitCollectionForElement(CollectionForElement node) {
-    if (identical(node.forLoopParts, _oldNode)) {
-      (node as CollectionForElementImpl).forLoopParts =
-          _newNode as ForLoopParts;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      (node as CollectionForElementImpl).body = _newNode as CollectionElement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitCollectionIfElement(CollectionIfElement node) {
-    if (identical(node.condition, _oldNode)) {
-      (node as CollectionIfElementImpl).condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.thenElement, _oldNode)) {
-      (node as CollectionIfElementImpl).thenElement =
-          _newNode as CollectionElement;
-      return true;
-    } else if (identical(node.elseElement, _oldNode)) {
-      (node as CollectionIfElementImpl).elseElement =
-          _newNode as CollectionElement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
   bool visitComment(Comment node) {
     if (_replaceInList(node.references)) {
       return true;
@@ -5094,6 +4489,18 @@
   }
 
   @override
+  bool visitForElement(ForElement node) {
+    if (identical(node.forLoopParts, _oldNode)) {
+      (node as ForElementImpl).forLoopParts = _newNode as ForLoopParts;
+      return true;
+    } else if (identical(node.body, _oldNode)) {
+      (node as ForElementImpl).body = _newNode as CollectionElement;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
   bool visitFormalParameterList(FormalParameterList node) {
     if (_replaceInList(node.parameters)) {
       return true;
@@ -5282,6 +4689,21 @@
   }
 
   @override
+  bool visitIfElement(IfElement node) {
+    if (identical(node.condition, _oldNode)) {
+      (node as IfElementImpl).condition = _newNode as Expression;
+      return true;
+    } else if (identical(node.thenElement, _oldNode)) {
+      (node as IfElementImpl).thenElement = _newNode as CollectionElement;
+      return true;
+    } else if (identical(node.elseElement, _oldNode)) {
+      (node as IfElementImpl).elseElement = _newNode as CollectionElement;
+      return true;
+    }
+    return visitNode(node);
+  }
+
+  @override
   bool visitIfStatement(IfStatement node) {
     if (identical(node.condition, _oldNode)) {
       node.condition = _newNode as Expression;
@@ -5421,33 +4843,6 @@
   }
 
   @override
-  bool visitMapForElement(MapForElement node) {
-    if (identical(node.forLoopParts, _oldNode)) {
-      (node as MapForElementImpl).forLoopParts = _newNode as ForLoopParts;
-      return true;
-    } else if (identical(node.body, _oldNode)) {
-      (node as MapForElementImpl).body = _newNode as MapElement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
-  bool visitMapIfElement(MapIfElement node) {
-    if (identical(node.condition, _oldNode)) {
-      (node as MapIfElementImpl).condition = _newNode as Expression;
-      return true;
-    } else if (identical(node.thenElement, _oldNode)) {
-      (node as MapIfElementImpl).thenElement = _newNode as MapElement;
-      return true;
-    } else if (identical(node.elseElement, _oldNode)) {
-      (node as MapIfElementImpl).elseElement = _newNode as MapElement;
-      return true;
-    }
-    return visitNode(node);
-  }
-
-  @override
   bool visitMapLiteral(MapLiteral node) {
     if (_replaceInList(node.entries)) {
       return true;
@@ -6213,30 +5608,6 @@
   }
 
   @override
-  bool visitCollectionForElement(CollectionForElement node) {
-    CollectionForElement toNode = this._toNode as CollectionForElement;
-    return _and(
-        _isEqualTokens(node.forKeyword, toNode.forKeyword),
-        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
-        _isEqualNodes(node.forLoopParts, toNode.forLoopParts),
-        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
-        _isEqualNodes(node.body, toNode.body));
-  }
-
-  @override
-  bool visitCollectionIfElement(CollectionIfElement node) {
-    CollectionIfElement toNode = this._toNode as CollectionIfElement;
-    return _and(
-        _isEqualTokens(node.ifKeyword, toNode.ifKeyword),
-        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
-        _isEqualNodes(node.condition, toNode.condition),
-        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
-        _isEqualNodes(node.thenElement, toNode.thenElement),
-        _isEqualTokens(node.elseKeyword, toNode.elseKeyword),
-        _isEqualNodes(node.elseElement, toNode.elseElement));
-  }
-
-  @override
   bool visitComment(Comment node) {
     Comment toNode = this._toNode as Comment;
     return _isEqualNodeLists(node.references, toNode.references);
@@ -6540,6 +5911,17 @@
   }
 
   @override
+  bool visitForElement(ForElement node) {
+    ForElement toNode = this._toNode as ForElement;
+    return _and(
+        _isEqualTokens(node.forKeyword, toNode.forKeyword),
+        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
+        _isEqualNodes(node.forLoopParts, toNode.forLoopParts),
+        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
+        _isEqualNodes(node.body, toNode.body));
+  }
+
+  @override
   bool visitFormalParameterList(FormalParameterList node) {
     FormalParameterList toNode = this._toNode as FormalParameterList;
     return _and(
@@ -6713,6 +6095,19 @@
   }
 
   @override
+  bool visitIfElement(IfElement node) {
+    IfElement toNode = this._toNode as IfElement;
+    return _and(
+        _isEqualTokens(node.ifKeyword, toNode.ifKeyword),
+        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
+        _isEqualNodes(node.condition, toNode.condition),
+        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
+        _isEqualNodes(node.thenElement, toNode.thenElement),
+        _isEqualTokens(node.elseKeyword, toNode.elseKeyword),
+        _isEqualNodes(node.elseElement, toNode.elseElement));
+  }
+
+  @override
   bool visitIfStatement(IfStatement node) {
     IfStatement toNode = this._toNode as IfStatement;
     return _and(
@@ -6893,30 +6288,6 @@
   }
 
   @override
-  bool visitMapForElement(MapForElement node) {
-    MapForElement toNode = this._toNode as MapForElement;
-    return _and(
-        _isEqualTokens(node.forKeyword, toNode.forKeyword),
-        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
-        _isEqualNodes(node.forLoopParts, toNode.forLoopParts),
-        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
-        _isEqualNodes(node.body, toNode.body));
-  }
-
-  @override
-  bool visitMapIfElement(MapIfElement node) {
-    MapIfElement toNode = this._toNode as MapIfElement;
-    return _and(
-        _isEqualTokens(node.ifKeyword, toNode.ifKeyword),
-        _isEqualTokens(node.leftParenthesis, toNode.leftParenthesis),
-        _isEqualNodes(node.condition, toNode.condition),
-        _isEqualTokens(node.rightParenthesis, toNode.rightParenthesis),
-        _isEqualNodes(node.thenElement, toNode.thenElement),
-        _isEqualTokens(node.elseKeyword, toNode.elseKeyword),
-        _isEqualNodes(node.elseElement, toNode.elseElement));
-  }
-
-  @override
   bool visitMapLiteral(MapLiteral node) {
     MapLiteral toNode = this._toNode as MapLiteral;
     if (_and(
@@ -7982,23 +7353,6 @@
   }
 
   @override
-  void visitCollectionForElement(CollectionForElement node) {
-    _writer.print('for (');
-    _visitNode(node.forLoopParts);
-    _writer.print(') ');
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitCollectionIfElement(CollectionIfElement node) {
-    _writer.print('if (');
-    _visitNode(node.condition);
-    _writer.print(') ');
-    _visitNode(node.thenElement);
-    _visitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
   void visitComment(Comment node) {}
 
   @override
@@ -8221,6 +7575,14 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    _writer.print('for (');
+    _visitNode(node.forLoopParts);
+    _writer.print(') ');
+    _visitNode(node.body);
+  }
+
+  @override
   void visitFormalParameterList(FormalParameterList node) {
     String groupEnd = null;
     _writer.print('(');
@@ -8372,6 +7734,15 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    _writer.print('if (');
+    _visitNode(node.condition);
+    _writer.print(') ');
+    _visitNode(node.thenElement);
+    _visitNodeWithPrefix(' else ', node.elseElement);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     _writer.print("if (");
     _visitNode(node.condition);
@@ -8498,23 +7869,6 @@
   }
 
   @override
-  void visitMapForElement(MapForElement node) {
-    _writer.print('for (');
-    _visitNode(node.forLoopParts);
-    _writer.print(') ');
-    _visitNode(node.body);
-  }
-
-  @override
-  void visitMapIfElement(MapIfElement node) {
-    _writer.print('if (');
-    _visitNode(node.condition);
-    _writer.print(') ');
-    _visitNode(node.thenElement);
-    _visitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
   void visitMapLiteral(MapLiteral node) {
     if (node.constKeyword != null) {
       _writer.print(node.constKeyword.lexeme);
@@ -9326,23 +8680,6 @@
   }
 
   @override
-  void visitCollectionForElement(CollectionForElement node) {
-    sink.write('for (');
-    safelyVisitNode(node.forLoopParts);
-    sink.write(') ');
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitCollectionIfElement(CollectionIfElement node) {
-    sink.write('if (');
-    safelyVisitNode(node.condition);
-    sink.write(') ');
-    safelyVisitNode(node.thenElement);
-    safelyVisitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
   void visitComment(Comment node) {}
 
   @override
@@ -9565,6 +8902,14 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    sink.write('for (');
+    safelyVisitNode(node.forLoopParts);
+    sink.write(') ');
+    safelyVisitNode(node.body);
+  }
+
+  @override
   void visitFormalParameterList(FormalParameterList node) {
     String groupEnd = null;
     sink.write('(');
@@ -9716,6 +9061,15 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    sink.write('if (');
+    safelyVisitNode(node.condition);
+    sink.write(') ');
+    safelyVisitNode(node.thenElement);
+    safelyVisitNodeWithPrefix(' else ', node.elseElement);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     sink.write("if (");
     safelyVisitNode(node.condition);
@@ -9839,23 +9193,6 @@
   }
 
   @override
-  void visitMapForElement(MapForElement node) {
-    sink.write('for (');
-    safelyVisitNode(node.forLoopParts);
-    sink.write(') ');
-    safelyVisitNode(node.body);
-  }
-
-  @override
-  void visitMapIfElement(MapIfElement node) {
-    sink.write('if (');
-    safelyVisitNode(node.condition);
-    sink.write(') ');
-    safelyVisitNode(node.thenElement);
-    safelyVisitNodeWithPrefix(' else ', node.elseElement);
-  }
-
-  @override
   void visitMapLiteral(MapLiteral node) {
     safelyVisitTokenWithSuffix(node.constKeyword, ' ');
     safelyVisitNodeWithSuffix(node.typeArguments, " ");
diff --git a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
index 453c439..024eca2 100644
--- a/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
+++ b/pkg/analyzer/lib/src/dart/constant/constant_verifier.dart
@@ -103,7 +103,7 @@
   void visitConstructorDeclaration(ConstructorDeclaration node) {
     if (node.constKeyword != null) {
       _validateConstructorInitializers(node);
-      _validateFieldInitializers(node.parent as ClassDeclaration, node);
+      _validateFieldInitializers(node.parent, node);
     }
     _validateDefaultValues(node.parameters);
     super.visitConstructorDeclaration(node);
@@ -548,8 +548,8 @@
   ///
   /// @param classDeclaration the class which should be validated
   /// @param errorSite the site at which errors should be reported.
-  void _validateFieldInitializers(
-      ClassDeclaration classDeclaration, ConstructorDeclaration errorSite) {
+  void _validateFieldInitializers(ClassOrMixinDeclaration classDeclaration,
+      ConstructorDeclaration errorSite) {
     NodeList<ClassMember> members = classDeclaration.members;
     for (ClassMember member in members) {
       if (member is FieldDeclaration && !member.isStatic) {
diff --git a/pkg/analyzer/lib/src/dart/constant/evaluation.dart b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
index 4e6bcd8..ee9cc60 100644
--- a/pkg/analyzer/lib/src/dart/constant/evaluation.dart
+++ b/pkg/analyzer/lib/src/dart/constant/evaluation.dart
@@ -1429,7 +1429,7 @@
     }
     Map<DartObjectImpl, DartObjectImpl> map = {};
     bool errorOccurred = false;
-    for (MapElement element in node.entries) {
+    for (CollectionElement element in node.entries) {
       errorOccurred = errorOccurred | _addElementsToMap(map, element);
     }
     if (errorOccurred) {
@@ -1660,7 +1660,7 @@
    * elements failed.
    */
   bool _addElementsToList(List<DartObject> list, CollectionElement element) {
-    if (element is CollectionIfElement) {
+    if (element is IfElement) {
       DartObjectImpl conditionResult = element.condition.accept(this);
       bool conditionValue = conditionResult?.toBoolValue();
       if (conditionValue == null) {
@@ -1697,8 +1697,8 @@
    * failed.
    */
   bool _addElementsToMap(
-      Map<DartObjectImpl, DartObjectImpl> map, MapElement element) {
-    if (element is MapIfElement) {
+      Map<DartObjectImpl, DartObjectImpl> map, CollectionElement element) {
+    if (element is IfElement) {
       DartObjectImpl conditionResult = element.condition.accept(this);
       bool conditionValue = conditionResult?.toBoolValue();
       if (conditionValue == null) {
@@ -1736,7 +1736,7 @@
    * elements failed.
    */
   bool _addElementsToSet(Set<DartObject> set, CollectionElement element) {
-    if (element is CollectionIfElement) {
+    if (element is IfElement) {
       DartObjectImpl conditionResult = element.condition.accept(this);
       bool conditionValue = conditionResult?.toBoolValue();
       if (conditionValue == null) {
diff --git a/pkg/analyzer/lib/src/dart/element/builder.dart b/pkg/analyzer/lib/src/dart/element/builder.dart
index 9aac7f7..e213e85 100644
--- a/pkg/analyzer/lib/src/dart/element/builder.dart
+++ b/pkg/analyzer/lib/src/dart/element/builder.dart
@@ -1179,8 +1179,16 @@
         new LocalVariableElementImpl.forNode(variableName);
     _setCodeRange(element, node);
     element.metadata = _createElementAnnotations(node.metadata);
-    ForEachStatement statement = node.parent as ForEachStatement;
-    element.setVisibleRange(statement.offset, statement.length);
+
+    var parent = node.parent;
+    if (parent is ForEachStatement) {
+      var statement = parent;
+      element.setVisibleRange(statement.offset, statement.length);
+    } else if (parent is ForEachPartsWithDeclaration) {
+      var statement = parent.parent;
+      element.setVisibleRange(statement.offset, statement.length);
+    }
+
     element.isConst = node.isConst;
     element.isFinal = node.isFinal;
     if (node.type == null) {
diff --git a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
index 8acdc92..b2fb92f 100644
--- a/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
+++ b/pkg/analyzer/lib/src/dart/element/inheritance_manager2.dart
@@ -43,10 +43,37 @@
 
   InheritanceManager2(this._typeSystem);
 
-  /// Return the member with the given [name] that the [type] inherits from the
-  /// mixins, superclasses, or interfaces; or `null` if no member is inherited.
+  /// Return the most specific signature of the member with the given [name]
+  /// that the [type] inherits from the mixins, superclasses, or interfaces;
+  /// or `null` if no member is inherited because the member is not declared
+  /// at all, or because there is no the most specific signature.
+  ///
+  /// This is equivalent to `getInheritedMap(type)[name]`.
   FunctionType getInherited(InterfaceType type, Name name) {
-    return getOverridden(type, name)?.last;
+    return getInheritedMap(type)[name];
+  }
+
+  /// Return signatures of all concrete members that the given [type] inherits
+  /// from the superclasses and mixins.
+  Map<Name, FunctionType> getInheritedConcreteMap(InterfaceType type) {
+    var interface = getInterface(type);
+    return interface._superImplemented.last;
+  }
+
+  /// Return the mapping from names to most specific signatures of members
+  /// inherited from the super-interfaces (superclasses, mixins, and
+  /// interfaces).  If there is no most specific signature for a name, the
+  /// corresponding name will not be included.
+  Map<Name, FunctionType> getInheritedMap(InterfaceType type) {
+    var interface = getInterface(type);
+    if (interface._inheritedMap == null) {
+      interface._inheritedMap = {};
+      _findMostSpecificFromNamedCandidates(
+        interface._inheritedMap,
+        interface._overridden,
+      );
+    }
+    return interface._inheritedMap;
   }
 
   /// Return the interface of the given [type].  It might include private
@@ -116,9 +143,9 @@
 
           implemented = <Name, FunctionType>{}
             ..addAll(implemented)
-            ..addAll(interfaceObj.implementedForMixing);
+            ..addAll(interfaceObj._implementedForMixing);
           superImplemented.add(implemented);
-          implementedForMixing.addAll(interfaceObj.implementedForMixing);
+          implementedForMixing.addAll(interfaceObj._implementedForMixing);
         }
       }
     } finally {
@@ -152,12 +179,12 @@
     var noSuchMethodForwarders = Set<Name>();
     if (classElement.isAbstract) {
       if (superInterface != null) {
-        noSuchMethodForwarders = superInterface.noSuchMethodForwarders;
+        noSuchMethodForwarders = superInterface._noSuchMethodForwarders;
       }
     } else {
       var noSuchMethod = implemented[_noSuchMethodName]?.element;
       if (noSuchMethod != null && !_isDeclaredInObject(noSuchMethod)) {
-        var superForwarders = superInterface?.noSuchMethodForwarders;
+        var superForwarders = superInterface?._noSuchMethodForwarders;
         for (var name in map.keys) {
           if (!implemented.containsKey(name) ||
               superForwarders != null && superForwarders.contains(name)) {
@@ -419,11 +446,11 @@
   final Map<Name, FunctionType> implemented;
 
   /// The set of names that are `noSuchMethod` forwarders in [implemented].
-  final Set<Name> noSuchMethodForwarders;
+  final Set<Name> _noSuchMethodForwarders;
 
   /// The map of names to their concrete implementations that can be mixed
   /// when this type is used as a mixin.
-  final Map<Name, FunctionType> implementedForMixing;
+  final Map<Name, FunctionType> _implementedForMixing;
 
   /// The map of names to their signatures from the mixins, superclasses,
   /// or interfaces.
@@ -440,12 +467,16 @@
   /// members of the class.
   final List<Conflict> conflicts;
 
+  /// The map of names to the most specific signatures from the mixins,
+  /// superclasses, or interfaces.
+  Map<Name, FunctionType> _inheritedMap;
+
   Interface._(
     this.map,
     this.declared,
     this.implemented,
-    this.noSuchMethodForwarders,
-    this.implementedForMixing,
+    this._noSuchMethodForwarders,
+    this._implementedForMixing,
     this._overridden,
     this._superImplemented,
     this.conflicts,
diff --git a/pkg/analyzer/lib/src/dart/error/hint_codes.dart b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
index 62c6a8a..185e224 100644
--- a/pkg/analyzer/lib/src/dart/error/hint_codes.dart
+++ b/pkg/analyzer/lib/src/dart/error/hint_codes.dart
@@ -280,6 +280,17 @@
       const HintCode('INVALID_USE_OF_VISIBLE_FOR_TESTING_MEMBER',
           "The member '{0}' can only be used within '{1}' or a test.");
 
+  /// This hint is generated anywhere where a private declaration is annotated
+  /// with `@visibleForTemplate` or `@visibleForTesting`.
+  ///
+  /// Parameters:
+  /// 0: the name of the member
+  /// 1: the name of the annotation
+  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.");
+
   /**
    * Hint for the `x is double` type checks.
    */
diff --git a/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
new file mode 100644
index 0000000..2f558cf
--- /dev/null
+++ b/pkg/analyzer/lib/src/dart/resolver/exit_detector.dart
@@ -0,0 +1,724 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/token.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// Instances of the class `ExitDetector` determine whether the visited AST node
+/// is guaranteed to terminate by executing a `return` statement, `throw`
+/// expression, `rethrow` expression, or simple infinite loop such as
+/// `while(true)`.
+class ExitDetector extends GeneralizingAstVisitor<bool> {
+  /// Set to `true` when a `break` is encountered, and reset to `false` when a
+  /// `do`, `while`, `for` or `switch` block is entered.
+  bool _enclosingBlockContainsBreak = false;
+
+  /// Set to `true` when a `continue` is encountered, and reset to `false` when
+  /// a `do`, `while`, `for` or `switch` block is entered.
+  bool _enclosingBlockContainsContinue = false;
+
+  /// Add node when a labelled `break` is encountered.
+  Set<AstNode> _enclosingBlockBreaksLabel = new Set<AstNode>();
+
+  @override
+  bool visitArgumentList(ArgumentList node) =>
+      _visitExpressions(node.arguments);
+
+  @override
+  bool visitAsExpression(AsExpression node) => _nodeExits(node.expression);
+
+  @override
+  bool visitAssertInitializer(AssertInitializer node) => false;
+
+  @override
+  bool visitAssertStatement(AssertStatement node) => false;
+
+  @override
+  bool visitAssignmentExpression(AssignmentExpression node) {
+    Expression leftHandSide = node.leftHandSide;
+    if (_nodeExits(leftHandSide)) {
+      return true;
+    }
+    TokenType operatorType = node.operator.type;
+    if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
+        operatorType == TokenType.BAR_BAR_EQ ||
+        operatorType == TokenType.QUESTION_QUESTION_EQ) {
+      return false;
+    }
+    if (leftHandSide is PropertyAccess &&
+        leftHandSide.operator.type == TokenType.QUESTION_PERIOD) {
+      return false;
+    }
+    return _nodeExits(node.rightHandSide);
+  }
+
+  @override
+  bool visitAwaitExpression(AwaitExpression node) =>
+      _nodeExits(node.expression);
+
+  @override
+  bool visitBinaryExpression(BinaryExpression node) {
+    Expression lhsExpression = node.leftOperand;
+    Expression rhsExpression = node.rightOperand;
+    TokenType operatorType = node.operator.type;
+    // If the operator is ||, then only consider the RHS of the binary
+    // expression if the left hand side is the false literal.
+    // TODO(jwren) Do we want to take constant expressions into account,
+    // evaluate if(false) {} differently than if(<condition>), when <condition>
+    // evaluates to a constant false value?
+    if (operatorType == TokenType.BAR_BAR) {
+      if (lhsExpression is BooleanLiteral) {
+        if (!lhsExpression.value) {
+          return _nodeExits(rhsExpression);
+        }
+      }
+      return _nodeExits(lhsExpression);
+    }
+    // If the operator is &&, then only consider the RHS of the binary
+    // expression if the left hand side is the true literal.
+    if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
+      if (lhsExpression is BooleanLiteral) {
+        if (lhsExpression.value) {
+          return _nodeExits(rhsExpression);
+        }
+      }
+      return _nodeExits(lhsExpression);
+    }
+    // If the operator is ??, then don't consider the RHS of the binary
+    // expression.
+    if (operatorType == TokenType.QUESTION_QUESTION) {
+      return _nodeExits(lhsExpression);
+    }
+    return _nodeExits(lhsExpression) || _nodeExits(rhsExpression);
+  }
+
+  @override
+  bool visitBlock(Block node) => _visitStatements(node.statements);
+
+  @override
+  bool visitBlockFunctionBody(BlockFunctionBody node) => _nodeExits(node.block);
+
+  @override
+  bool visitBreakStatement(BreakStatement node) {
+    _enclosingBlockContainsBreak = true;
+    if (node.label != null) {
+      _enclosingBlockBreaksLabel.add(node.target);
+    }
+    return false;
+  }
+
+  @override
+  bool visitCascadeExpression(CascadeExpression node) =>
+      _nodeExits(node.target) || _visitExpressions(node.cascadeSections);
+
+  @override
+  bool visitConditionalExpression(ConditionalExpression node) {
+    Expression conditionExpression = node.condition;
+    Expression thenStatement = node.thenExpression;
+    Expression elseStatement = node.elseExpression;
+    // TODO(jwren) Do we want to take constant expressions into account,
+    // evaluate if(false) {} differently than if(<condition>), when <condition>
+    // evaluates to a constant false value?
+    if (_nodeExits(conditionExpression)) {
+      return true;
+    }
+    if (thenStatement == null || elseStatement == null) {
+      return false;
+    }
+    return thenStatement.accept(this) && elseStatement.accept(this);
+  }
+
+  @override
+  bool visitContinueStatement(ContinueStatement node) {
+    _enclosingBlockContainsContinue = true;
+    return false;
+  }
+
+  @override
+  bool visitDoStatement(DoStatement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    bool outerContinueValue = _enclosingBlockContainsContinue;
+    _enclosingBlockContainsBreak = false;
+    _enclosingBlockContainsContinue = false;
+    try {
+      bool bodyExits = _nodeExits(node.body);
+      bool containsBreakOrContinue =
+          _enclosingBlockContainsBreak || _enclosingBlockContainsContinue;
+      // Even if we determine that the body "exits", there might be break or
+      // continue statements that actually mean it _doesn't_ always exit.
+      if (bodyExits && !containsBreakOrContinue) {
+        return true;
+      }
+      Expression conditionExpression = node.condition;
+      if (_nodeExits(conditionExpression)) {
+        return true;
+      }
+      // TODO(jwren) Do we want to take all constant expressions into account?
+      if (conditionExpression is BooleanLiteral) {
+        // If do {} while (true), and the body doesn't break, then return true.
+        if (conditionExpression.value && !_enclosingBlockContainsBreak) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+      _enclosingBlockContainsContinue = outerContinueValue;
+    }
+  }
+
+  @override
+  bool visitEmptyStatement(EmptyStatement node) => false;
+
+  @override
+  bool visitExpressionStatement(ExpressionStatement node) =>
+      _nodeExits(node.expression);
+
+  @override
+  bool visitForEachStatement(ForEachStatement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    try {
+      bool iterableExits = _nodeExits(node.iterable);
+      // Discard whether the for-each body exits; since the for-each iterable
+      // may be empty, execution may never enter the body, so it doesn't matter
+      // if it exits or not.  We still must visit the body, to accurately
+      // manage `_enclosingBlockBreaksLabel`.
+      _nodeExits(node.body);
+      return iterableExits;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+  }
+
+  @override
+  bool visitForElement(ForElement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    try {
+      ForLoopParts forLoopParts = node.forLoopParts;
+      if (forLoopParts is ForParts) {
+        if (forLoopParts is ForPartsWithDeclarations) {
+          if (forLoopParts.variables != null &&
+              _visitVariableDeclarations(forLoopParts.variables.variables)) {
+            return true;
+          }
+        } else if (forLoopParts is ForPartsWithExpression) {
+          if (forLoopParts.initialization != null &&
+              _nodeExits(forLoopParts.initialization)) {
+            return true;
+          }
+        }
+        Expression conditionExpression = forLoopParts.condition;
+        if (conditionExpression != null && _nodeExits(conditionExpression)) {
+          return true;
+        }
+        if (_visitExpressions(forLoopParts.updaters)) {
+          return true;
+        }
+        bool blockReturns = _nodeExits(node.body);
+        // TODO(jwren) Do we want to take all constant expressions into account?
+        // If for(; true; ) (or for(;;)), and the body doesn't return or the body
+        // doesn't have a break, then return true.
+        bool implicitOrExplictTrue = conditionExpression == null ||
+            (conditionExpression is BooleanLiteral &&
+                conditionExpression.value);
+        if (implicitOrExplictTrue) {
+          if (blockReturns || !_enclosingBlockContainsBreak) {
+            return true;
+          }
+        }
+        return false;
+      } else if (forLoopParts is ForEachParts) {
+        bool iterableExits = _nodeExits(forLoopParts.iterable);
+        // Discard whether the for-each body exits; since the for-each iterable
+        // may be empty, execution may never enter the body, so it doesn't matter
+        // if it exits or not.  We still must visit the body, to accurately
+        // manage `_enclosingBlockBreaksLabel`.
+        _nodeExits(node.body);
+        return iterableExits;
+      }
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+    return false;
+  }
+
+  @override
+  bool visitForStatement(ForStatement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    try {
+      if (node.variables != null &&
+          _visitVariableDeclarations(node.variables.variables)) {
+        return true;
+      }
+      if (node.initialization != null && _nodeExits(node.initialization)) {
+        return true;
+      }
+      Expression conditionExpression = node.condition;
+      if (conditionExpression != null && _nodeExits(conditionExpression)) {
+        return true;
+      }
+      if (_visitExpressions(node.updaters)) {
+        return true;
+      }
+      bool blockReturns = _nodeExits(node.body);
+      // TODO(jwren) Do we want to take all constant expressions into account?
+      // If for(; true; ) (or for(;;)), and the body doesn't return or the body
+      // doesn't have a break, then return true.
+      bool implicitOrExplictTrue = conditionExpression == null ||
+          (conditionExpression is BooleanLiteral && conditionExpression.value);
+      if (implicitOrExplictTrue) {
+        if (blockReturns || !_enclosingBlockContainsBreak) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+  }
+
+  @override
+  bool visitForStatement2(ForStatement2 node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    ForLoopParts parts = node.forLoopParts;
+    try {
+      if (parts is ForEachParts) {
+        bool iterableExits = _nodeExits(parts.iterable);
+        // Discard whether the for-each body exits; since the for-each iterable
+        // may be empty, execution may never enter the body, so it doesn't matter
+        // if it exits or not.  We still must visit the body, to accurately
+        // manage `_enclosingBlockBreaksLabel`.
+        _nodeExits(node.body);
+        return iterableExits;
+      }
+      VariableDeclarationList variables;
+      Expression initialization;
+      Expression condition;
+      NodeList<Expression> updaters;
+      if (parts is ForPartsWithDeclarations) {
+        variables = parts.variables;
+        condition = parts.condition;
+        updaters = parts.updaters;
+      } else if (parts is ForPartsWithExpression) {
+        initialization = parts.initialization;
+        condition = parts.condition;
+        updaters = parts.updaters;
+      }
+      if (variables != null &&
+          _visitVariableDeclarations(variables.variables)) {
+        return true;
+      }
+      if (initialization != null && _nodeExits(initialization)) {
+        return true;
+      }
+      if (condition != null && _nodeExits(condition)) {
+        return true;
+      }
+      if (_visitExpressions(updaters)) {
+        return true;
+      }
+      bool blockReturns = _nodeExits(node.body);
+      // TODO(jwren) Do we want to take all constant expressions into account?
+      // If for(; true; ) (or for(;;)), and the body doesn't return or the body
+      // doesn't have a break, then return true.
+      bool implicitOrExplictTrue =
+          condition == null || (condition is BooleanLiteral && condition.value);
+      if (implicitOrExplictTrue) {
+        if (blockReturns || !_enclosingBlockContainsBreak) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+  }
+
+  @override
+  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
+      false;
+
+  @override
+  bool visitFunctionExpression(FunctionExpression node) => false;
+
+  @override
+  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
+    if (_nodeExits(node.function)) {
+      return true;
+    }
+    return node.argumentList.accept(this);
+  }
+
+  @override
+  bool visitGenericFunctionType(GenericFunctionType node) => false;
+
+  @override
+  bool visitIdentifier(Identifier node) => false;
+
+  @override
+  bool visitIfElement(IfElement node) {
+    Expression conditionExpression = node.condition;
+    CollectionElement thenElement = node.thenElement;
+    CollectionElement elseElement = node.elseElement;
+    if (_nodeExits(conditionExpression)) {
+      return true;
+    }
+
+    bool conditionValue = _knownConditionValue(conditionExpression);
+    if (conditionValue == true) {
+      return _nodeExits(thenElement);
+    } else if (conditionValue == false && elseElement != null) {
+      return _nodeExits(elseElement);
+    }
+
+    bool thenExits = _nodeExits(thenElement);
+    bool elseExits = _nodeExits(elseElement);
+    if (thenElement == null || elseElement == null) {
+      return false;
+    }
+    return thenExits && elseExits;
+  }
+
+  @override
+  bool visitIfStatement(IfStatement node) {
+    Expression conditionExpression = node.condition;
+    Statement thenStatement = node.thenStatement;
+    Statement elseStatement = node.elseStatement;
+    if (_nodeExits(conditionExpression)) {
+      return true;
+    }
+
+    bool conditionValue = _knownConditionValue(conditionExpression);
+    if (conditionValue == true) {
+      return _nodeExits(thenStatement);
+    } else if (conditionValue == false && elseStatement != null) {
+      return _nodeExits(elseStatement);
+    }
+
+    bool thenExits = _nodeExits(thenStatement);
+    bool elseExits = _nodeExits(elseStatement);
+    if (thenStatement == null || elseStatement == null) {
+      return false;
+    }
+    return thenExits && elseExits;
+  }
+
+  @override
+  bool visitIndexExpression(IndexExpression node) {
+    Expression target = node.realTarget;
+    if (_nodeExits(target)) {
+      return true;
+    }
+    if (_nodeExits(node.index)) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  bool visitInstanceCreationExpression(InstanceCreationExpression node) =>
+      _nodeExits(node.argumentList);
+
+  @override
+  bool visitIsExpression(IsExpression node) => node.expression.accept(this);
+
+  @override
+  bool visitLabel(Label node) => false;
+
+  @override
+  bool visitLabeledStatement(LabeledStatement node) {
+    try {
+      bool statementExits = _nodeExits(node.statement);
+      bool neverBrokeFromLabel =
+          !_enclosingBlockBreaksLabel.contains(node.statement);
+      return statementExits && neverBrokeFromLabel;
+    } finally {
+      _enclosingBlockBreaksLabel.remove(node.statement);
+    }
+  }
+
+  @override
+  bool visitListLiteral2(ListLiteral2 node) {
+    for (CollectionElement element in node.elements) {
+      if (_nodeExits(element)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool visitLiteral(Literal node) => false;
+
+  @override
+  bool visitMapLiteral2(MapLiteral2 node) {
+    for (CollectionElement entry in node.entries) {
+      if (_nodeExits(entry)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool visitMapLiteralEntry(MapLiteralEntry node) {
+    return _nodeExits(node.key) || _nodeExits(node.value);
+  }
+
+  @override
+  bool visitMethodInvocation(MethodInvocation node) {
+    Expression target = node.realTarget;
+    if (target != null) {
+      if (target.accept(this)) {
+        return true;
+      }
+      if (node.operator.type == TokenType.QUESTION_PERIOD) {
+        return false;
+      }
+    }
+    Element element = node.methodName.staticElement;
+    if (element != null && element.hasAlwaysThrows) {
+      return true;
+    }
+    return _nodeExits(node.argumentList);
+  }
+
+  @override
+  bool visitNamedExpression(NamedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  bool visitNode(AstNode node) {
+    throw new StateError(
+        'Missing a visit method for a node of type ${node.runtimeType}');
+  }
+
+  @override
+  bool visitParenthesizedExpression(ParenthesizedExpression node) =>
+      node.expression.accept(this);
+
+  @override
+  bool visitPostfixExpression(PostfixExpression node) => false;
+
+  @override
+  bool visitPrefixExpression(PrefixExpression node) => false;
+
+  @override
+  bool visitPropertyAccess(PropertyAccess node) {
+    Expression target = node.realTarget;
+    if (target != null && target.accept(this)) {
+      return true;
+    }
+    return false;
+  }
+
+  @override
+  bool visitRethrowExpression(RethrowExpression node) => true;
+
+  @override
+  bool visitReturnStatement(ReturnStatement node) => true;
+
+  @override
+  bool visitSetLiteral2(SetLiteral2 node) {
+    for (CollectionElement element in node.elements) {
+      if (_nodeExits(element)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool visitSpreadElement(SpreadElement node) {
+    return _nodeExits(node.expression);
+  }
+
+  @override
+  bool visitSuperExpression(SuperExpression node) => false;
+
+  @override
+  bool visitSwitchCase(SwitchCase node) => _visitStatements(node.statements);
+
+  @override
+  bool visitSwitchDefault(SwitchDefault node) =>
+      _visitStatements(node.statements);
+
+  @override
+  bool visitSwitchStatement(SwitchStatement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    try {
+      bool hasDefault = false;
+      bool hasNonExitingCase = false;
+      List<SwitchMember> members = node.members;
+      for (int i = 0; i < members.length; i++) {
+        SwitchMember switchMember = members[i];
+        if (switchMember is SwitchDefault) {
+          hasDefault = true;
+          // If this is the last member and there are no statements, then it
+          // does not exit.
+          if (switchMember.statements.isEmpty && i + 1 == members.length) {
+            hasNonExitingCase = true;
+            continue;
+          }
+        }
+        // For switch members with no statements, don't visit the children.
+        // Otherwise, if there children statements don't exit, mark this as a
+        // non-exiting case.
+        if (!switchMember.statements.isEmpty && !switchMember.accept(this)) {
+          hasNonExitingCase = true;
+        }
+      }
+      if (hasNonExitingCase) {
+        return false;
+      }
+      // As all cases exit, return whether that list includes `default`.
+      return hasDefault;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+  }
+
+  @override
+  bool visitThisExpression(ThisExpression node) => false;
+
+  @override
+  bool visitThrowExpression(ThrowExpression node) => true;
+
+  @override
+  bool visitTryStatement(TryStatement node) {
+    if (_nodeExits(node.finallyBlock)) {
+      return true;
+    }
+    if (!_nodeExits(node.body)) {
+      return false;
+    }
+    for (CatchClause c in node.catchClauses) {
+      if (!_nodeExits(c.body)) {
+        return false;
+      }
+    }
+    return true;
+  }
+
+  @override
+  bool visitTypeName(TypeName node) => false;
+
+  @override
+  bool visitVariableDeclaration(VariableDeclaration node) {
+    Expression initializer = node.initializer;
+    if (initializer != null) {
+      return initializer.accept(this);
+    }
+    return false;
+  }
+
+  @override
+  bool visitVariableDeclarationList(VariableDeclarationList node) =>
+      _visitVariableDeclarations(node.variables);
+
+  @override
+  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
+    NodeList<VariableDeclaration> variables = node.variables.variables;
+    for (int i = 0; i < variables.length; i++) {
+      if (variables[i].accept(this)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  @override
+  bool visitWhileStatement(WhileStatement node) {
+    bool outerBreakValue = _enclosingBlockContainsBreak;
+    _enclosingBlockContainsBreak = false;
+    try {
+      Expression conditionExpression = node.condition;
+      if (conditionExpression.accept(this)) {
+        return true;
+      }
+      node.body.accept(this);
+      // TODO(jwren) Do we want to take all constant expressions into account?
+      if (conditionExpression is BooleanLiteral) {
+        // If while(true), and the body doesn't have a break, then return true.
+        // The body might be found to exit, but if there are any break
+        // statements, then it is a faulty finding. In other words:
+        //
+        // * If the body exits, and does not contain a break statement, then
+        //   it exits.
+        // * If the body does not exit, and does not contain a break statement,
+        //   then it loops infinitely (also an exit).
+        //
+        // As both conditions forbid any break statements to be found, the logic
+        // just boils down to checking [_enclosingBlockContainsBreak].
+        if (conditionExpression.value && !_enclosingBlockContainsBreak) {
+          return true;
+        }
+      }
+      return false;
+    } finally {
+      _enclosingBlockContainsBreak = outerBreakValue;
+    }
+  }
+
+  @override
+  bool visitYieldStatement(YieldStatement node) => _nodeExits(node.expression);
+
+  /// If the given [expression] has a known Boolean value, return the known
+  /// value, otherwise return `null`.
+  bool _knownConditionValue(Expression conditionExpression) {
+    // TODO(jwren) Do we want to take all constant expressions into account?
+    if (conditionExpression is BooleanLiteral) {
+      return conditionExpression.value;
+    }
+    return null;
+  }
+
+  /// Return `true` if the given [node] exits.
+  bool _nodeExits(AstNode node) {
+    if (node == null) {
+      return false;
+    }
+    return node.accept(this);
+  }
+
+  bool _visitExpressions(NodeList<Expression> expressions) {
+    for (int i = expressions.length - 1; i >= 0; i--) {
+      if (expressions[i].accept(this)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool _visitStatements(NodeList<Statement> statements) {
+    for (int i = 0; i < statements.length; i++) {
+      if (statements[i].accept(this)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  bool _visitVariableDeclarations(
+      NodeList<VariableDeclaration> variableDeclarations) {
+    for (int i = variableDeclarations.length - 1; i >= 0; i--) {
+      if (variableDeclarations[i].accept(this)) {
+        return true;
+      }
+    }
+    return false;
+  }
+
+  /// Return `true` if the given [node] exits.
+  static bool exits(AstNode node) {
+    return new ExitDetector()._nodeExits(node);
+  }
+}
diff --git a/pkg/analyzer/lib/src/dart/resolver/flow_analysis.dart b/pkg/analyzer/lib/src/dart/resolver/flow_analysis.dart
index 5301558..1c8dc31 100644
--- a/pkg/analyzer/lib/src/dart/resolver/flow_analysis.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/flow_analysis.dart
@@ -4,16 +4,54 @@
 
 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/type_system.dart';
 
-class FlowAnalysis {
+/// Sets of variables that are potentially assigned in a node.
+class AssignedVariables {
+  static final emptySet = Set<VariableElement>();
+
+  /// Mapping from a loop [AstNode] to the set of variables that are
+  /// potentially assigned in this loop.
+  final Map<AstNode, Set<VariableElement>> _map = {};
+
+  /// The stack of nested loops.
+  final List<Set<VariableElement>> _stack = [];
+
+  /// Return the set of variables that are potentially assigned in the [loop].
+  Set<VariableElement> operator [](AstNode loop) {
+    return _map[loop] ?? emptySet;
+  }
+
+  void beginLoop() {
+    var set = Set<VariableElement>.identity();
+    _stack.add(set);
+  }
+
+  void endLoop(AstNode loop) {
+    _map[loop] = _stack.removeLast();
+  }
+
+  void write(VariableElement variable) {
+    for (var i = 0; i < _stack.length; ++i) {
+      _stack[i].add(variable);
+    }
+  }
+}
+
+class FlowAnalysis<T> {
+  final _identity = _State<T>(
+    false,
+    _ElementSet.empty,
+    _ElementSet.empty,
+    _ElementSet.empty,
+    const {},
+  );
+
   /// The output list of variables that were read before they were written.
   /// TODO(scheglov) use _ElementSet?
   final List<LocalVariableElement> readBeforeWritten = [];
 
-  /// The [TypeSystem] of the enclosing library, used to check subtyping.
-  final TypeSystem typeSystem;
+  /// The [TypeOperations], used to access types, and check subtyping.
+  final TypeOperations<T> typeOperations;
 
   /// The enclosing [FunctionBody], used to check for potential mutations.
   final FunctionBody functionBody;
@@ -27,29 +65,37 @@
   /// states.
   final Map<Statement, int> _statementToStackIndex = {};
 
-  _State _current;
+  /// The list of all variables.
+  final List<VariableElement> _variables = [];
+
+  _State<T> _current;
 
   /// The last boolean condition, for [_conditionTrue] and [_conditionFalse].
   Expression _condition;
 
   /// The state when [_condition] evaluates to `true`.
-  _State _conditionTrue;
+  _State<T> _conditionTrue;
 
   /// The state when [_condition] evaluates to `false`.
-  _State _conditionFalse;
+  _State<T> _conditionFalse;
 
-  FlowAnalysis(this.typeSystem, this.functionBody) {
-    _current = _State(true, _ElementSet.empty, const {});
+  FlowAnalysis(this.typeOperations, this.functionBody) {
+    _current = _State<T>(
+      true,
+      _ElementSet.empty,
+      _ElementSet.empty,
+      _ElementSet.empty,
+      const {},
+    );
   }
 
   /// Return `true` if the current state is reachable.
   bool get isReachable => _current.reachable;
 
   /// Add a new [variable], which might be already [assigned].
-  void add(LocalVariableElement variable, {bool assigned: false}) {
-    if (!assigned) {
-      _current = _current.add(variable);
-    }
+  void add(VariableElement variable, {bool assigned: false}) {
+    _variables.add(variable);
+    _current = _current.add(variable, assigned: assigned);
   }
 
   void conditional_elseBegin(ConditionalExpression node, bool isBool) {
@@ -79,15 +125,15 @@
       var trueThen = _stack.removeLast();
       var falseThen = _stack.removeLast();
 
-      var trueResult = trueThen.combine(typeSystem, trueElse);
-      var falseResult = falseThen.combine(typeSystem, falseElse);
+      var trueResult = _join(trueThen, trueElse);
+      var falseResult = _join(falseThen, falseElse);
 
       _condition = node;
       _conditionTrue = trueResult;
       _conditionFalse = falseResult;
     }
 
-    _current = afterThen.combine(typeSystem, afterElse);
+    _current = _join(afterThen, afterElse);
   }
 
   void conditional_thenBegin(ConditionalExpression node) {
@@ -98,20 +144,42 @@
     _current = trueCondition;
   }
 
+  /// The [node] checks that the [variable] is equal to `null`.
+  void conditionEqNull(BinaryExpression node, VariableElement variable) {
+    if (functionBody.isPotentiallyMutatedInClosure(variable)) {
+      return;
+    }
+
+    _condition = node;
+    _conditionTrue = _current.markNullable(variable);
+    _conditionFalse = _current.markNonNullable(variable);
+  }
+
+  /// The [node] checks that the [variable] is not equal to `null`.
+  void conditionNotEqNull(BinaryExpression node, VariableElement variable) {
+    if (functionBody.isPotentiallyMutatedInClosure(variable)) {
+      return;
+    }
+
+    _condition = node;
+    _conditionTrue = _current.markNonNullable(variable);
+    _conditionFalse = _current.markNullable(variable);
+  }
+
   void doStatement_bodyBegin(
       DoStatement node, Set<VariableElement> loopAssigned) {
     _current = _current.removePromotedAll(loopAssigned);
 
     _statementToStackIndex[node] = _stack.length;
-    _stack.add(_State.identity); // break
-    _stack.add(_State.identity); // continue
+    _stack.add(_identity); // break
+    _stack.add(_identity); // continue
   }
 
   void doStatement_conditionBegin() {
     // Tail of the stack: break, continue
 
     var continueState = _stack.removeLast();
-    _current = _current.combine(typeSystem, continueState);
+    _current = _join(_current, continueState);
   }
 
   void doStatement_end(DoStatement node) {
@@ -122,12 +190,12 @@
     var falseCondition = _stack.removeLast();
     var breakState = _stack.removeLast();
 
-    _current = falseCondition.combine(typeSystem, breakState);
+    _current = _join(falseCondition, breakState);
   }
 
   void falseLiteral(BooleanLiteral expression) {
     _condition = expression;
-    _conditionTrue = _State.identity;
+    _conditionTrue = _identity;
     _conditionFalse = _current;
   }
 
@@ -138,7 +206,7 @@
 
   void forEachStatement_end() {
     var afterIterable = _stack.removeLast();
-    _current = _current.combine(typeSystem, afterIterable);
+    _current = _join(_current, afterIterable);
   }
 
   void forStatement_bodyBegin(Statement node, Expression condition) {
@@ -148,8 +216,8 @@
     var trueCondition = _stack.removeLast();
 
     _statementToStackIndex[node] = _stack.length;
-    _stack.add(_State.identity); // break
-    _stack.add(_State.identity); // continue
+    _stack.add(_identity); // break
+    _stack.add(_identity); // continue
 
     _current = trueCondition;
   }
@@ -163,7 +231,7 @@
     var breakState = _stack.removeLast();
     var falseCondition = _stack.removeLast();
 
-    _current = falseCondition.combine(typeSystem, breakState);
+    _current = _join(falseCondition, breakState);
   }
 
   void forStatement_updaterBegin() {
@@ -171,7 +239,7 @@
     var afterBody = _current;
     var continueState = _stack.removeLast();
 
-    _current = afterBody.combine(typeSystem, continueState);
+    _current = _join(afterBody, continueState);
   }
 
   void functionExpression_begin() {
@@ -197,30 +265,29 @@
   void handleBreak(AstNode target) {
     var breakIndex = _statementToStackIndex[target];
     if (breakIndex != null) {
-      _stack[breakIndex] = _stack[breakIndex].combine(typeSystem, _current);
+      _stack[breakIndex] = _join(_stack[breakIndex], _current);
     }
-    _current = _State.identity;
+    _current = _current.exit();
   }
 
   void handleContinue(AstNode target) {
     var breakIndex = _statementToStackIndex[target];
     if (breakIndex != null) {
       var continueIndex = breakIndex + 1;
-      _stack[continueIndex] =
-          _stack[continueIndex].combine(typeSystem, _current);
+      _stack[continueIndex] = _join(_stack[continueIndex], _current);
     }
-    _current = _State.identity;
+    _current = _current.exit();
   }
 
   /// Register the fact that the current state definitely exists, e.g. returns
   /// from the body, throws an exception, etc.
   void handleExit() {
-    _current = _State.identity;
+    _current = _current.exit();
   }
 
   void ifNullExpression_end() {
     var afterLeft = _stack.removeLast();
-    _current = _current.combine(typeSystem, afterLeft);
+    _current = _join(_current, afterLeft);
   }
 
   void ifNullExpression_rightBegin() {
@@ -235,8 +302,8 @@
   }
 
   void ifStatement_end(bool hasElse) {
-    _State afterThen;
-    _State afterElse;
+    _State<T> afterThen;
+    _State<T> afterElse;
     if (hasElse) {
       afterThen = _stack.removeLast();
       afterElse = _current;
@@ -244,7 +311,7 @@
       afterThen = _current; // no `else`, so `then` is still current
       afterElse = _stack.removeLast(); // `falseCond` is still on the stack
     }
-    _current = afterThen.combine(typeSystem, afterElse);
+    _current = _join(afterThen, afterElse);
   }
 
   void ifStatement_thenBegin(IfStatement ifStatement) {
@@ -256,21 +323,31 @@
   }
 
   void isExpression_end(
-      IsExpression isExpression, VariableElement variable, DartType type) {
+      IsExpression isExpression, VariableElement variable, T type) {
     if (functionBody.isPotentiallyMutatedInClosure(variable)) {
       return;
     }
 
     _condition = isExpression;
     if (isExpression.notOperator == null) {
-      _conditionTrue = _current.promote(typeSystem, variable, type);
+      _conditionTrue = _current.promote(typeOperations, variable, type);
       _conditionFalse = _current;
     } else {
       _conditionTrue = _current;
-      _conditionFalse = _current.promote(typeSystem, variable, type);
+      _conditionFalse = _current.promote(typeOperations, variable, type);
     }
   }
 
+  /// Return `true` if the [variable] is known to be be nullable.
+  bool isNonNullable(VariableElement variable) {
+    return !_current.notNonNullable.contains(variable);
+  }
+
+  /// Return `true` if the [variable] is known to be be non-nullable.
+  bool isNullable(VariableElement variable) {
+    return !_current.notNullable.contains(variable);
+  }
+
   void logicalAnd_end(BinaryExpression andExpression) {
     _conditionalEnd(andExpression.rightOperand);
     // Tail of the stack: falseLeft, trueLeft, falseRight, trueRight
@@ -282,8 +359,8 @@
     var falseLeft = _stack.removeLast();
 
     var trueResult = trueRight;
-    var falseResult = falseLeft.combine(typeSystem, falseRight);
-    var afterResult = trueResult.combine(typeSystem, falseResult);
+    var falseResult = _join(falseLeft, falseRight);
+    var afterResult = _join(trueResult, falseResult);
 
     _condition = andExpression;
     _conditionTrue = trueResult;
@@ -320,9 +397,9 @@
     var trueLeft = _stack.removeLast();
     _stack.removeLast(); // falseLeft is not used
 
-    var trueResult = trueLeft.combine(typeSystem, trueRight);
+    var trueResult = _join(trueLeft, trueRight);
     var falseResult = falseRight;
-    var afterResult = trueResult.combine(typeSystem, falseResult);
+    var afterResult = _join(trueResult, falseResult);
 
     _condition = orExpression;
     _conditionTrue = trueResult;
@@ -341,7 +418,7 @@
 
   /// Retrieves the type that the [variable] is promoted to, if the [variable]
   /// is currently promoted.  Otherwise returns `null`.
-  DartType promotedType(VariableElement variable) {
+  T promotedType(VariableElement variable) {
     return _current.promoted[variable];
   }
 
@@ -376,62 +453,66 @@
     if (hasDefault) {
       _current = breakState;
     } else {
-      _current = breakState.combine(typeSystem, afterExpression);
+      _current = _join(breakState, afterExpression);
     }
   }
 
   void switchStatement_expressionEnd(SwitchStatement node) {
     _statementToStackIndex[node] = _stack.length;
-    _stack.add(_State.identity); // break
-    _stack.add(_State.identity); // continue
+    _stack.add(_identity); // break
+    _stack.add(_identity); // continue
     _stack.add(_current); // afterExpression
   }
 
   void trueLiteral(BooleanLiteral expression) {
     _condition = expression;
     _conditionTrue = _current;
-    _conditionFalse = _State.identity;
+    _conditionFalse = _identity;
   }
 
-  void tryStatement_bodyBegin() {
+  void tryCatchStatement_bodyBegin() {
     _stack.add(_current);
     // Tail of the stack: beforeBody
   }
 
-  void tryStatement_bodyEnd(Set<VariableElement> notPromoted) {
+  void tryCatchStatement_bodyEnd(Set<VariableElement> assignedInBody) {
     var beforeBody = _stack.removeLast();
-    var beforeCatch = beforeBody.removePromotedAll(notPromoted);
+    var beforeCatch = beforeBody.removePromotedAll(assignedInBody);
     _stack.add(beforeCatch);
     _stack.add(_current); // afterBodyAndCatches
     // Tail of the stack: beforeCatch, afterBodyAndCatches
   }
 
-  void tryStatement_catchBegin() {
+  void tryCatchStatement_catchBegin() {
     var beforeCatch = _stack[_stack.length - 2];
     _current = beforeCatch;
   }
 
-  void tryStatement_catchEnd() {
+  void tryCatchStatement_catchEnd() {
     var afterBodyAndCatches = _stack.last;
-    _stack.last = afterBodyAndCatches.combine(typeSystem, _current);
+    _stack.last = _join(afterBodyAndCatches, _current);
   }
 
-  void tryStatement_end() {
+  void tryCatchStatement_end() {
     var afterBodyAndCatches = _stack.removeLast();
-    _current = _current.setReachable(afterBodyAndCatches.reachable);
+    _stack.removeLast(); // beforeCatch
+    _current = afterBodyAndCatches;
   }
 
-  void tryStatement_finallyBegin() {
-    // TODO(scheglov) This code is incomplete, so has bug.
-    // `finally` might be executed:
-    // (1) on exception in the body or a catch;
-    // (2) on normal completion of the body or a catch;
-    // The code below only works for (1).
-    var afterBodyAndCatches = _stack.removeLast();
-    var beforeCatch = _stack.removeLast();
+  void tryFinallyStatement_bodyBegin() {
+    _stack.add(_current); // beforeTry
+  }
 
-    _current = afterBodyAndCatches.setReachable(beforeCatch.reachable);
-    _stack.add(afterBodyAndCatches); // for 'reachable'
+  void tryFinallyStatement_end(Set<VariableElement> assignedInFinally) {
+    var afterBody = _stack.removeLast();
+    _current = _current.restrict(typeOperations, afterBody, assignedInFinally);
+  }
+
+  void tryFinallyStatement_finallyBegin(Set<VariableElement> assignedInBody) {
+    var beforeTry = _stack.removeLast();
+    var afterBody = _current;
+    _stack.add(afterBody);
+    _current = _join(afterBody, beforeTry.removePromotedAll(assignedInBody));
   }
 
   void verifyStackEmpty() {
@@ -445,8 +526,8 @@
     var trueCondition = _stack.removeLast();
 
     _statementToStackIndex[node] = _stack.length;
-    _stack.add(_State.identity); // break
-    _stack.add(_State.identity); // continue
+    _stack.add(_identity); // break
+    _stack.add(_identity); // continue
 
     _current = trueCondition;
   }
@@ -460,12 +541,16 @@
     var breakState = _stack.removeLast();
     var falseCondition = _stack.removeLast();
 
-    _current = falseCondition.combine(typeSystem, breakState);
+    _current = _join(falseCondition, breakState);
   }
 
   /// Register write of the given [variable] in the current state.
-  void write(VariableElement variable) {
-    _current = _current.write(variable);
+  void write(
+    VariableElement variable, {
+    bool isNull = false,
+    bool isNonNull = false,
+  }) {
+    _current = _current.write(variable, isNull: isNull, isNonNull: isNonNull);
   }
 
   void _conditionalEnd(Expression condition) {
@@ -480,57 +565,94 @@
       _stack.add(_current);
     }
   }
+
+  _State<T> _join(_State<T> first, _State<T> second) {
+    if (identical(first, _identity)) return second;
+    if (identical(second, _identity)) return first;
+
+    if (first.reachable && !second.reachable) return first;
+    if (!first.reachable && second.reachable) return second;
+
+    var newReachable = first.reachable || second.reachable;
+    var newNotAssigned = first.notAssigned.union(second.notAssigned);
+    var newNotNullable = first.notNullable.union(second.notNullable);
+    var newNotNonNullable = first.notNonNullable.union(second.notNonNullable);
+    var newPromoted = _joinPromoted(first.promoted, second.promoted);
+
+    return _State._identicalOrNew(
+      first,
+      second,
+      newReachable,
+      newNotAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      newPromoted,
+    );
+  }
+
+  Map<VariableElement, T> _joinPromoted(
+    Map<VariableElement, T> first,
+    Map<VariableElement, T> second,
+  ) {
+    if (identical(first, second)) return first;
+    if (first.isEmpty || second.isEmpty) return const {};
+
+    var result = <VariableElement, T>{};
+    var alwaysFirst = true;
+    var alwaysSecond = true;
+    for (var element in first.keys) {
+      var firstType = first[element];
+      var secondType = second[element];
+      if (firstType != null && secondType != null) {
+        if (typeOperations.isSubtypeOf(firstType, secondType)) {
+          result[element] = secondType;
+          alwaysFirst = false;
+        } else if (typeOperations.isSubtypeOf(secondType, firstType)) {
+          result[element] = firstType;
+          alwaysSecond = false;
+        } else {
+          alwaysFirst = false;
+          alwaysSecond = false;
+        }
+      } else {
+        alwaysFirst = false;
+        alwaysSecond = false;
+      }
+    }
+
+    if (alwaysFirst) return first;
+    if (alwaysSecond) return second;
+    if (result.isEmpty) return const {};
+    return result;
+  }
 }
 
-/// Sets of variables that are potentially assigned in loops.
-class LoopAssignedVariables {
-  static final emptySet = Set<VariableElement>();
+/// Operations on types, abstracted from concrete type interfaces.
+abstract class TypeOperations<T> {
+  /// Return the static type of with the given [element].
+  T elementType(VariableElement element);
 
-  /// Mapping from a loop [AstNode] to the set of variables that are
-  /// potentially assigned in this loop.
-  final Map<AstNode, Set<VariableElement>> _map = {};
-
-  /// The stack of nested loops.
-  final List<Set<VariableElement>> _stack = [];
-
-  /// Return the set of variables that are potentially assigned in the [loop].
-  Set<VariableElement> operator [](AstNode loop) {
-    return _map[loop] ?? emptySet;
-  }
-
-  void beginLoop() {
-    var set = Set<VariableElement>.identity();
-    _stack.add(set);
-  }
-
-  void endLoop(AstNode loop) {
-    _map[loop] = _stack.removeLast();
-  }
-
-  void write(VariableElement variable) {
-    for (var i = 0; i < _stack.length; ++i) {
-      _stack[i].add(variable);
-    }
-  }
+  /// Return `true` if the [leftType] is a subtype of the [rightType].
+  bool isSubtypeOf(T leftType, T rightType);
 }
 
 /// List based immutable set of elements.
 class _ElementSet {
   static final empty = _ElementSet._(
-    List<LocalVariableElement>(0),
+    List<VariableElement>(0),
   );
 
-  final List<LocalVariableElement> elements;
+  final List<VariableElement> elements;
 
   _ElementSet._(this.elements);
 
-  _ElementSet add(LocalVariableElement addedElement) {
+  _ElementSet add(VariableElement addedElement) {
     if (contains(addedElement)) {
       return this;
     }
 
     var length = elements.length;
-    var newElements = List<LocalVariableElement>(length + 1);
+    var newElements = List<VariableElement>(length + 1);
     for (var i = 0; i < length; ++i) {
       newElements[i] = elements[i];
     }
@@ -538,7 +660,15 @@
     return _ElementSet._(newElements);
   }
 
-  bool contains(LocalVariableElement element) {
+  _ElementSet addAll(Iterable<VariableElement> elements) {
+    var result = this;
+    for (var element in elements) {
+      result = result.add(element);
+    }
+    return result;
+  }
+
+  bool contains(VariableElement element) {
     var length = elements.length;
     for (var i = 0; i < length; ++i) {
       if (identical(elements[i], element)) {
@@ -548,7 +678,18 @@
     return false;
   }
 
-  _ElementSet remove(LocalVariableElement removedElement) {
+  _ElementSet intersect(_ElementSet other) {
+    if (identical(other, empty)) return empty;
+
+    // TODO(scheglov) optimize
+    var newElements =
+        elements.toSet().intersection(other.elements.toSet()).toList();
+
+    if (newElements.isEmpty) return empty;
+    return _ElementSet._(newElements);
+  }
+
+  _ElementSet remove(VariableElement removedElement) {
     if (!contains(removedElement)) {
       return this;
     }
@@ -558,7 +699,7 @@
       return empty;
     }
 
-    var newElements = List<LocalVariableElement>(length - 1);
+    var newElements = List<VariableElement>(length - 1);
     var newIndex = 0;
     for (var i = 0; i < length; ++i) {
       var element = elements[i];
@@ -571,7 +712,7 @@
   }
 
   _ElementSet union(_ElementSet other) {
-    if (other == null || other.elements.isEmpty) {
+    if (other.elements.isEmpty) {
       return this;
     }
 
@@ -585,125 +726,225 @@
   }
 }
 
-class _State {
-  static final identity = _State(false, _ElementSet.empty, const {});
-
+class _State<T> {
   final bool reachable;
   final _ElementSet notAssigned;
-  final Map<VariableElement, DartType> promoted;
+  final _ElementSet notNullable;
+  final _ElementSet notNonNullable;
+  final Map<VariableElement, T> promoted;
 
-  _State(this.reachable, this.notAssigned, this.promoted);
+  _State(
+    this.reachable,
+    this.notAssigned,
+    this.notNullable,
+    this.notNonNullable,
+    this.promoted,
+  );
 
   /// Add a new [variable] to track definite assignment.
-  _State add(LocalVariableElement variable) {
-    var newNotAssigned = notAssigned.add(variable);
-    if (identical(newNotAssigned, notAssigned)) return this;
-    return _State(reachable, newNotAssigned, promoted);
-  }
+  _State<T> add(VariableElement variable, {bool assigned: false}) {
+    var newNotAssigned = assigned ? notAssigned : notAssigned.add(variable);
+    var newNotNullable = notNullable.add(variable);
+    var newNotNonNullable = notNonNullable.add(variable);
 
-  _State combine(TypeSystem typeSystem, _State other) {
-    if (identical(this, identity)) return other;
-    if (identical(other, identity)) return this;
-
-    var newReachable = reachable || other.reachable;
-    var newNotAssigned = notAssigned.union(other.notAssigned);
-    var newPromoted = _combinePromoted(typeSystem, promoted, other.promoted);
-
-    if (reachable == newReachable &&
-        identical(notAssigned, newNotAssigned) &&
-        identical(promoted, newPromoted)) {
+    if (identical(newNotAssigned, notAssigned) &&
+        identical(newNotNullable, notNullable) &&
+        identical(newNotNonNullable, notNonNullable)) {
       return this;
     }
-    if (other.reachable == newReachable &&
-        identical(other.notAssigned, newNotAssigned) &&
-        identical(other.promoted, newPromoted)) {
-      return other;
-    }
 
-    return _State(newReachable, newNotAssigned, newPromoted);
+    return _State<T>(
+      reachable,
+      newNotAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      promoted,
+    );
   }
 
-  _State promote(
-      TypeSystem typeSystem, VariableElement variable, DartType type) {
-    var previousType = promoted[variable];
-    previousType ??= variable.type;
+  _State<T> exit() {
+    return _State<T>(false, notAssigned, notNullable, notNonNullable, promoted);
+  }
 
-    if (typeSystem.isSubtypeOf(type, previousType) && type != previousType) {
-      var newPromoted = <VariableElement, DartType>{}..addAll(promoted);
+  _State<T> markNonNullable(VariableElement variable) {
+    var newNotNullable = notNullable.add(variable);
+    var newNotNonNullable = notNonNullable.remove(variable);
+
+    if (identical(newNotNullable, notNullable) &&
+        identical(newNotNonNullable, notNonNullable)) {
+      return this;
+    }
+
+    return _State<T>(
+      reachable,
+      notAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      promoted,
+    );
+  }
+
+  _State<T> markNullable(VariableElement variable) {
+    var newNotNullable = notNullable.remove(variable);
+    var newNotNonNullable = notNonNullable.add(variable);
+
+    if (identical(newNotNullable, notNullable) &&
+        identical(newNotNonNullable, notNonNullable)) {
+      return this;
+    }
+
+    return _State<T>(
+      reachable,
+      notAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      promoted,
+    );
+  }
+
+  _State<T> promote(
+    TypeOperations<T> typeOperations,
+    VariableElement variable,
+    T type,
+  ) {
+    var previousType = promoted[variable];
+    previousType ??= typeOperations.elementType(variable);
+
+    if (typeOperations.isSubtypeOf(type, previousType) &&
+        type != previousType) {
+      var newPromoted = <VariableElement, T>{}..addAll(promoted);
       newPromoted[variable] = type;
-      return _State(reachable, notAssigned, newPromoted);
+      return _State<T>(
+        reachable,
+        notAssigned,
+        notNullable,
+        notNonNullable,
+        newPromoted,
+      );
     }
 
     return this;
   }
 
-  _State removePromotedAll(Set<VariableElement> variables) {
+  _State<T> removePromotedAll(Set<VariableElement> variables) {
+    var newNotNullable = notNullable.addAll(variables);
+    var newNotNonNullable = notNonNullable.addAll(variables);
     var newPromoted = _removePromotedAll(promoted, variables);
 
-    if (identical(newPromoted, promoted)) return this;
+    if (identical(newNotNullable, notNullable) &&
+        identical(newNotNonNullable, notNonNullable) &&
+        identical(newPromoted, promoted)) return this;
 
-    return _State(reachable, notAssigned, newPromoted);
+    return _State<T>(
+      reachable,
+      notAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      newPromoted,
+    );
   }
 
-  _State setReachable(bool reachable) {
+  _State<T> restrict(
+    TypeOperations<T> typeOperations,
+    _State<T> other,
+    Set<VariableElement> unsafe,
+  ) {
+    var newReachable = reachable && other.reachable;
+    var newNotAssigned = notAssigned.intersect(other.notAssigned);
+
+    var newNotNullable = _ElementSet.empty;
+    for (var variable in notNullable.elements) {
+      if (unsafe.contains(variable) || other.notNullable.contains(variable)) {
+        newNotNullable = newNotNullable.add(variable);
+      }
+    }
+
+    var newNotNonNullable = _ElementSet.empty;
+    for (var variable in notNonNullable.elements) {
+      if (unsafe.contains(variable) ||
+          other.notNonNullable.contains(variable)) {
+        newNotNonNullable = newNotNonNullable.add(variable);
+      }
+    }
+
+    var newPromoted = <VariableElement, T>{};
+    for (var variable in promoted.keys) {
+      var thisType = promoted[variable];
+      if (!unsafe.contains(variable)) {
+        var otherType = other.promoted[variable];
+        if (otherType != null &&
+            typeOperations.isSubtypeOf(otherType, thisType)) {
+          newPromoted[variable] = otherType;
+          continue;
+        }
+      }
+      newPromoted[variable] = thisType;
+    }
+
+    return _identicalOrNew(
+      this,
+      other,
+      newReachable,
+      newNotAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      newPromoted,
+    );
+  }
+
+  _State<T> setReachable(bool reachable) {
     if (this.reachable == reachable) return this;
 
-    return _State(reachable, notAssigned, promoted);
+    return _State<T>(
+      reachable,
+      notAssigned,
+      notNullable,
+      notNonNullable,
+      promoted,
+    );
   }
 
-  _State write(VariableElement variable) {
+  _State<T> write(
+    VariableElement variable, {
+    bool isNull = false,
+    bool isNonNull = false,
+  }) {
     var newNotAssigned = variable is LocalVariableElement
         ? notAssigned.remove(variable)
         : notAssigned;
+
+    var newNotNullable =
+        isNull ? notNullable.remove(variable) : notNullable.add(variable);
+
+    var newNotNonNullable = isNonNull
+        ? notNonNullable.remove(variable)
+        : notNonNullable.add(variable);
+
     var newPromoted = _removePromoted(promoted, variable);
 
     if (identical(newNotAssigned, notAssigned) &&
+        identical(newNotNullable, notNullable) &&
+        identical(newNotNonNullable, notNonNullable) &&
         identical(newPromoted, promoted)) {
       return this;
     }
 
-    return _State(reachable, newNotAssigned, newPromoted);
+    return _State<T>(
+      reachable,
+      newNotAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      newPromoted,
+    );
   }
 
-  static Map<VariableElement, DartType> _combinePromoted(TypeSystem typeSystem,
-      Map<VariableElement, DartType> a, Map<VariableElement, DartType> b) {
-    if (identical(a, b)) return a;
-    if (a.isEmpty || b.isEmpty) return const {};
-
-    var result = <VariableElement, DartType>{};
-    var alwaysA = true;
-    var alwaysB = true;
-    for (var element in a.keys) {
-      var aType = a[element];
-      var bType = b[element];
-      if (aType != null && bType != null) {
-        if (typeSystem.isSubtypeOf(aType, bType)) {
-          result[element] = bType;
-          alwaysA = false;
-        } else if (typeSystem.isSubtypeOf(bType, aType)) {
-          result[element] = aType;
-          alwaysB = false;
-        } else {
-          alwaysA = false;
-          alwaysB = false;
-        }
-      } else {
-        alwaysA = false;
-        alwaysB = false;
-      }
-    }
-
-    if (alwaysA) return a;
-    if (alwaysB) return b;
-    if (result.isEmpty) return const {};
-    return result;
-  }
-
-  static Map<VariableElement, DartType> _removePromoted(
-      Map<VariableElement, DartType> map, VariableElement variable) {
+  Map<VariableElement, T> _removePromoted(
+    Map<VariableElement, T> map,
+    VariableElement variable,
+  ) {
     if (map.isEmpty) return const {};
 
-    var result = <VariableElement, DartType>{};
+    var result = <VariableElement, T>{};
     for (var key in map.keys) {
       if (!identical(key, variable)) {
         result[key] = map[key];
@@ -714,18 +955,58 @@
     return result;
   }
 
-  static Map<VariableElement, DartType> _removePromotedAll(
-      Map<VariableElement, DartType> map, Set<VariableElement> variables) {
+  Map<VariableElement, T> _removePromotedAll(
+    Map<VariableElement, T> map,
+    Set<VariableElement> variables,
+  ) {
     if (map.isEmpty) return const {};
+    if (variables.isEmpty) return map;
 
-    var result = <VariableElement, DartType>{};
+    var result = <VariableElement, T>{};
+    var noChanges = true;
     for (var key in map.keys) {
-      if (!variables.contains(key)) {
+      if (variables.contains(key)) {
+        noChanges = false;
+      } else {
         result[key] = map[key];
       }
     }
 
+    if (noChanges) return map;
     if (result.isEmpty) return const {};
     return result;
   }
+
+  static _State<T> _identicalOrNew<T>(
+    _State<T> first,
+    _State<T> second,
+    bool newReachable,
+    _ElementSet newNotAssigned,
+    _ElementSet newNotNullable,
+    _ElementSet newNotNonNullable,
+    Map<VariableElement, T> newPromoted,
+  ) {
+    if (first.reachable == newReachable &&
+        identical(first.notAssigned, newNotAssigned) &&
+        identical(first.notNullable, newNotNullable) &&
+        identical(first.notNonNullable, newNotNonNullable) &&
+        identical(first.promoted, newPromoted)) {
+      return first;
+    }
+    if (second.reachable == newReachable &&
+        identical(second.notAssigned, newNotAssigned) &&
+        identical(second.notNullable, newNotNullable) &&
+        identical(second.notNonNullable, newNotNonNullable) &&
+        identical(second.promoted, newPromoted)) {
+      return second;
+    }
+
+    return _State<T>(
+      newReachable,
+      newNotAssigned,
+      newNotNullable,
+      newNotNonNullable,
+      newPromoted,
+    );
+  }
 }
diff --git a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
index ed4f68e..9e54c4c 100644
--- a/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
+++ b/pkg/analyzer/lib/src/dart/resolver/inheritance_manager.dart
@@ -21,6 +21,7 @@
  * Instances of the class `InheritanceManager` manage the knowledge of where class members
  * (methods, getters & setters) are inherited from.
  */
+@Deprecated('Use InheritanceManager2 instead.')
 class InheritanceManager {
   /**
    * The [LibraryElement] that is managed by this manager.
@@ -76,7 +77,7 @@
    * @return a mapping between the set of all members inherited from the passed [ClassElement]
    *         superclass hierarchy, and the associated [ExecutableElement]
    */
-  @deprecated
+  @Deprecated('Use InheritanceManager2.getInheritedConcreteMap() instead.')
   MemberMap getMapOfMembersInheritedFromClasses(ClassElement classElt) =>
       new MemberMap.fromMap(
           _computeClassChainLookupMap(classElt, new HashSet<ClassElement>()));
@@ -89,7 +90,7 @@
    * @return a mapping between the set of all string names of the members inherited from the passed
    *         [ClassElement] interface hierarchy, and the associated [ExecutableElement].
    */
-  @deprecated
+  @Deprecated('Use InheritanceManager2.getInheritedMap() instead.')
   MemberMap getMapOfMembersInheritedFromInterfaces(ClassElement classElt) =>
       new MemberMap.fromMap(
           _computeInterfaceLookupMap(classElt, new HashSet<ClassElement>()));
@@ -125,7 +126,7 @@
    * @return the inherited executable element with the member name, or `null` if no such
    *         member exists
    */
-  @deprecated
+  @Deprecated('Use InheritanceManager2.getInherited() instead.')
   ExecutableElement lookupInheritance(
       ClassElement classElt, String memberName) {
     if (memberName == null || memberName.isEmpty) {
@@ -150,7 +151,7 @@
    * @return the inherited executable element with the member name, or `null` if no such
    *         member exists
    */
-  @deprecated
+  @Deprecated('Use InheritanceManager2.getMember() instead.')
   ExecutableElement lookupMember(ClassElement classElt, String memberName) {
     ExecutableElement element = _lookupMemberInClass(classElt, memberName);
     if (element != null) {
@@ -169,7 +170,7 @@
    * @param memberName the name of the class member to query
    * @return a list of overridden methods
    */
-  @deprecated
+  @Deprecated('Use InheritanceManager2.getOverridden() instead.')
   List<ExecutableElement> lookupOverrides(
       ClassElement classElt, String memberName) {
     List<ExecutableElement> result = new List<ExecutableElement>();
diff --git a/pkg/analyzer/lib/src/error/codes.dart b/pkg/analyzer/lib/src/error/codes.dart
index 599447e..81dcb16 100644
--- a/pkg/analyzer/lib/src/error/codes.dart
+++ b/pkg/analyzer/lib/src/error/codes.dart
@@ -3899,7 +3899,8 @@
           'INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED',
           "Parameters can't override default values, "
           "this method overrides '{0}.{1}' where '{2}' has a different value.",
-          correction: "Try using the same default value in both methods.");
+          correction: "Try using the same default value in both methods.",
+          errorSeverity: ErrorSeverity.WARNING);
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method
@@ -3914,7 +3915,8 @@
           'INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL',
           "Parameters can't override default values, this method overrides "
           "'{0}.{1}' where this positional parameter has a different value.",
-          correction: "Try using the same default value in both methods.");
+          correction: "Try using the same default value in both methods.",
+          errorSeverity: ErrorSeverity.WARNING);
 
   /**
    * 7.1 Instance Methods: It is a static warning if an instance method
diff --git a/pkg/analyzer/lib/src/error/inheritance_override.dart b/pkg/analyzer/lib/src/error/inheritance_override.dart
index 20ecec0..a5f1196 100644
--- a/pkg/analyzer/lib/src/error/inheritance_override.dart
+++ b/pkg/analyzer/lib/src/error/inheritance_override.dart
@@ -164,7 +164,8 @@
           _checkDeclaredMember(fieldList, libraryUri, fieldElement.setter);
         }
       } else if (member is MethodDeclaration) {
-        _checkDeclaredMember(member, libraryUri, member.declaredElement);
+        _checkDeclaredMember(member, libraryUri, member.declaredElement,
+            methodParameterNodes: member.parameters?.parameters);
       }
     }
 
@@ -248,8 +249,9 @@
   void _checkDeclaredMember(
     AstNode node,
     Uri libraryUri,
-    ExecutableElement member,
-  ) {
+    ExecutableElement member, {
+    List<AstNode> methodParameterNodes,
+  }) {
     if (member == null) return;
     if (member.isStatic) return;
 
@@ -276,6 +278,13 @@
             ],
           );
         }
+        if (methodParameterNodes != null) {
+          _checkForOptionalParametersDifferentDefaultValues(
+            superMemberType.element,
+            member,
+            methodParameterNodes,
+          );
+        }
       }
     }
   }
@@ -406,6 +415,84 @@
     }
   }
 
+  void _checkForOptionalParametersDifferentDefaultValues(
+    ExecutableElement baseExecutable,
+    ExecutableElement derivedExecutable,
+    List<AstNode> derivedParameterNodes,
+  ) {
+    var derivedOptionalNodes = <AstNode>[];
+    var derivedOptionalElements = <ParameterElementImpl>[];
+    var derivedParameterElements = derivedExecutable.parameters;
+    for (var i = 0; i < derivedParameterElements.length; i++) {
+      var parameterElement = derivedParameterElements[i];
+      if (parameterElement.isOptional) {
+        derivedOptionalNodes.add(derivedParameterNodes[i]);
+        derivedOptionalElements.add(parameterElement);
+      }
+    }
+
+    var baseOptionalElements = <ParameterElementImpl>[];
+    var baseParameterElements = baseExecutable.parameters;
+    for (var i = 0; i < baseParameterElements.length; ++i) {
+      var baseParameter = baseParameterElements[i];
+      if (baseParameter.isOptional) {
+        baseOptionalElements.add(baseParameter);
+      }
+    }
+
+    // Stop if no optional parameters.
+    if (baseOptionalElements.isEmpty || derivedOptionalElements.isEmpty) {
+      return;
+    }
+
+    if (derivedOptionalElements[0].isNamed) {
+      for (int i = 0; i < derivedOptionalElements.length; i++) {
+        var derivedElement = derivedOptionalElements[i];
+        var name = derivedElement.name;
+        for (var j = 0; j < baseOptionalElements.length; j++) {
+          var baseParameter = baseOptionalElements[j];
+          if (name == baseParameter.name && baseParameter.initializer != null) {
+            var baseValue = baseParameter.computeConstantValue();
+            var derivedResult = derivedElement.evaluationResult;
+            if (derivedResult.value != baseValue) {
+              reporter.reportErrorForNode(
+                StaticWarningCode
+                    .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+                derivedOptionalNodes[i],
+                [
+                  baseExecutable.enclosingElement.displayName,
+                  baseExecutable.displayName,
+                  name
+                ],
+              );
+            }
+          }
+        }
+      }
+    } else {
+      for (var i = 0;
+          i < derivedOptionalElements.length && i < baseOptionalElements.length;
+          i++) {
+        var baseElement = baseOptionalElements[i];
+        if (baseElement.initializer != null) {
+          var baseValue = baseElement.computeConstantValue();
+          var derivedResult = derivedOptionalElements[i].evaluationResult;
+          if (derivedResult.value != baseValue) {
+            reporter.reportErrorForNode(
+              StaticWarningCode
+                  .INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+              derivedOptionalNodes[i],
+              [
+                baseExecutable.enclosingElement.displayName,
+                baseExecutable.displayName
+              ],
+            );
+          }
+        }
+      }
+    }
+  }
+
   /// Check that [classElement] is not a superinterface to itself.
   /// The [path] is a list containing the potentially cyclic implements path.
   ///
diff --git a/pkg/analyzer/lib/src/fasta/ast_builder.dart b/pkg/analyzer/lib/src/fasta/ast_builder.dart
index 0413025..edbcf3c 100644
--- a/pkg/analyzer/lib/src/fasta/ast_builder.dart
+++ b/pkg/analyzer/lib/src/fasta/ast_builder.dart
@@ -288,7 +288,7 @@
 
   @override
   void endIfControlFlow(Token token) {
-    var thenElement = pop();
+    CollectionElement thenElement = pop();
     ParenthesizedExpression condition = pop();
     Token ifToken = pop();
     pushIfControlFlowInfo(ifToken, condition, thenElement, null, null);
@@ -296,26 +296,31 @@
 
   @override
   void endIfElseControlFlow(Token token) {
-    var elseElement = pop();
+    CollectionElement elseElement = pop();
     Token elseToken = pop();
-    var thenElement = pop();
+    CollectionElement thenElement = pop();
     ParenthesizedExpression condition = pop();
     Token ifToken = pop();
     pushIfControlFlowInfo(
         ifToken, condition, thenElement, elseToken, elseElement);
   }
 
-  void pushIfControlFlowInfo(Token ifToken, ParenthesizedExpression condition,
-      var thenElement, Token elseToken, var elseElement) {
+  void pushIfControlFlowInfo(
+      Token ifToken,
+      ParenthesizedExpression condition,
+      CollectionElement thenElement,
+      Token elseToken,
+      CollectionElement elseElement) {
     if (enableControlFlowCollections) {
-      push(new _IfControlFlowInfo(
-          ifToken,
-          condition.leftParenthesis,
-          condition.expression,
-          condition.rightParenthesis,
-          thenElement,
-          elseToken,
-          elseElement));
+      push(ast.ifElement(
+        ifKeyword: ifToken,
+        leftParenthesis: condition.leftParenthesis,
+        condition: condition.expression,
+        rightParenthesis: condition.rightParenthesis,
+        thenElement: thenElement,
+        elseKeyword: elseToken,
+        elseElement: elseElement,
+      ));
     } else {
       handleRecoverableError(
           templateUnexpectedToken.withArguments(ifToken), ifToken, ifToken);
@@ -923,8 +928,14 @@
   void pushForControlFlowInfo(Token awaitToken, Token forToken,
       Token leftParenthesis, ForLoopParts forLoopParts, Object entry) {
     if (enableControlFlowCollections) {
-      push(new _ForControlFlowInfo(awaitToken, forToken, leftParenthesis,
-          forLoopParts, leftParenthesis.endGroup, entry));
+      push(ast.forElement(
+        awaitKeyword: awaitToken,
+        forKeyword: forToken,
+        leftParenthesis: leftParenthesis,
+        forLoopParts: forLoopParts,
+        rightParenthesis: leftParenthesis.endGroup,
+        body: entry as CollectionElement,
+      ));
     } else {
       handleRecoverableError(
           templateUnexpectedToken.withArguments(forToken), forToken, forToken);
@@ -978,12 +989,7 @@
     debugEvent("LiteralList");
 
     if (enableControlFlowCollections || enableSpreadCollections) {
-      List<CollectionElement> elements = <CollectionElement>[];
-      popTypedList(count)?.forEach((element) {
-        elements.add(element is _EntryInfo
-            ? element.asCollectionElement(ast)
-            : element as CollectionElement);
-      });
+      List<CollectionElement> elements = popCollectionElements(count);
 
       TypeArgumentList typeArguments = pop();
       push(ast.listLiteral2(
@@ -1058,12 +1064,7 @@
     debugEvent("LiteralSet");
 
     if (enableControlFlowCollections || enableSpreadCollections) {
-      List<CollectionElement> elements = <CollectionElement>[];
-      popTypedList(count)?.forEach((element) {
-        elements.add(element is _EntryInfo
-            ? element.asCollectionElement(ast)
-            : element as CollectionElement);
-      });
+      List<CollectionElement> elements = popCollectionElements(count);
 
       TypeArgumentList typeArguments = pop();
       push(ast.setLiteral2(
@@ -1089,13 +1090,7 @@
     debugEvent("LiteralMap");
 
     if (enableControlFlowCollections || enableSpreadCollections) {
-      List<MapElement> entries = <MapElement>[];
-      popTypedList(count)?.forEach((entry) {
-        entries.add(entry is _EntryInfo
-            ? entry.asMapElement(ast)
-            : entry as MapElement);
-      });
-
+      List<CollectionElement> entries = popCollectionElements(count);
       TypeArgumentList typeArguments = pop();
       push(ast.mapLiteral2(
         constKeyword: constKeyword,
@@ -3153,6 +3148,15 @@
     debugEvent("endElseStatement");
   }
 
+  List<CollectionElement> popCollectionElements(int count) {
+    final elements = new List<CollectionElement>()..length = count;
+    for (int index = count - 1; index >= 0; --index) {
+      var element = pop();
+      elements[index] = element as CollectionElement;
+    }
+    return elements;
+  }
+
   List popList(int n, List list) {
     if (n == 0) return null;
     return stack.popList(n, list, null);
@@ -3270,94 +3274,3 @@
 
   _ConstructorNameWithInvalidTypeArgs(this.name, this.invalidTypeArgs);
 }
-
-abstract class _EntryInfo {
-  CollectionElement asCollectionElement(AstFactory ast);
-  MapElement asMapElement(AstFactory ast);
-}
-
-class _ForControlFlowInfo implements _EntryInfo {
-  final Token awaitToken;
-  final Token forKeyword;
-  final Token leftParenthesis;
-  final ForLoopParts forLoopParts;
-  final Token rightParenthesis;
-  final entry;
-
-  _ForControlFlowInfo(this.awaitToken, this.forKeyword, this.leftParenthesis,
-      this.forLoopParts, this.rightParenthesis, this.entry);
-
-  @override
-  CollectionElement asCollectionElement(AstFactory ast) =>
-      ast.collectionForElement(
-        awaitKeyword: awaitToken,
-        forKeyword: forKeyword,
-        leftParenthesis: leftParenthesis,
-        forLoopParts: forLoopParts,
-        rightParenthesis: rightParenthesis,
-        body: entry is _EntryInfo
-            ? entry.asCollectionElement(ast)
-            : entry as CollectionElement,
-      );
-
-  @override
-  MapElement asMapElement(AstFactory ast) => ast.mapForElement(
-        awaitKeyword: awaitToken,
-        forKeyword: forKeyword,
-        leftParenthesis: leftParenthesis,
-        forLoopParts: forLoopParts,
-        rightParenthesis: rightParenthesis,
-        body:
-            entry is _EntryInfo ? entry.asMapElement(ast) : entry as MapElement,
-      );
-}
-
-class _IfControlFlowInfo implements _EntryInfo {
-  final Token ifToken;
-  final Token leftParenthesis;
-  final Expression conditionExpression;
-  final Token rightParenthesis;
-  final thenElement;
-  final Token elseToken;
-  final elseElement;
-
-  _IfControlFlowInfo(
-      this.ifToken,
-      this.leftParenthesis,
-      this.conditionExpression,
-      this.rightParenthesis,
-      this.thenElement,
-      this.elseToken,
-      this.elseElement);
-
-  @override
-  CollectionElement asCollectionElement(AstFactory ast) =>
-      ast.collectionIfElement(
-        ifKeyword: ifToken,
-        leftParenthesis: leftParenthesis,
-        condition: conditionExpression,
-        rightParenthesis: rightParenthesis,
-        thenElement: thenElement is _EntryInfo
-            ? thenElement.asCollectionElement(ast)
-            : thenElement as CollectionElement,
-        elseKeyword: elseToken,
-        elseElement: elseElement is _EntryInfo
-            ? elseElement.asCollectionElement(ast)
-            : elseElement as CollectionElement,
-      );
-
-  @override
-  MapElement asMapElement(AstFactory ast) => ast.mapIfElement(
-        ifKeyword: ifToken,
-        leftParenthesis: leftParenthesis,
-        condition: conditionExpression,
-        rightParenthesis: rightParenthesis,
-        thenElement: thenElement is _EntryInfo
-            ? thenElement.asMapElement(ast)
-            : thenElement as MapElement,
-        elseKeyword: elseToken,
-        elseElement: elseElement is _EntryInfo
-            ? elseElement.asMapElement(ast)
-            : elseElement as MapElement,
-      );
-}
diff --git a/pkg/analyzer/lib/src/generated/element_resolver.dart b/pkg/analyzer/lib/src/generated/element_resolver.dart
index cc16f64..b86cd55 100644
--- a/pkg/analyzer/lib/src/generated/element_resolver.dart
+++ b/pkg/analyzer/lib/src/generated/element_resolver.dart
@@ -9,7 +9,6 @@
 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/analysis/experiments.dart';
 import 'package:analyzer/src/dart/ast/ast.dart'
     show
         ChildEntities,
@@ -110,11 +109,6 @@
    */
   InterfaceType _typeType;
 
-  /**
-   * The enabled experiments
-   */
-  ExperimentStatus _experimentStatus;
-
   /// Whether constant evaluation errors should be reported during resolution.
   final bool reportConstEvaluationErrors;
 
@@ -130,9 +124,6 @@
         _methodInvocationResolver = new MethodInvocationResolver(_resolver) {
     _dynamicType = _resolver.typeProvider.dynamicType;
     _typeType = _resolver.typeProvider.typeType;
-    _experimentStatus = (_resolver.definingLibrary.context.analysisOptions
-            as AnalysisOptionsImpl)
-        .experimentStatus;
   }
 
   /**
@@ -162,13 +153,6 @@
             null, StaticWarningCode.USE_OF_VOID_RESULT, operator, []);
         return;
       }
-      if (_experimentStatus.non_nullable &&
-          staticType != null &&
-          (staticType as TypeImpl).nullability == Nullability.nullable) {
-        _recordUndefinedToken(null,
-            StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE, operator, []);
-        return;
-      }
     }
 
     if (operatorType != TokenType.AMPERSAND_AMPERSAND_EQ &&
@@ -917,11 +901,6 @@
       } else if (staticType != null && staticType.isVoid) {
         errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
         errorArguments = [];
-      } else if (staticType != null &&
-          _experimentStatus.non_nullable &&
-          (staticType as TypeImpl).nullability == Nullability.nullable) {
-        errorCode = StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE;
-        errorArguments = [];
       } else {
         errorCode = StaticTypeWarningCode.UNDEFINED_OPERATOR;
       }
@@ -1662,11 +1641,6 @@
           if (staticType.isVoid) {
             errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
             arguments = [];
-          } else if ((staticType as TypeImpl).nullability ==
-                  Nullability.nullable &&
-              _experimentStatus.non_nullable) {
-            errorCode = StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE;
-            arguments = [];
           } else {
             errorCode = StaticTypeWarningCode.UNDEFINED_SETTER;
           }
@@ -1682,11 +1656,6 @@
           if (staticType.isVoid) {
             errorCode = StaticWarningCode.USE_OF_VOID_RESULT;
             arguments = [];
-          } else if ((staticType as TypeImpl).nullability ==
-                  Nullability.nullable &&
-              _experimentStatus.non_nullable) {
-            errorCode = StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE;
-            arguments = [];
           } else {
             errorCode = StaticTypeWarningCode.UNDEFINED_GETTER;
           }
@@ -1766,11 +1735,8 @@
    * no match on the given [type], or accessing a [member] on a nullable type.
    */
   bool _shouldReportInvalidMember(DartType type, Element member) {
-    bool unchecked = _experimentStatus.non_nullable &&
-        type != null &&
-        (type as TypeImpl).nullability == Nullability.nullable;
     return type != null &&
-        (member == null || unchecked) &&
+        member == null &&
         !type.isDynamic &&
         !type.isDartCoreNull;
   }
diff --git a/pkg/analyzer/lib/src/generated/error_verifier.dart b/pkg/analyzer/lib/src/generated/error_verifier.dart
index 185f11d..55f766e 100644
--- a/pkg/analyzer/lib/src/generated/error_verifier.dart
+++ b/pkg/analyzer/lib/src/generated/error_verifier.dart
@@ -369,6 +369,7 @@
     } else {
       _checkForInvalidCompoundAssignment(node, lhs, rhs);
       _checkForArgumentTypeNotAssignableForArgument(rhs);
+      _checkForNullableDereference(lhs);
     }
     _checkForAssignmentToFinal(lhs);
     super.visitAssignmentExpression(node);
@@ -394,15 +395,15 @@
       _checkForAssignability(node.rightOperand, _boolType,
           StaticTypeWarningCode.NON_BOOL_OPERAND, [lexeme]);
       _checkForUseOfVoidResult(node.rightOperand);
+      _checkForNullableDereference(node.leftOperand);
       _checkForNullableDereference(node.rightOperand);
+    } else if (type != TokenType.EQ_EQ && type != TokenType.BANG_EQ) {
+      _checkForArgumentTypeNotAssignableForArgument(node.rightOperand);
+      _checkForNullableDereference(node.leftOperand);
     } else {
       _checkForArgumentTypeNotAssignableForArgument(node.rightOperand);
     }
 
-    if (type != TokenType.EQ_EQ && type != TokenType.BANG_EQ) {
-      _checkForNullableDereference(node.leftOperand);
-    }
-
     _checkForUseOfVoidResult(node.leftOperand);
 
     super.visitBinaryExpression(node);
@@ -455,6 +456,11 @@
     }
   }
 
+  void visitCascadeExpression(CascadeExpression node) {
+    _checkForNullableDereference(node.target);
+    super.visitCascadeExpression(node);
+  }
+
   @override
   void visitCatchClause(CatchClause node) {
     _checkDuplicateDefinitionInCatchClause(node);
@@ -695,6 +701,39 @@
   }
 
   @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    DeclaredIdentifier loopVariable = node.loopVariable;
+    if (loopVariable == null) {
+      // Ignore malformed for statements.
+      return;
+    }
+    if (_checkForEachParts(node, loopVariable.identifier)) {
+      if (loopVariable.isConst) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, loopVariable);
+      }
+    }
+    super.visitForEachPartsWithDeclaration(node);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    SimpleIdentifier identifier = node.identifier;
+    if (identifier == null) {
+      // Ignore malformed for statements.
+      return;
+    }
+    if (_checkForEachParts(node, identifier)) {
+      Element variableElement = identifier.staticElement;
+      if (variableElement is VariableElement && variableElement.isConst) {
+        _errorReporter.reportErrorForNode(
+            CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE, identifier);
+      }
+    }
+    super.visitForEachPartsWithIdentifier(node);
+  }
+
+  @override
   void visitForEachStatement(ForEachStatement node) {
     _checkForInIterable(node);
     super.visitForEachStatement(node);
@@ -708,6 +747,25 @@
   }
 
   @override
+  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    if (node.condition != null) {
+      _checkForNonBoolCondition(node.condition);
+    }
+    if (node.variables != null) {
+      _checkDuplicateVariables(node.variables);
+    }
+    super.visitForPartsWithDeclarations(node);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    if (node.condition != null) {
+      _checkForNonBoolCondition(node.condition);
+    }
+    super.visitForPartsWithExpression(node);
+  }
+
+  @override
   void visitForStatement(ForStatement node) {
     if (node.condition != null) {
       _checkForNonBoolCondition(node.condition);
@@ -789,6 +847,7 @@
       _checkTypeArguments(node);
     }
     _checkForImplicitDynamicInvoke(node);
+    _checkForNullableDereference(node.function);
     super.visitFunctionExpressionInvocation(node);
   }
 
@@ -874,6 +933,7 @@
   @override
   void visitIndexExpression(IndexExpression node) {
     _checkForArgumentTypeNotAssignableForArgument(node.index);
+    _checkForNullableDereference(node.target);
     super.visitIndexExpression(node);
   }
 
@@ -935,7 +995,8 @@
               CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST);
         }
       }
-      _checkForExpectedOneListTypeArgument(node, typeArguments);
+      _checkTypeArgumentCount(typeArguments, 1,
+          StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS);
     }
     _checkForImplicitDynamicTypedLiteral(node);
     _checkForListElementTypeNotAssignable(node);
@@ -944,6 +1005,26 @@
   }
 
   @override
+  void visitListLiteral2(ListLiteral2 node) {
+    TypeArgumentList typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      if (node.isConst) {
+        NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+        if (arguments.isNotEmpty) {
+          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
+              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST);
+        }
+      }
+      _checkTypeArgumentCount(typeArguments, 1,
+          StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS);
+    }
+    _checkForImplicitDynamicTypedLiteral(node);
+    _checkForListElementTypeNotAssignable2(node);
+
+    super.visitListLiteral2(node);
+  }
+
+  @override
   void visitMapLiteral(MapLiteral node) {
     TypeArgumentList typeArguments = node.typeArguments;
     if (typeArguments != null) {
@@ -954,7 +1035,8 @@
               CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
         }
       }
-      _checkExpectedTwoMapTypeArguments(typeArguments);
+      _checkTypeArgumentCount(typeArguments, 2,
+          StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS);
     }
     _checkForImplicitDynamicTypedLiteral(node);
     _checkForMapTypeNotAssignable(node);
@@ -963,6 +1045,26 @@
   }
 
   @override
+  void visitMapLiteral2(MapLiteral2 node) {
+    TypeArgumentList typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+      if (arguments.isNotEmpty) {
+        if (node.isConst) {
+          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
+              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP);
+        }
+      }
+      _checkTypeArgumentCount(typeArguments, 2,
+          StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS);
+    }
+    _checkForImplicitDynamicTypedLiteral(node);
+    _checkForMapTypeNotAssignable2(node);
+    _checkForNonConstMapAsExpressionStatement2(node);
+    super.visitMapLiteral2(node);
+  }
+
+  @override
   void visitMethodDeclaration(MethodDeclaration node) {
     ExecutableElement previousFunction = _enclosingFunction;
     try {
@@ -1000,9 +1102,15 @@
       _checkForInstanceAccessToStaticMember(typeReference, methodName);
     } else {
       _checkForUnqualifiedReferenceToNonLocalStaticMember(methodName);
+      _checkForNullableDereference(node.function);
     }
     _checkTypeArguments(node);
     _checkForImplicitDynamicInvoke(node);
+    if (node.operator?.type != TokenType.QUESTION_PERIOD &&
+        methodName.name != 'toString' &&
+        methodName.name != 'noSuchMethod') {
+      _checkForNullableDereference(target);
+    }
     super.visitMethodInvocation(node);
   }
 
@@ -1059,6 +1167,7 @@
   void visitPostfixExpression(PostfixExpression node) {
     _checkForAssignmentToFinal(node.operand);
     _checkForIntNotAssignable(node.operand);
+    _checkForNullableDereference(node.operand);
     super.visitPostfixExpression(node);
   }
 
@@ -1071,6 +1180,12 @@
       _checkForStaticAccessToInstanceMember(typeReference, name);
       _checkForInstanceAccessToStaticMember(typeReference, name);
     }
+    String property = node.identifier.name;
+    if (node.staticElement is ExecutableElement &&
+        property != 'hashCode' &&
+        property != 'runtimeType') {
+      _checkForNullableDereference(node.prefix);
+    }
     super.visitPrefixedIdentifier(node);
   }
 
@@ -1096,6 +1211,11 @@
     SimpleIdentifier propertyName = node.propertyName;
     _checkForStaticAccessToInstanceMember(typeReference, propertyName);
     _checkForInstanceAccessToStaticMember(typeReference, propertyName);
+    if (node.operator?.type != TokenType.QUESTION_PERIOD &&
+        propertyName.name != 'hashCode' &&
+        propertyName.name != 'runtimeType') {
+      _checkForNullableDereference(node.target);
+    }
     super.visitPropertyAccess(node);
   }
 
@@ -1138,7 +1258,8 @@
               CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET);
         }
       }
-      _checkForExpectedOneSetTypeArgument(node, typeArguments);
+      _checkTypeArgumentCount(typeArguments, 1,
+          StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS);
     }
     _checkForImplicitDynamicTypedLiteral(node);
     _checkForSetElementTypeNotAssignable(node);
@@ -1147,6 +1268,26 @@
   }
 
   @override
+  void visitSetLiteral2(SetLiteral2 node) {
+    TypeArgumentList typeArguments = node.typeArguments;
+    if (typeArguments != null) {
+      if (node.isConst) {
+        NodeList<TypeAnnotation> arguments = typeArguments.arguments;
+        if (arguments.isNotEmpty) {
+          _checkForInvalidTypeArgumentInConstTypedLiteral(arguments,
+              CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET);
+        }
+      }
+      _checkTypeArgumentCount(typeArguments, 1,
+          StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS);
+    }
+    _checkForImplicitDynamicTypedLiteral(node);
+    _checkForSetElementTypeNotAssignable2(node);
+
+    super.visitSetLiteral2(node);
+  }
+
+  @override
   void visitSimpleFormalParameter(SimpleFormalParameter node) {
     _checkForConstFormalParameter(node);
     _checkForPrivateOptionalParameter(node);
@@ -1716,22 +1857,6 @@
   }
 
   /**
-   * Verify that the given list of [typeArguments] contains exactly two
-   * elements.
-   *
-   * See [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS].
-   */
-  void _checkExpectedTwoMapTypeArguments(TypeArgumentList typeArguments) {
-    int num = typeArguments.arguments.length;
-    if (num != 2) {
-      _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS,
-          typeArguments,
-          [num]);
-    }
-  }
-
-  /**
    * Check that return statements without expressions are not in a generative
    * constructor and the return type is not assignable to `null`; that is, we
    * don't have `return;` if the enclosing method has a non-void containing
@@ -2433,6 +2558,34 @@
   }
 
   /**
+   * Verify that the given [element] can be assigned to the [elementType] of the
+   * enclosing list or set literal. Report an error with the given [errorCode]
+   * if not.
+   *
+   * This method corresponds to
+   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
+   */
+  void _checkForCollectionElementTypeNotAssignableWithElementType(
+      CollectionElement element, DartType elementType, ErrorCode errorCode) {
+    if (element is ForElement) {
+      _checkForCollectionElementTypeNotAssignableWithElementType(
+          element.body, elementType, errorCode);
+    } else if (element is IfElement) {
+      _checkForCollectionElementTypeNotAssignableWithElementType(
+          element.thenElement, elementType, errorCode);
+      _checkForCollectionElementTypeNotAssignableWithElementType(
+          element.elseElement, elementType, errorCode);
+    } else if (element is Expression) {
+      _checkForArgumentTypeNotAssignable(
+          element, elementType, getStaticType(element), errorCode);
+    } else if (element is SpreadElement) {
+      Expression expression = element.expression;
+      _checkForArgumentTypeNotAssignable(
+          expression, elementType, getStaticType(expression), errorCode);
+    }
+  }
+
+  /**
    * Verify that the [_enclosingClass] does not have a method and getter pair
    * with the same name on, via inheritance.
    *
@@ -2902,39 +3055,67 @@
   }
 
   /**
-   * Verify that if the given list [literal] has type arguments then there is
-   * exactly one. The [typeArguments] are the type arguments.
-   *
-   * See [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS].
+   * Return `true` if the caller should continue checking the rest of the
+   * information in the for-each part.
    */
-  void _checkForExpectedOneListTypeArgument(
-      ListLiteral literal, TypeArgumentList typeArguments) {
-    // check number of type arguments
-    int num = typeArguments.arguments.length;
-    if (num != 1) {
-      _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS,
-          typeArguments,
-          [num]);
+  bool _checkForEachParts(ForEachParts node, SimpleIdentifier variable) {
+    if (_checkForNullableDereference(node.iterable)) {
+      return false;
     }
-  }
 
-  /**
-   * Verify that if the given set [literal] has type arguments then there is
-   * exactly one. The [typeArguments] are the type arguments.
-   *
-   * See [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS].
-   */
-  void _checkForExpectedOneSetTypeArgument(
-      SetLiteral literal, TypeArgumentList typeArguments) {
-    // check number of type arguments
-    int count = typeArguments.arguments.length;
-    if (count != 1) {
-      _errorReporter.reportErrorForNode(
-          StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS,
-          typeArguments,
-          [count]);
+    if (_checkForUseOfVoidResult(node.iterable)) {
+      return false;
     }
+
+    DartType iterableType = getStaticType(node.iterable);
+    if (iterableType.isDynamic) {
+      return false;
+    }
+
+    // The type of the loop variable.
+    DartType variableType = getStaticType(variable);
+
+    AstNode parent = node.parent;
+    Token awaitKeyword;
+    if (parent is ForStatement2) {
+      awaitKeyword = parent.awaitKeyword;
+    } else if (parent is ForElement) {
+      awaitKeyword = parent.awaitKeyword;
+    }
+    DartType loopType = awaitKeyword != null
+        ? _typeProvider.streamType
+        : _typeProvider.iterableType;
+
+    // Use an explicit string instead of [loopType] to remove the "<E>".
+    String loopTypeName = awaitKeyword != null ? "Stream" : "Iterable";
+
+    // The object being iterated has to implement Iterable<T> for some T that
+    // is assignable to the variable's type.
+    // TODO(rnystrom): Move this into mostSpecificTypeArgument()?
+    iterableType = iterableType.resolveToBound(_typeProvider.objectType);
+    DartType bestIterableType =
+        _typeSystem.mostSpecificTypeArgument(iterableType, loopType);
+
+    // Allow it to be a supertype of Iterable<T> (basically just Object) and do
+    // an implicit downcast to Iterable<dynamic>.
+    if (bestIterableType == null) {
+      if (_typeSystem.isSubtypeOf(loopType, iterableType)) {
+        bestIterableType = DynamicTypeImpl.instance;
+      }
+    }
+
+    if (bestIterableType == null) {
+      _errorReporter.reportTypeErrorForNode(
+          StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE,
+          node.iterable,
+          [iterableType, loopTypeName]);
+    } else if (!_typeSystem.isAssignableTo(bestIterableType, variableType)) {
+      _errorReporter.reportTypeErrorForNode(
+          StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE,
+          node.iterable,
+          [iterableType, loopTypeName, variableType]);
+    }
+    return true;
   }
 
   /**
@@ -3442,6 +3623,7 @@
     DartType type = node.staticType;
     // It's an error if either the key or value was inferred as dynamic.
     if (type is InterfaceType && type.typeArguments.any((t) => t.isDynamic)) {
+      // TODO(brianwilkerson) Add StrongModeCode.IMPLICIT_DYNAMIC_SET_LITERAL
       ErrorCode errorCode = node is ListLiteral
           ? StrongModeCode.IMPLICIT_DYNAMIC_LIST_LITERAL
           : StrongModeCode.IMPLICIT_DYNAMIC_MAP_LITERAL;
@@ -3838,8 +4020,8 @@
   }
 
   /**
-   * Verify that the elements given list [literal] are subtypes of the list's
-   * static type.
+   * Verify that the elements of the given list [literal] are subtypes of the
+   * list's static type.
    *
    * See [CompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE], and
    * [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE].
@@ -3874,6 +4056,92 @@
   }
 
   /**
+   * Verify that the elements of the given list [literal] are subtypes of the
+   * list's static type.
+   */
+  void _checkForListElementTypeNotAssignable2(ListLiteral2 literal) {
+    // Determine the list's element type. We base this on the static type and
+    // not the literal's type arguments because in strong mode, the type
+    // arguments may be inferred.
+    DartType listType = literal.staticType;
+    assert(listType is InterfaceTypeImpl);
+
+    List<DartType> typeArguments =
+        (listType as InterfaceTypeImpl).typeArguments;
+    assert(typeArguments.length == 1);
+
+    DartType listElementType = typeArguments[0];
+
+    // Check every list element.
+    bool isConst = literal.isConst;
+    for (CollectionElement element in literal.elements) {
+      if (isConst) {
+        // TODO(paulberry): this error should be based on the actual type of the
+        // list element, not the static type.  See dartbug.com/21119.
+        _checkForCollectionElementTypeNotAssignableWithElementType(
+            element,
+            listElementType,
+            CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
+      } else {
+        _checkForCollectionElementTypeNotAssignableWithElementType(
+            element,
+            listElementType,
+            StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE);
+      }
+    }
+  }
+
+  /**
+   * Verify that the given [element] can be assigned to the [elementType] of the
+   * enclosing list or set literal. Report an error with the given [errorCode]
+   * if not.
+   *
+   * This method corresponds to
+   * [BestPracticesVerifier.checkForArgumentTypeNotAssignableWithExpectedTypes].
+   */
+  void _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+      CollectionElement element,
+      DartType keyType,
+      DartType valueType,
+      ErrorCode keyErrorCode,
+      ErrorCode valueErrorCode) {
+    if (element is ForElement) {
+      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+          element.body, keyType, valueType, keyErrorCode, valueErrorCode);
+    } else if (element is IfElement) {
+      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+          element.thenElement,
+          keyType,
+          valueType,
+          keyErrorCode,
+          valueErrorCode);
+      _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+          element.elseElement,
+          keyType,
+          valueType,
+          keyErrorCode,
+          valueErrorCode);
+    } else if (element is MapLiteralEntry) {
+      _checkForArgumentTypeNotAssignableWithExpectedTypes(
+          element.key, keyType, keyErrorCode);
+      _checkForArgumentTypeNotAssignableWithExpectedTypes(
+          element.value, valueType, valueErrorCode);
+    } else if (element is SpreadElement) {
+      Expression expression = element.expression;
+      DartType expressionType = getStaticType(expression);
+      if (expressionType is ParameterizedType) {
+        List<DartType> typeArguments = expressionType.typeArguments;
+        if (typeArguments.length == 2) {
+          _checkForArgumentTypeNotAssignable(
+              expression, keyType, typeArguments[0], keyErrorCode);
+          _checkForArgumentTypeNotAssignable(
+              expression, valueType, typeArguments[1], valueErrorCode);
+        }
+      }
+    }
+  }
+
+  /**
    * Verify that the key/value of entries of the given map [literal] are
    * subtypes of the map's static type.
    *
@@ -3920,6 +4188,55 @@
   }
 
   /**
+   * Verify that the key/value of entries of the given map [literal] are
+   * subtypes of the map's static type.
+   *
+   * See [CompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE],
+   * [CompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE],
+   * [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE], and
+   * [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE].
+   */
+  void _checkForMapTypeNotAssignable2(MapLiteral2 literal) {
+    // Determine the map's key and value types. We base this on the static type
+    // and not the literal's type arguments because in strong mode, the type
+    // arguments may be inferred.
+    DartType mapType = literal.staticType;
+    if (mapType == null) {
+      // This is known to happen when the literal is the default value in an
+      // optional parameter in a generic function type alias.
+      return;
+    }
+    assert(mapType is InterfaceTypeImpl);
+
+    List<DartType> typeArguments = (mapType as InterfaceTypeImpl).typeArguments;
+    assert(typeArguments.length == 2);
+    DartType keyType = typeArguments[0];
+    DartType valueType = typeArguments[1];
+
+    bool isConst = literal.isConst;
+    NodeList<CollectionElement> entries = literal.entries;
+    for (CollectionElement entry in entries) {
+      if (isConst) {
+        // TODO(paulberry): this error should be based on the actual type of the
+        // list element, not the static type.  See dartbug.com/21119.
+        _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+            entry,
+            keyType,
+            valueType,
+            CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+            CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
+      } else {
+        _checkForMapElementTypeNotAssignableWithKeyOrValueType(
+            entry,
+            keyType,
+            valueType,
+            StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE,
+            StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE);
+      }
+    }
+  }
+
+  /**
    * Verify that the [_enclosingClass] does not define members with the same name
    * as the enclosing class.
    *
@@ -4509,6 +4826,37 @@
   }
 
   /**
+   * Verify the given map [literal] either:
+   * * has `const modifier`
+   * * has explicit type arguments
+   * * is not start of the statement
+   *
+   * See [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT].
+   */
+  void _checkForNonConstMapAsExpressionStatement2(MapLiteral2 literal) {
+    // "const"
+    if (literal.constKeyword != null) {
+      return;
+    }
+    // has type arguments
+    if (literal.typeArguments != null) {
+      return;
+    }
+    // prepare statement
+    Statement statement = literal.thisOrAncestorOfType<ExpressionStatement>();
+    if (statement == null) {
+      return;
+    }
+    // OK, statement does not start with map
+    if (!identical(statement.beginToken, literal.beginToken)) {
+      return;
+    }
+
+    _errorReporter.reportErrorForNode(
+        CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT, literal);
+  }
+
+  /**
    * Verify that the given method [declaration] of operator `[]=`, has `void`
    * return type.
    *
@@ -4557,6 +4905,7 @@
   bool _checkForNullableDereference(Expression expression) {
     if (expression == null ||
         !_options.experimentStatus.non_nullable ||
+        expression.staticType == null ||
         (expression.staticType as TypeImpl).nullability !=
             Nullability.nullable) {
       return false;
@@ -5054,6 +5403,42 @@
   }
 
   /**
+   * Verify that the elements in the given set [literal] are subtypes of the
+   * set's static type.
+   *
+   * See [CompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE], and
+   * [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE].
+   */
+  void _checkForSetElementTypeNotAssignable2(SetLiteral2 literal) {
+    // Determine the list's element type. We base this on the static type and
+    // not the literal's type arguments because in strong mode, the type
+    // arguments may be inferred.
+    DartType setType = literal.staticType;
+    assert(setType is InterfaceTypeImpl);
+
+    List<DartType> typeArguments = (setType as InterfaceTypeImpl).typeArguments;
+    assert(typeArguments.length == 1);
+
+    DartType setElementType = typeArguments[0];
+
+    // Check every list element.
+    bool isConst = literal.isConst;
+    for (CollectionElement element in literal.elements) {
+      if (isConst) {
+        // TODO(paulberry): this error should be based on the actual type of the
+        // element, not the static type.  See dartbug.com/21119.
+        _checkForCollectionElementTypeNotAssignableWithElementType(
+            element,
+            setElementType,
+            CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
+      } else {
+        _checkForCollectionElementTypeNotAssignableWithElementType(element,
+            setElementType, StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE);
+      }
+    }
+  }
+
+  /**
    * Check the given [typeReference] and that the [name] is not a reference to
    * an instance member.
    *
@@ -5683,6 +6068,20 @@
   }
 
   /**
+   * Verify that the given list of [typeArguments] contains exactly the
+   * [expectedCount] of elements, reporting an error with the given [errorCode]
+   * if not.
+   */
+  void _checkTypeArgumentCount(
+      TypeArgumentList typeArguments, int expectedCount, ErrorCode errorCode) {
+    int actualCount = typeArguments.arguments.length;
+    if (actualCount != expectedCount) {
+      _errorReporter
+          .reportErrorForNode(errorCode, typeArguments, [actualCount]);
+    }
+  }
+
+  /**
    * Verify that the given [typeArguments] are all within their bounds, as
    * defined by the given [element].
    *
diff --git a/pkg/analyzer/lib/src/generated/resolver.dart b/pkg/analyzer/lib/src/generated/resolver.dart
index e4b1515..e10c1fd 100644
--- a/pkg/analyzer/lib/src/generated/resolver.dart
+++ b/pkg/analyzer/lib/src/generated/resolver.dart
@@ -24,6 +24,7 @@
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
 import 'package:analyzer/src/dart/element/member.dart' show ConstructorMember;
 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/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
@@ -38,6 +39,7 @@
 import 'package:path/path.dart' as path;
 
 export 'package:analyzer/src/dart/constant/constant_verifier.dart';
+export 'package:analyzer/src/dart/resolver/exit_detector.dart';
 export 'package:analyzer/src/dart/resolver/inheritance_manager.dart';
 export 'package:analyzer/src/dart/resolver/scope.dart';
 export 'package:analyzer/src/generated/type_system.dart';
@@ -299,6 +301,7 @@
     TypeSystem typeSystem,
     ResourceProvider resourceProvider,
     DeclaredVariables declaredVariables,
+    AnalysisOptions analysisOptions,
   })  : _nullType = typeProvider.nullType,
         _futureNullType = typeProvider.futureNullType,
         _typeSystem = typeSystem ?? new Dart2TypeSystem(typeProvider),
@@ -311,8 +314,13 @@
     Workspace workspace =
         ContextBuilder.createWorkspace(resourceProvider, libraryPath, builder);
     _workspacePackage = workspace.findPackageFor(libraryPath);
-    _linterContext = LinterContextImpl(null /* allUnits */,
-        null /* currentUnit */, declaredVariables, typeProvider, _typeSystem);
+    _linterContext = LinterContextImpl(
+        null /* allUnits */,
+        null /* currentUnit */,
+        declaredVariables,
+        typeProvider,
+        _typeSystem,
+        analysisOptions);
   }
 
   @override
@@ -343,7 +351,39 @@
         _errorReporter.reportErrorForNode(
             HintCode.INVALID_SEALED_ANNOTATION, node, [node.element.name]);
       }
+    } else if (element?.isVisibleForTemplate == true ||
+        element?.isVisibleForTesting == true) {
+      if (parent is Declaration) {
+        reportInvalidAnnotation(Element declaredElement) {
+          _errorReporter.reportErrorForNode(
+              HintCode.INVALID_VISIBILITY_ANNOTATION,
+              node,
+              [declaredElement.name, node.name.name]);
+        }
+
+        if (parent is TopLevelVariableDeclaration) {
+          for (VariableDeclaration variable in parent.variables.variables) {
+            if (Identifier.isPrivateName(variable.declaredElement.name)) {
+              reportInvalidAnnotation(variable.declaredElement);
+            }
+          }
+        } else if (parent is FieldDeclaration) {
+          for (VariableDeclaration variable in parent.fields.variables) {
+            if (Identifier.isPrivateName(variable.declaredElement.name)) {
+              reportInvalidAnnotation(variable.declaredElement);
+            }
+          }
+        } else if (parent.declaredElement != null &&
+            Identifier.isPrivateName(parent.declaredElement.name)) {
+          reportInvalidAnnotation(parent.declaredElement);
+        }
+      } else {
+        // Something other than a declaration was annotated. Whatever this is,
+        // it probably warrants a Hint, but this has not been specified on
+        // visibleForTemplate or visibleForTesting, so leave it alone for now.
+      }
     }
+
     super.visitAnnotation(node);
   }
 
@@ -702,6 +742,15 @@
       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) &&
@@ -724,7 +773,7 @@
       }
       LibraryElement library =
           element is LibraryElement ? element : element.library;
-      HintCode hintCode = _workspacePackage.contains(library.source.fullName)
+      HintCode hintCode = isLibraryInWorkspacePackage(library)
           ? HintCode.DEPRECATED_MEMBER_USE_FROM_SAME_PACKAGE
           : HintCode.DEPRECATED_MEMBER_USE;
       _errorReporter.reportErrorForNode(hintCode, node, [displayName]);
@@ -1541,6 +1590,34 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    Expression conditionExpression = node.condition;
+    conditionExpression?.accept(this);
+    if (!_isDebugConstant(conditionExpression)) {
+      EvaluationResultImpl result =
+          _getConstantBooleanValue(conditionExpression);
+      if (result != null) {
+        if (result.value.toBoolValue() == true) {
+          // Report error on else block: if(true) {} else {!}
+          CollectionElement elseElement = node.elseElement;
+          if (elseElement != null) {
+            _errorReporter.reportErrorForNode(HintCode.DEAD_CODE, elseElement);
+            node.thenElement?.accept(this);
+            return;
+          }
+        } else {
+          // Report error on if block: if (false) {!} else {}
+          _errorReporter.reportErrorForNode(
+              HintCode.DEAD_CODE, node.thenElement);
+          node.elseElement?.accept(this);
+          return;
+        }
+      }
+    }
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     Expression conditionExpression = node.condition;
     conditionExpression?.accept(this);
@@ -2392,594 +2469,6 @@
   }
 }
 
-/// Instances of the class `ExitDetector` determine whether the visited AST node
-/// is guaranteed to terminate by executing a `return` statement, `throw`
-/// expression, `rethrow` expression, or simple infinite loop such as
-/// `while(true)`.
-class ExitDetector extends GeneralizingAstVisitor<bool> {
-  /// Set to `true` when a `break` is encountered, and reset to `false` when a
-  /// `do`, `while`, `for` or `switch` block is entered.
-  bool _enclosingBlockContainsBreak = false;
-
-  /// Set to `true` when a `continue` is encountered, and reset to `false` when
-  /// a `do`, `while`, `for` or `switch` block is entered.
-  bool _enclosingBlockContainsContinue = false;
-
-  /// Add node when a labelled `break` is encountered.
-  Set<AstNode> _enclosingBlockBreaksLabel = new Set<AstNode>();
-
-  @override
-  bool visitArgumentList(ArgumentList node) =>
-      _visitExpressions(node.arguments);
-
-  @override
-  bool visitAsExpression(AsExpression node) => _nodeExits(node.expression);
-
-  @override
-  bool visitAssertInitializer(AssertInitializer node) => false;
-
-  @override
-  bool visitAssertStatement(AssertStatement node) => false;
-
-  @override
-  bool visitAssignmentExpression(AssignmentExpression node) {
-    Expression leftHandSide = node.leftHandSide;
-    if (_nodeExits(leftHandSide)) {
-      return true;
-    }
-    TokenType operatorType = node.operator.type;
-    if (operatorType == TokenType.AMPERSAND_AMPERSAND_EQ ||
-        operatorType == TokenType.BAR_BAR_EQ ||
-        operatorType == TokenType.QUESTION_QUESTION_EQ) {
-      return false;
-    }
-    if (leftHandSide is PropertyAccess &&
-        leftHandSide.operator.type == TokenType.QUESTION_PERIOD) {
-      return false;
-    }
-    return _nodeExits(node.rightHandSide);
-  }
-
-  @override
-  bool visitAwaitExpression(AwaitExpression node) =>
-      _nodeExits(node.expression);
-
-  @override
-  bool visitBinaryExpression(BinaryExpression node) {
-    Expression lhsExpression = node.leftOperand;
-    Expression rhsExpression = node.rightOperand;
-    TokenType operatorType = node.operator.type;
-    // If the operator is ||, then only consider the RHS of the binary
-    // expression if the left hand side is the false literal.
-    // TODO(jwren) Do we want to take constant expressions into account,
-    // evaluate if(false) {} differently than if(<condition>), when <condition>
-    // evaluates to a constant false value?
-    if (operatorType == TokenType.BAR_BAR) {
-      if (lhsExpression is BooleanLiteral) {
-        if (!lhsExpression.value) {
-          return _nodeExits(rhsExpression);
-        }
-      }
-      return _nodeExits(lhsExpression);
-    }
-    // If the operator is &&, then only consider the RHS of the binary
-    // expression if the left hand side is the true literal.
-    if (operatorType == TokenType.AMPERSAND_AMPERSAND) {
-      if (lhsExpression is BooleanLiteral) {
-        if (lhsExpression.value) {
-          return _nodeExits(rhsExpression);
-        }
-      }
-      return _nodeExits(lhsExpression);
-    }
-    // If the operator is ??, then don't consider the RHS of the binary
-    // expression.
-    if (operatorType == TokenType.QUESTION_QUESTION) {
-      return _nodeExits(lhsExpression);
-    }
-    return _nodeExits(lhsExpression) || _nodeExits(rhsExpression);
-  }
-
-  @override
-  bool visitBlock(Block node) => _visitStatements(node.statements);
-
-  @override
-  bool visitBlockFunctionBody(BlockFunctionBody node) => _nodeExits(node.block);
-
-  @override
-  bool visitBreakStatement(BreakStatement node) {
-    _enclosingBlockContainsBreak = true;
-    if (node.label != null) {
-      _enclosingBlockBreaksLabel.add(node.target);
-    }
-    return false;
-  }
-
-  @override
-  bool visitCascadeExpression(CascadeExpression node) =>
-      _nodeExits(node.target) || _visitExpressions(node.cascadeSections);
-
-  @override
-  bool visitConditionalExpression(ConditionalExpression node) {
-    Expression conditionExpression = node.condition;
-    Expression thenStatement = node.thenExpression;
-    Expression elseStatement = node.elseExpression;
-    // TODO(jwren) Do we want to take constant expressions into account,
-    // evaluate if(false) {} differently than if(<condition>), when <condition>
-    // evaluates to a constant false value?
-    if (_nodeExits(conditionExpression)) {
-      return true;
-    }
-    if (thenStatement == null || elseStatement == null) {
-      return false;
-    }
-    return thenStatement.accept(this) && elseStatement.accept(this);
-  }
-
-  @override
-  bool visitContinueStatement(ContinueStatement node) {
-    _enclosingBlockContainsContinue = true;
-    return false;
-  }
-
-  @override
-  bool visitDoStatement(DoStatement node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    bool outerContinueValue = _enclosingBlockContainsContinue;
-    _enclosingBlockContainsBreak = false;
-    _enclosingBlockContainsContinue = false;
-    try {
-      bool bodyExits = _nodeExits(node.body);
-      bool containsBreakOrContinue =
-          _enclosingBlockContainsBreak || _enclosingBlockContainsContinue;
-      // Even if we determine that the body "exits", there might be break or
-      // continue statements that actually mean it _doesn't_ always exit.
-      if (bodyExits && !containsBreakOrContinue) {
-        return true;
-      }
-      Expression conditionExpression = node.condition;
-      if (_nodeExits(conditionExpression)) {
-        return true;
-      }
-      // TODO(jwren) Do we want to take all constant expressions into account?
-      if (conditionExpression is BooleanLiteral) {
-        // If do {} while (true), and the body doesn't break, then return true.
-        if (conditionExpression.value && !_enclosingBlockContainsBreak) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-      _enclosingBlockContainsContinue = outerContinueValue;
-    }
-  }
-
-  @override
-  bool visitEmptyStatement(EmptyStatement node) => false;
-
-  @override
-  bool visitExpressionStatement(ExpressionStatement node) =>
-      _nodeExits(node.expression);
-
-  @override
-  bool visitForEachStatement(ForEachStatement node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    _enclosingBlockContainsBreak = false;
-    try {
-      bool iterableExits = _nodeExits(node.iterable);
-      // Discard whether the for-each body exits; since the for-each iterable
-      // may be empty, execution may never enter the body, so it doesn't matter
-      // if it exits or not.  We still must visit the body, to accurately
-      // manage `_enclosingBlockBreaksLabel`.
-      _nodeExits(node.body);
-      return iterableExits;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-    }
-  }
-
-  @override
-  bool visitForStatement(ForStatement node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    _enclosingBlockContainsBreak = false;
-    try {
-      if (node.variables != null &&
-          _visitVariableDeclarations(node.variables.variables)) {
-        return true;
-      }
-      if (node.initialization != null && _nodeExits(node.initialization)) {
-        return true;
-      }
-      Expression conditionExpression = node.condition;
-      if (conditionExpression != null && _nodeExits(conditionExpression)) {
-        return true;
-      }
-      if (_visitExpressions(node.updaters)) {
-        return true;
-      }
-      bool blockReturns = _nodeExits(node.body);
-      // TODO(jwren) Do we want to take all constant expressions into account?
-      // If for(; true; ) (or for(;;)), and the body doesn't return or the body
-      // doesn't have a break, then return true.
-      bool implicitOrExplictTrue = conditionExpression == null ||
-          (conditionExpression is BooleanLiteral && conditionExpression.value);
-      if (implicitOrExplictTrue) {
-        if (blockReturns || !_enclosingBlockContainsBreak) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-    }
-  }
-
-  @override
-  bool visitForStatement2(ForStatement2 node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    _enclosingBlockContainsBreak = false;
-    ForLoopParts parts = node.forLoopParts;
-    try {
-      if (parts is ForEachParts) {
-        bool iterableExits = _nodeExits(parts.iterable);
-        // Discard whether the for-each body exits; since the for-each iterable
-        // may be empty, execution may never enter the body, so it doesn't matter
-        // if it exits or not.  We still must visit the body, to accurately
-        // manage `_enclosingBlockBreaksLabel`.
-        _nodeExits(node.body);
-        return iterableExits;
-      }
-      VariableDeclarationList variables;
-      Expression initialization;
-      Expression condition;
-      NodeList<Expression> updaters;
-      if (parts is ForPartsWithDeclarations) {
-        variables = parts.variables;
-        condition = parts.condition;
-        updaters = parts.updaters;
-      } else if (parts is ForPartsWithExpression) {
-        initialization = parts.initialization;
-        condition = parts.condition;
-        updaters = parts.updaters;
-      }
-      if (variables != null &&
-          _visitVariableDeclarations(variables.variables)) {
-        return true;
-      }
-      if (initialization != null && _nodeExits(initialization)) {
-        return true;
-      }
-      if (condition != null && _nodeExits(condition)) {
-        return true;
-      }
-      if (_visitExpressions(updaters)) {
-        return true;
-      }
-      bool blockReturns = _nodeExits(node.body);
-      // TODO(jwren) Do we want to take all constant expressions into account?
-      // If for(; true; ) (or for(;;)), and the body doesn't return or the body
-      // doesn't have a break, then return true.
-      bool implicitOrExplictTrue =
-          condition == null || (condition is BooleanLiteral && condition.value);
-      if (implicitOrExplictTrue) {
-        if (blockReturns || !_enclosingBlockContainsBreak) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-    }
-  }
-
-  @override
-  bool visitFunctionDeclarationStatement(FunctionDeclarationStatement node) =>
-      false;
-
-  @override
-  bool visitFunctionExpression(FunctionExpression node) => false;
-
-  @override
-  bool visitFunctionExpressionInvocation(FunctionExpressionInvocation node) {
-    if (_nodeExits(node.function)) {
-      return true;
-    }
-    return node.argumentList.accept(this);
-  }
-
-  @override
-  bool visitGenericFunctionType(GenericFunctionType node) => false;
-
-  @override
-  bool visitIdentifier(Identifier node) => false;
-
-  @override
-  bool visitIfStatement(IfStatement node) {
-    Expression conditionExpression = node.condition;
-    Statement thenStatement = node.thenStatement;
-    Statement elseStatement = node.elseStatement;
-    if (_nodeExits(conditionExpression)) {
-      return true;
-    }
-    // TODO(jwren) Do we want to take all constant expressions into account?
-    if (conditionExpression is BooleanLiteral) {
-      if (conditionExpression.value) {
-        // if (true) ...
-        return _nodeExits(thenStatement);
-      } else if (elseStatement != null) {
-        // if (false) ...
-        return _nodeExits(elseStatement);
-      }
-    }
-    bool thenExits = _nodeExits(thenStatement);
-    bool elseExits = _nodeExits(elseStatement);
-    if (thenStatement == null || elseStatement == null) {
-      return false;
-    }
-    return thenExits && elseExits;
-  }
-
-  @override
-  bool visitIndexExpression(IndexExpression node) {
-    Expression target = node.realTarget;
-    if (_nodeExits(target)) {
-      return true;
-    }
-    if (_nodeExits(node.index)) {
-      return true;
-    }
-    return false;
-  }
-
-  @override
-  bool visitInstanceCreationExpression(InstanceCreationExpression node) =>
-      _nodeExits(node.argumentList);
-
-  @override
-  bool visitIsExpression(IsExpression node) => node.expression.accept(this);
-
-  @override
-  bool visitLabel(Label node) => false;
-
-  @override
-  bool visitLabeledStatement(LabeledStatement node) {
-    try {
-      bool statementExits = _nodeExits(node.statement);
-      bool neverBrokeFromLabel =
-          !_enclosingBlockBreaksLabel.contains(node.statement);
-      return statementExits && neverBrokeFromLabel;
-    } finally {
-      _enclosingBlockBreaksLabel.remove(node.statement);
-    }
-  }
-
-  @override
-  bool visitLiteral(Literal node) => false;
-
-  @override
-  bool visitMethodInvocation(MethodInvocation node) {
-    Expression target = node.realTarget;
-    if (target != null) {
-      if (target.accept(this)) {
-        return true;
-      }
-      if (node.operator.type == TokenType.QUESTION_PERIOD) {
-        return false;
-      }
-    }
-    Element element = node.methodName.staticElement;
-    if (element != null && element.hasAlwaysThrows) {
-      return true;
-    }
-    return _nodeExits(node.argumentList);
-  }
-
-  @override
-  bool visitNamedExpression(NamedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  bool visitParenthesizedExpression(ParenthesizedExpression node) =>
-      node.expression.accept(this);
-
-  @override
-  bool visitPostfixExpression(PostfixExpression node) => false;
-
-  @override
-  bool visitPrefixExpression(PrefixExpression node) => false;
-
-  @override
-  bool visitPropertyAccess(PropertyAccess node) {
-    Expression target = node.realTarget;
-    if (target != null && target.accept(this)) {
-      return true;
-    }
-    return false;
-  }
-
-  @override
-  bool visitRethrowExpression(RethrowExpression node) => true;
-
-  @override
-  bool visitReturnStatement(ReturnStatement node) => true;
-
-  @override
-  bool visitSuperExpression(SuperExpression node) => false;
-
-  @override
-  bool visitSwitchCase(SwitchCase node) => _visitStatements(node.statements);
-
-  @override
-  bool visitSwitchDefault(SwitchDefault node) =>
-      _visitStatements(node.statements);
-
-  @override
-  bool visitSwitchStatement(SwitchStatement node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    _enclosingBlockContainsBreak = false;
-    try {
-      bool hasDefault = false;
-      bool hasNonExitingCase = false;
-      List<SwitchMember> members = node.members;
-      for (int i = 0; i < members.length; i++) {
-        SwitchMember switchMember = members[i];
-        if (switchMember is SwitchDefault) {
-          hasDefault = true;
-          // If this is the last member and there are no statements, then it
-          // does not exit.
-          if (switchMember.statements.isEmpty && i + 1 == members.length) {
-            hasNonExitingCase = true;
-            continue;
-          }
-        }
-        // For switch members with no statements, don't visit the children.
-        // Otherwise, if there children statements don't exit, mark this as a
-        // non-exiting case.
-        if (!switchMember.statements.isEmpty && !switchMember.accept(this)) {
-          hasNonExitingCase = true;
-        }
-      }
-      if (hasNonExitingCase) {
-        return false;
-      }
-      // As all cases exit, return whether that list includes `default`.
-      return hasDefault;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-    }
-  }
-
-  @override
-  bool visitThisExpression(ThisExpression node) => false;
-
-  @override
-  bool visitThrowExpression(ThrowExpression node) => true;
-
-  @override
-  bool visitTryStatement(TryStatement node) {
-    if (_nodeExits(node.finallyBlock)) {
-      return true;
-    }
-    if (!_nodeExits(node.body)) {
-      return false;
-    }
-    for (CatchClause c in node.catchClauses) {
-      if (!_nodeExits(c.body)) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  @override
-  bool visitTypeName(TypeName node) => false;
-
-  @override
-  bool visitVariableDeclaration(VariableDeclaration node) {
-    Expression initializer = node.initializer;
-    if (initializer != null) {
-      return initializer.accept(this);
-    }
-    return false;
-  }
-
-  @override
-  bool visitVariableDeclarationList(VariableDeclarationList node) =>
-      _visitVariableDeclarations(node.variables);
-
-  @override
-  bool visitVariableDeclarationStatement(VariableDeclarationStatement node) {
-    NodeList<VariableDeclaration> variables = node.variables.variables;
-    for (int i = 0; i < variables.length; i++) {
-      if (variables[i].accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  @override
-  bool visitWhileStatement(WhileStatement node) {
-    bool outerBreakValue = _enclosingBlockContainsBreak;
-    _enclosingBlockContainsBreak = false;
-    try {
-      Expression conditionExpression = node.condition;
-      if (conditionExpression.accept(this)) {
-        return true;
-      }
-      node.body.accept(this);
-      // TODO(jwren) Do we want to take all constant expressions into account?
-      if (conditionExpression is BooleanLiteral) {
-        // If while(true), and the body doesn't have a break, then return true.
-        // The body might be found to exit, but if there are any break
-        // statements, then it is a faulty finding. In other words:
-        //
-        // * If the body exits, and does not contain a break statement, then
-        //   it exits.
-        // * If the body does not exit, and does not contain a break statement,
-        //   then it loops infinitely (also an exit).
-        //
-        // As both conditions forbid any break statements to be found, the logic
-        // just boils down to checking [_enclosingBlockContainsBreak].
-        if (conditionExpression.value && !_enclosingBlockContainsBreak) {
-          return true;
-        }
-      }
-      return false;
-    } finally {
-      _enclosingBlockContainsBreak = outerBreakValue;
-    }
-  }
-
-  @override
-  bool visitYieldStatement(YieldStatement node) => _nodeExits(node.expression);
-
-  /// Return `true` if the given node exits.
-  ///
-  /// @param node the node being tested
-  /// @return `true` if the given node exits
-  bool _nodeExits(AstNode node) {
-    if (node == null) {
-      return false;
-    }
-    return node.accept(this);
-  }
-
-  bool _visitExpressions(NodeList<Expression> expressions) {
-    for (int i = expressions.length - 1; i >= 0; i--) {
-      if (expressions[i].accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool _visitStatements(NodeList<Statement> statements) {
-    for (int i = 0; i < statements.length; i++) {
-      if (statements[i].accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  bool _visitVariableDeclarations(
-      NodeList<VariableDeclaration> variableDeclarations) {
-    for (int i = variableDeclarations.length - 1; i >= 0; i--) {
-      if (variableDeclarations[i].accept(this)) {
-        return true;
-      }
-    }
-    return false;
-  }
-
-  /// Return `true` if the given [node] exits.
-  static bool exits(AstNode node) {
-    return new ExitDetector()._nodeExits(node);
-  }
-}
-
 /// A visitor that visits ASTs and fills [UsedImportedElements].
 class GatherUsedImportedElementsVisitor extends RecursiveAstVisitor {
   final LibraryElement library;
@@ -3820,18 +3309,13 @@
 
   /// Resolve the instance fields in the given compilation unit [node].
   void resolveCompilationUnit(CompilationUnit node) {
-    _overrideManager.enterScope();
-    try {
-      NodeList<CompilationUnitMember> declarations = node.declarations;
-      int declarationCount = declarations.length;
-      for (int i = 0; i < declarationCount; i++) {
-        CompilationUnitMember declaration = declarations[i];
-        if (declaration is ClassDeclaration) {
-          _resolveClassDeclaration(declaration);
-        }
+    NodeList<CompilationUnitMember> declarations = node.declarations;
+    int declarationCount = declarations.length;
+    for (int i = 0; i < declarationCount; i++) {
+      CompilationUnitMember declaration = declarations[i];
+      if (declaration is ClassDeclaration) {
+        _resolveClassDeclaration(declaration);
       }
-    } finally {
-      _overrideManager.exitScope();
     }
   }
 
@@ -4184,10 +3668,6 @@
 
   InferenceContext inferenceContext = null;
 
-  /// The object keeping track of which elements have had their types
-  /// overridden.
-  TypeOverrideManager _overrideManager = new TypeOverrideManager();
-
   /// The object keeping track of which elements have had their types promoted.
   TypePromotionManager _promoteManager = new TypePromotionManager();
 
@@ -4248,13 +3728,6 @@
   ExecutableElement get enclosingFunction => _enclosingFunction;
 
   /// Return the object keeping track of which elements have had their types
-  /// overridden.
-  ///
-  /// @return the object keeping track of which elements have had their types
-  ///         overridden
-  TypeOverrideManager get overrideManager => _overrideManager;
-
-  /// Return the object keeping track of which elements have had their types
   /// promoted.
   ///
   /// @return the object keeping track of which elements have had their types
@@ -4300,11 +3773,6 @@
     return null;
   }
 
-  /// Prepares this [ResolverVisitor] to using it for incremental resolution.
-  void initForIncrementalResolution() {
-    _overrideManager.enterScope();
-  }
-
   /// Given a downward inference type [fnType], and the declared
   /// [typeParameterList] for a function expression, determines if we can enable
   /// downward inference and if so, returns the function type to use for
@@ -4361,66 +3829,6 @@
     // TODO(brianwilkerson) Remove this method.
   }
 
-  /// If it is appropriate to do so, override the current type of the given
-  /// element with the given type.
-  ///
-  /// @param element the element whose type might be overridden
-  /// @param potentialType the potential type of the element
-  /// @param allowPrecisionLoss true if `potentialType` is allowed to be less
-  ///        precise than the current best type
-  ///
-  /// Return a new better [DartType], or `null` if [potentialType] is not better
-  /// than the current [element] type.
-  DartType overrideVariable(VariableElement element, DartType potentialType,
-      bool allowPrecisionLoss) {
-    // TODO(scheglov) type propagation for instance/top-level fields
-    // was disabled because it depends on the order or visiting.
-    // If both field and its client are in the same unit, and we visit
-    // the client before the field, then propagated type is not set yet.
-    if (element is PropertyInducingElement) {
-      return null;
-    }
-
-    if (potentialType == null ||
-        potentialType.isBottom ||
-        potentialType.isDartCoreNull) {
-      return null;
-    }
-    DartType currentType = _overrideManager.getBestType(element);
-
-    if (potentialType == currentType) {
-      return null;
-    }
-
-    // If we aren't allowing precision loss then the third and fourth conditions
-    // check that we aren't losing precision.
-    //
-    // Let [C] be the current type and [P] be the potential type.  When we
-    // aren't allowing precision loss -- which is the case for is-checks -- we
-    // check that [! (C << P)] or  [P << C]. The second check, that [P << C], is
-    // analogous to part of the Dart Language Spec rule for type promotion under
-    // is-checks (in the analogy [T] is [P] and [S] is [C]):
-    //
-    //   An is-expression of the form [v is T] shows that [v] has type [T] iff
-    //   [T] is more specific than the type [S] of the expression [v] and both
-    //   [T != dynamic] and [S != dynamic].
-    //
-    // It also covers an important case that is not applicable in the spec:
-    // for union types, we want an is-check to promote from an union type to
-    // (a subtype of) any of its members.
-    //
-    // The first check, that [! (C << P)], covers the case where [P] and [C] are
-    // unrelated types; This case is not addressed in the spec for static types.
-    if (currentType == null ||
-        allowPrecisionLoss ||
-        !currentType.isMoreSpecificThan(potentialType) ||
-        potentialType.isMoreSpecificThan(currentType)) {
-      _overrideManager.setType(element, potentialType);
-      return potentialType;
-    }
-    return null;
-  }
-
   /// A client is about to resolve a member in the given class declaration.
   void prepareToResolveMembersInClass(ClassDeclaration node) {
     _enclosingClassDeclaration = node;
@@ -4551,23 +3959,18 @@
       InferenceContext.setType(rightOperand, typeProvider.boolType);
       leftOperand?.accept(this);
       if (rightOperand != null) {
-        _overrideManager.enterScope();
+        _promoteManager.enterScope();
         try {
-          _promoteManager.enterScope();
-          try {
-            // Type promotion.
-            _promoteTypes(leftOperand);
-            _clearTypePromotionsIfPotentiallyMutatedIn(leftOperand);
-            _clearTypePromotionsIfPotentiallyMutatedIn(rightOperand);
-            _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
-                rightOperand);
-            // Visit right operand.
-            rightOperand.accept(this);
-          } finally {
-            _promoteManager.exitScope();
-          }
+          // Type promotion.
+          _promoteTypes(leftOperand);
+          _clearTypePromotionsIfPotentiallyMutatedIn(leftOperand);
+          _clearTypePromotionsIfPotentiallyMutatedIn(rightOperand);
+          _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
+              rightOperand);
+          // Visit right operand.
+          rightOperand.accept(this);
         } finally {
-          _overrideManager.exitScope();
+          _promoteManager.exitScope();
         }
       }
       node.accept(elementResolver);
@@ -4576,12 +3979,7 @@
       InferenceContext.setType(rightOperand, typeProvider.boolType);
       leftOperand?.accept(this);
       if (rightOperand != null) {
-        _overrideManager.enterScope();
-        try {
-          rightOperand.accept(this);
-        } finally {
-          _overrideManager.exitScope();
-        }
+        rightOperand.accept(this);
       }
       node.accept(elementResolver);
     } else {
@@ -4619,12 +4017,10 @@
 
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
-    _overrideManager.enterScope();
     try {
       inferenceContext.pushReturnContext(node);
       super.visitBlockFunctionBody(node);
     } finally {
-      _overrideManager.exitScope();
       inferenceContext.popReturnContext(node);
     }
   }
@@ -4710,20 +4106,15 @@
 
   @override
   void visitCompilationUnit(CompilationUnit node) {
-    _overrideManager.enterScope();
-    try {
-      NodeList<Directive> directives = node.directives;
-      int directiveCount = directives.length;
-      for (int i = 0; i < directiveCount; i++) {
-        directives[i].accept(this);
-      }
-      NodeList<CompilationUnitMember> declarations = node.declarations;
-      int declarationCount = declarations.length;
-      for (int i = 0; i < declarationCount; i++) {
-        declarations[i].accept(this);
-      }
-    } finally {
-      _overrideManager.exitScope();
+    NodeList<Directive> directives = node.directives;
+    int directiveCount = directives.length;
+    for (int i = 0; i < directiveCount; i++) {
+      directives[i].accept(this);
+    }
+    NodeList<CompilationUnitMember> declarations = node.declarations;
+    int declarationCount = declarations.length;
+    for (int i = 0; i < declarationCount; i++) {
+      declarations[i].accept(this);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -4735,34 +4126,24 @@
     condition?.accept(this);
     Expression thenExpression = node.thenExpression;
     if (thenExpression != null) {
-      _overrideManager.enterScope();
+      _promoteManager.enterScope();
       try {
-        _promoteManager.enterScope();
-        try {
-          // Type promotion.
-          _promoteTypes(condition);
-          _clearTypePromotionsIfPotentiallyMutatedIn(thenExpression);
-          _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
-              thenExpression);
-          // Visit "then" expression.
-          InferenceContext.setTypeFromNode(thenExpression, node);
-          thenExpression.accept(this);
-        } finally {
-          _promoteManager.exitScope();
-        }
+        // Type promotion.
+        _promoteTypes(condition);
+        _clearTypePromotionsIfPotentiallyMutatedIn(thenExpression);
+        _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
+            thenExpression);
+        // Visit "then" expression.
+        InferenceContext.setTypeFromNode(thenExpression, node);
+        thenExpression.accept(this);
       } finally {
-        _overrideManager.exitScope();
+        _promoteManager.exitScope();
       }
     }
     Expression elseExpression = node.elseExpression;
     if (elseExpression != null) {
-      _overrideManager.enterScope();
-      try {
-        InferenceContext.setTypeFromNode(elseExpression, node);
-        elseExpression.accept(this);
-      } finally {
-        _overrideManager.exitScope();
-      }
+      InferenceContext.setTypeFromNode(elseExpression, node);
+      elseExpression.accept(this);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
@@ -4854,15 +4235,8 @@
 
   @override
   void visitDoStatement(DoStatement node) {
-    _overrideManager.enterScope();
-    try {
-      InferenceContext.setType(node.condition, typeProvider.boolType);
-      super.visitDoStatement(node);
-    } finally {
-      _overrideManager.exitScope();
-    }
-    // TODO(brianwilkerson) If the loop can only be exited because the condition
-    // is false, then propagateFalseState(node.getCondition());
+    InferenceContext.setType(node.condition, typeProvider.boolType);
+    super.visitDoStatement(node);
   }
 
   @override
@@ -4906,7 +4280,6 @@
     if (resolveOnlyCommentInFunctionBody) {
       return;
     }
-    _overrideManager.enterScope();
     try {
       InferenceContext.setTypeFromNode(node.expression, node);
       inferenceContext.pushReturnContext(node);
@@ -4920,35 +4293,11 @@
         inferenceContext.addReturnOrYieldType(type);
       }
     } finally {
-      _overrideManager.exitScope();
       inferenceContext.popReturnContext(node);
     }
   }
 
   @override
-  void visitFieldDeclaration(FieldDeclaration node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitFieldDeclaration(node);
-    } finally {
-      Map<VariableElement, DartType> overrides =
-          _overrideManager.captureOverrides(node.fields);
-      _overrideManager.exitScope();
-      _overrideManager.applyOverrides(overrides);
-    }
-  }
-
-  @override
-  void visitForEachStatement(ForEachStatement node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitForEachStatement(node);
-    } finally {
-      _overrideManager.exitScope();
-    }
-  }
-
-  @override
   void visitForEachStatementInScope(ForEachStatement node) {
     Expression iterable = node.iterable;
     DeclaredIdentifier loopVariable = node.loopVariable;
@@ -4986,61 +4335,122 @@
     loopVariable?.accept(this);
     Statement body = node.body;
     if (body != null) {
-      _overrideManager.enterScope();
-      try {
-        if (loopVariable != null && iterable != null) {
-          LocalVariableElement loopElement = loopVariable.declaredElement;
-          if (loopElement != null) {
-            DartType propagatedType = null;
-            if (node.awaitKeyword == null) {
-              propagatedType = _getIteratorElementType(iterable);
-            } else {
-              propagatedType = _getStreamElementType(iterable);
-            }
-            if (propagatedType != null) {
-              overrideVariable(loopElement, propagatedType, true);
-            }
-          }
-        } else if (identifier != null && iterable != null) {
-          Element identifierElement = identifier.staticElement;
-          if (identifierElement is VariableElement) {
-            DartType iteratorElementType = _getIteratorElementType(iterable);
-            overrideVariable(identifierElement, iteratorElementType, true);
-          }
-        }
-        visitStatementInScope(body);
-      } finally {
-        _overrideManager.exitScope();
-      }
+      visitStatementInScope(body);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
   }
 
   @override
-  void visitForStatement(ForStatement node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitForStatement(node);
-    } finally {
-      _overrideManager.exitScope();
-    }
-  }
+  void visitForElement(ForElement node) {
+    ForLoopParts forLoopParts = node.forLoopParts;
+    if (forLoopParts is ForParts) {
+      if (forLoopParts is ForPartsWithDeclarations) {
+        forLoopParts.variables?.accept(this);
+      } else if (forLoopParts is ForPartsWithExpression) {
+        forLoopParts.initialization?.accept(this);
+      }
+      InferenceContext.setType(forLoopParts.condition, typeProvider.boolType);
+      forLoopParts.condition?.accept(this);
+      node.body?.accept(this);
+      forLoopParts.updaters.accept(this);
+    } else if (forLoopParts is ForEachParts) {
+      Expression iterable = forLoopParts.iterable;
+      DeclaredIdentifier loopVariable;
+      DartType valueType;
+      if (forLoopParts is ForEachPartsWithDeclaration) {
+        loopVariable = forLoopParts.loopVariable;
+        valueType = loopVariable?.type?.type ?? UnknownInferredType.instance;
+      } else if (forLoopParts is ForEachPartsWithIdentifier) {
+        SimpleIdentifier identifier = forLoopParts.identifier;
+        identifier?.accept(this);
+        Element element = identifier?.staticElement;
+        if (element is VariableElement) {
+          valueType = element.type;
+        } else if (element is PropertyAccessorElement) {
+          if (element.parameters.isNotEmpty) {
+            valueType = element.parameters[0].type;
+          }
+        }
+      }
 
-  @override
-  void visitForStatement2(ForStatement2 node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitForStatement2(node);
-    } finally {
-      _overrideManager.exitScope();
+      if (valueType != null) {
+        InterfaceType targetType = (node.awaitKeyword == null)
+            ? typeProvider.iterableType
+            : typeProvider.streamType;
+        InferenceContext.setType(iterable, targetType.instantiate([valueType]));
+      }
+      //
+      // We visit the iterator before the loop variable because the loop
+      // variable cannot be in scope while visiting the iterator.
+      //
+      iterable?.accept(this);
+      loopVariable?.accept(this);
+      node.body?.accept(this);
+
+      node.accept(elementResolver);
+      node.accept(typeAnalyzer);
     }
   }
 
   @override
   void visitForStatement2InScope(ForStatement2 node) {
-    throw new UnsupportedError('Implement this');
-    visitStatementInScope(node.body); // ignore: dead_code
+    ForLoopParts forLoopParts = node.forLoopParts;
+    if (forLoopParts is ForParts) {
+      if (forLoopParts is ForPartsWithDeclarations) {
+        forLoopParts.variables?.accept(this);
+      } else if (forLoopParts is ForPartsWithExpression) {
+        forLoopParts.initialization?.accept(this);
+      }
+      InferenceContext.setType(forLoopParts.condition, typeProvider.boolType);
+      forLoopParts.condition?.accept(this);
+      visitStatementInScope(node.body);
+      forLoopParts.updaters.accept(this);
+    } else if (forLoopParts is ForEachParts) {
+      Expression iterable = forLoopParts.iterable;
+      DeclaredIdentifier loopVariable;
+      SimpleIdentifier identifier;
+      if (forLoopParts is ForEachPartsWithDeclaration) {
+        loopVariable = forLoopParts.loopVariable;
+      } else if (forLoopParts is ForEachPartsWithIdentifier) {
+        identifier = forLoopParts.identifier;
+        identifier?.accept(this);
+      }
+
+      DartType valueType;
+      if (loopVariable != null) {
+        TypeAnnotation typeAnnotation = loopVariable.type;
+        valueType = typeAnnotation?.type ?? UnknownInferredType.instance;
+      }
+      if (identifier != null) {
+        Element element = identifier.staticElement;
+        if (element is VariableElement) {
+          valueType = element.type;
+        } else if (element is PropertyAccessorElement) {
+          if (element.parameters.isNotEmpty) {
+            valueType = element.parameters[0].type;
+          }
+        }
+      }
+      if (valueType != null) {
+        InterfaceType targetType = (node.awaitKeyword == null)
+            ? typeProvider.iterableType
+            : typeProvider.streamType;
+        InferenceContext.setType(iterable, targetType.instantiate([valueType]));
+      }
+      //
+      // We visit the iterator before the loop variable because the loop variable
+      // cannot be in scope while visiting the iterator.
+      //
+      iterable?.accept(this);
+      loopVariable?.accept(this);
+      Statement body = node.body;
+      if (body != null) {
+        visitStatementInScope(body);
+      }
+      node.accept(elementResolver);
+      node.accept(typeAnalyzer);
+    }
   }
 
   @override
@@ -5049,13 +4459,8 @@
     node.initialization?.accept(this);
     InferenceContext.setType(node.condition, typeProvider.boolType);
     node.condition?.accept(this);
-    _overrideManager.enterScope();
-    try {
-      visitStatementInScope(node.body);
-      node.updaters.accept(this);
-    } finally {
-      _overrideManager.exitScope();
-    }
+    visitStatementInScope(node.body);
+    node.updaters.accept(this);
   }
 
   @override
@@ -5088,22 +4493,17 @@
     try {
       _currentFunctionBody = node.body;
       _enclosingFunction = node.declaredElement;
-      _overrideManager.enterScope();
-      try {
-        DartType functionType = InferenceContext.getContext(node);
+      DartType functionType = InferenceContext.getContext(node);
+      if (functionType is FunctionType) {
+        functionType =
+            matchFunctionTypeParameters(node.typeParameters, functionType);
         if (functionType is FunctionType) {
-          functionType =
-              matchFunctionTypeParameters(node.typeParameters, functionType);
-          if (functionType is FunctionType) {
-            _inferFormalParameterList(node.parameters, functionType);
-            InferenceContext.setType(
-                node.body, _computeReturnOrYieldType(functionType.returnType));
-          }
+          _inferFormalParameterList(node.parameters, functionType);
+          InferenceContext.setType(
+              node.body, _computeReturnOrYieldType(functionType.returnType));
         }
-        super.visitFunctionExpression(node);
-      } finally {
-        _overrideManager.exitScope();
       }
+      super.visitFunctionExpression(node);
     } finally {
       _currentFunctionBody = outerFunctionBody;
       _enclosingFunction = outerFunction;
@@ -5153,61 +4553,57 @@
   void visitHideCombinator(HideCombinator node) {}
 
   @override
+  void visitIfElement(IfElement node) {
+    Expression condition = node.condition;
+    InferenceContext.setType(condition, typeProvider.boolType);
+    condition?.accept(this);
+    CollectionElement thenElement = node.thenElement;
+    if (thenElement != null) {
+      _promoteManager.enterScope();
+      try {
+        // Type promotion.
+        _promoteTypes(condition);
+        _clearTypePromotionsIfPotentiallyMutatedIn(thenElement);
+        _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
+            thenElement);
+        // Visit "then".
+        thenElement.accept(this);
+      } finally {
+        _promoteManager.exitScope();
+      }
+    }
+    node.elseElement?.accept(this);
+
+    node.accept(elementResolver);
+    node.accept(typeAnalyzer);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     Expression condition = node.condition;
     InferenceContext.setType(condition, typeProvider.boolType);
     condition?.accept(this);
-    Map<VariableElement, DartType> thenOverrides =
-        const <VariableElement, DartType>{};
     Statement thenStatement = node.thenStatement;
     if (thenStatement != null) {
-      _overrideManager.enterScope();
+      _promoteManager.enterScope();
       try {
-        _promoteManager.enterScope();
-        try {
-          // Type promotion.
-          _promoteTypes(condition);
-          _clearTypePromotionsIfPotentiallyMutatedIn(thenStatement);
-          _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
-              thenStatement);
-          // Visit "then".
-          visitStatementInScope(thenStatement);
-        } finally {
-          _promoteManager.exitScope();
-        }
+        // Type promotion.
+        _promoteTypes(condition);
+        _clearTypePromotionsIfPotentiallyMutatedIn(thenStatement);
+        _clearTypePromotionsIfAccessedInClosureAndProtentiallyMutated(
+            thenStatement);
+        // Visit "then".
+        visitStatementInScope(thenStatement);
       } finally {
-        thenOverrides = _overrideManager.captureLocalOverrides();
-        _overrideManager.exitScope();
+        _promoteManager.exitScope();
       }
     }
-    Map<VariableElement, DartType> elseOverrides =
-        const <VariableElement, DartType>{};
     Statement elseStatement = node.elseStatement;
     if (elseStatement != null) {
-      _overrideManager.enterScope();
-      try {
-        visitStatementInScope(elseStatement);
-      } finally {
-        elseOverrides = _overrideManager.captureLocalOverrides();
-        _overrideManager.exitScope();
-      }
+      visitStatementInScope(elseStatement);
     }
     node.accept(elementResolver);
     node.accept(typeAnalyzer);
-    // Join overrides.
-    bool thenIsAbrupt = _isAbruptTerminationStatement(thenStatement);
-    bool elseIsAbrupt = _isAbruptTerminationStatement(elseStatement);
-    if (elseIsAbrupt && !thenIsAbrupt) {
-      _overrideManager.applyOverrides(thenOverrides);
-    } else if (thenIsAbrupt && !elseIsAbrupt) {
-      _overrideManager.applyOverrides(elseOverrides);
-    } else if (!thenIsAbrupt && !elseIsAbrupt) {
-      List<Map<VariableElement, DartType>> perBranchOverrides =
-          <Map<VariableElement, DartType>>[];
-      perBranchOverrides.add(thenOverrides);
-      perBranchOverrides.add(elseOverrides);
-      _overrideManager.mergeOverrides(perBranchOverrides);
-    }
   }
 
   @override
@@ -5343,10 +4739,10 @@
       DartType kType = mapT.typeArguments[0];
       DartType vType = mapT.typeArguments[1];
 
-      void pushTypesDown(MapElement element) {
-        if (element is MapForElement) {
+      void pushTypesDown(CollectionElement element) {
+        if (element is ForElement) {
           pushTypesDown(element.body);
-        } else if (element is MapIfElement) {
+        } else if (element is IfElement) {
           pushTypesDown(element.thenElement);
           pushTypesDown(element.elseElement);
         } else if (element is MapLiteralEntry) {
@@ -5357,7 +4753,7 @@
         }
       }
 
-      for (MapElement element in node.entries) {
+      for (CollectionElement element in node.entries) {
         pushTypesDown(element);
       }
       InferenceContext.setType(node, mapT);
@@ -5572,24 +4968,9 @@
 
   @override
   void visitSwitchCase(SwitchCase node) {
-    _overrideManager.enterScope();
-    try {
-      InferenceContext.setType(
-          node.expression, _enclosingSwitchStatementExpressionType);
-      super.visitSwitchCase(node);
-    } finally {
-      _overrideManager.exitScope();
-    }
-  }
-
-  @override
-  void visitSwitchDefault(SwitchDefault node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitSwitchDefault(node);
-    } finally {
-      _overrideManager.exitScope();
-    }
+    InferenceContext.setType(
+        node.expression, _enclosingSwitchStatementExpressionType);
+    super.visitSwitchCase(node);
   }
 
   @override
@@ -5605,19 +4986,6 @@
   }
 
   @override
-  void visitTopLevelVariableDeclaration(TopLevelVariableDeclaration node) {
-    _overrideManager.enterScope();
-    try {
-      super.visitTopLevelVariableDeclaration(node);
-    } finally {
-      Map<VariableElement, DartType> overrides =
-          _overrideManager.captureOverrides(node.variables);
-      _overrideManager.exitScope();
-      _overrideManager.applyOverrides(overrides);
-    }
-  }
-
-  @override
   void visitTypeName(TypeName node) {}
 
   @override
@@ -5661,12 +5029,7 @@
       condition?.accept(this);
       Statement body = node.body;
       if (body != null) {
-        _overrideManager.enterScope();
-        try {
-          visitStatementInScope(body);
-        } finally {
-          _overrideManager.exitScope();
-        }
+        visitStatementInScope(body);
       }
     } finally {
       _implicitLabelScope = outerImplicitScope;
@@ -5792,62 +5155,6 @@
     return typeProvider.futureOrType.instantiate([type]);
   }
 
-  /// The given expression is the expression used to compute the iterator for a
-  /// for-each statement. Attempt to compute the type of objects that will be
-  /// assigned to the loop variable and return that type. Return `null` if the
-  /// type could not be determined. The [iteratorExpression] is the expression
-  /// that will return the Iterable being iterated over.
-  DartType _getIteratorElementType(Expression iteratorExpression) {
-    DartType expressionType = iteratorExpression.staticType;
-    if (expressionType is InterfaceType) {
-      PropertyAccessorElement iteratorFunction =
-          expressionType.lookUpInheritedGetter("iterator");
-      if (iteratorFunction == null) {
-        // TODO(brianwilkerson) Should we report this error?
-        return null;
-      }
-      DartType iteratorType = iteratorFunction.returnType;
-      if (iteratorType is InterfaceType) {
-        PropertyAccessorElement currentFunction =
-            iteratorType.lookUpInheritedGetter("current");
-        if (currentFunction == null) {
-          // TODO(brianwilkerson) Should we report this error?
-          return null;
-        }
-        return currentFunction.returnType;
-      }
-    }
-    return null;
-  }
-
-  /// The given expression is the expression used to compute the stream for an
-  /// asynchronous for-each statement. Attempt to compute the type of objects
-  /// that will be assigned to the loop variable and return that type.
-  /// Return `null` if the type could not be determined. The [streamExpression]
-  /// is the expression that will return the stream being iterated over.
-  DartType _getStreamElementType(Expression streamExpression) {
-    DartType streamType = streamExpression.staticType;
-    if (streamType is InterfaceType) {
-      MethodElement listenFunction = streamType.lookUpInheritedMethod("listen");
-      if (listenFunction == null) {
-        return null;
-      }
-      List<ParameterElement> listenParameters = listenFunction.parameters;
-      if (listenParameters == null || listenParameters.length < 1) {
-        return null;
-      }
-      DartType onDataType = listenParameters[0].type;
-      if (onDataType is FunctionType) {
-        List<ParameterElement> onDataParameters = onDataType.parameters;
-        if (onDataParameters == null || onDataParameters.isEmpty) {
-          return null;
-        }
-        return onDataParameters[0].type;
-      }
-    }
-    return null;
-  }
-
   /// Return `true` if the given [parameter] element of the AST being resolved
   /// is resynthesized and is an API-level, not local, so has its initializer
   /// serialized.
@@ -5974,71 +5281,6 @@
     }
   }
 
-  /// Return `true` if the given expression terminates abruptly (that is, if any
-  /// expression following the given expression will not be reached).
-  ///
-  /// @param expression the expression being tested
-  /// @return `true` if the given expression terminates abruptly
-  bool _isAbruptTerminationExpression(Expression expression) {
-    // TODO(brianwilkerson) This needs to be significantly improved. Ideally we
-    // would eventually turn this into a method on Expression that returns a
-    // termination indication (normal, abrupt with no exception, abrupt with an
-    // exception).
-    expression = expression?.unParenthesized;
-    return expression is ThrowExpression || expression is RethrowExpression;
-  }
-
-  /// Return `true` if the given statement terminates abruptly (that is, if any
-  /// statement following the given statement will not be reached).
-  ///
-  /// @param statement the statement being tested
-  /// @return `true` if the given statement terminates abruptly
-  bool _isAbruptTerminationStatement(Statement statement) {
-    // TODO(brianwilkerson) This needs to be significantly improved. Ideally we
-    // would eventually turn this into a method on Statement that returns a
-    // termination indication (normal, abrupt with no exception, abrupt with an
-    // exception).
-    //
-    // collinsn: it is unsound to assume that [break] and [continue] are
-    // "abrupt". See: https://code.google.com/p/dart/issues/detail?id=19929#c4
-    // (tests are included in TypePropagationTest.java).
-    // In general, the difficulty is loopy control flow.
-    //
-    // In the presence of exceptions things become much more complicated, but
-    // while we only use this to propagate at [if]-statement join points,
-    // checking for [return] may work well enough in the common case.
-    if (statement is ReturnStatement) {
-      return true;
-    } else if (statement is ExpressionStatement) {
-      return _isAbruptTerminationExpression(statement.expression);
-    } else if (statement is Block) {
-      NodeList<Statement> statements = statement.statements;
-      int size = statements.length;
-      if (size == 0) {
-        return false;
-      }
-
-      // This last-statement-is-return heuristic is unsound for adversarial
-      // code, but probably works well in the common case:
-      //
-      //   var x = 123;
-      //   var c = true;
-      //   L: if (c) {
-      //     x = "hello";
-      //     c = false;
-      //     break L;
-      //     return;
-      //   }
-      //   print(x);
-      //
-      // Unsound to assume that [x = "hello";] never executed after the
-      // if-statement. Of course, a dead-code analysis could point out that
-      // [return] here is dead.
-      return _isAbruptTerminationStatement(statements[size - 1]);
-    }
-    return false;
-  }
-
   /// Return `true` if the given variable is accessed within a closure in the
   /// given [AstNode] and also mutated somewhere in variable scope. This
   /// information is only available for local variables (including parameters).
@@ -6121,9 +5363,9 @@
 
   void _pushCollectionTypesDown(
       CollectionElement element, ParameterizedType collectionType) {
-    if (element is CollectionForElement) {
+    if (element is ForElement) {
       _pushCollectionTypesDown(element.body, collectionType);
-    } else if (element is CollectionIfElement) {
+    } else if (element is IfElement) {
       _pushCollectionTypesDown(element.thenElement, collectionType);
       _pushCollectionTypesDown(element.elseElement, collectionType);
     } else if (element is Expression) {
@@ -7659,191 +6901,6 @@
   }
 }
 
-/// Instances of the class `TypeOverrideManager` manage the ability to override
-/// the type of an element within a given context.
-class TypeOverrideManager {
-  /// The current override scope, or `null` if no scope has been entered.
-  TypeOverrideManager_TypeOverrideScope currentScope;
-
-  /// Apply a set of overrides that were previously captured.
-  ///
-  /// @param overrides the overrides to be applied
-  void applyOverrides(Map<VariableElement, DartType> overrides) {
-    if (currentScope == null) {
-      throw new StateError("Cannot apply overrides without a scope");
-    }
-    currentScope.applyOverrides(overrides);
-  }
-
-  /// Return a table mapping the elements whose type is overridden in the
-  /// current scope to the overriding type.
-  ///
-  /// @return the overrides in the current scope
-  Map<VariableElement, DartType> captureLocalOverrides() {
-    if (currentScope == null) {
-      throw new StateError("Cannot capture local overrides without a scope");
-    }
-    return currentScope.captureLocalOverrides();
-  }
-
-  /// Return a map from the elements for the variables in the given list that
-  /// have their types overridden to the overriding type.
-  ///
-  /// @param variableList the list of variables whose overriding types are to be
-  ///        captured
-  /// @return a table mapping elements to their overriding types
-  Map<VariableElement, DartType> captureOverrides(
-      VariableDeclarationList variableList) {
-    if (currentScope == null) {
-      throw new StateError("Cannot capture overrides without a scope");
-    }
-    return currentScope.captureOverrides(variableList);
-  }
-
-  /// Enter a new override scope.
-  void enterScope() {
-    currentScope = new TypeOverrideManager_TypeOverrideScope(currentScope);
-  }
-
-  /// Exit the current override scope.
-  void exitScope() {
-    if (currentScope == null) {
-      throw new StateError("No scope to exit");
-    }
-    currentScope = currentScope._outerScope;
-  }
-
-  /// Return the best type information available for the given element. If the
-  /// type of the element has been overridden, then return the overriding type.
-  /// Otherwise, return the static type.
-  ///
-  /// @param element the element for which type information is to be returned
-  /// @return the best type information available for the given element
-  DartType getBestType(VariableElement element) {
-    DartType bestType = getType(element);
-    return bestType ?? element.type;
-  }
-
-  /// Return the overridden type of the given element, or `null` if the type of
-  /// the element has not been overridden.
-  ///
-  /// @param element the element whose type might have been overridden
-  /// @return the overridden type of the given element
-  DartType getType(Element element) {
-    if (currentScope == null) {
-      return null;
-    }
-    return currentScope.getType(element);
-  }
-
-  /// Update overrides assuming [perBranchOverrides] is the collection of
-  /// per-branch overrides for *all* branches flowing into a join point.
-  void mergeOverrides(List<Map<VariableElement, DartType>> perBranchOverrides) {
-    int length = perBranchOverrides.length;
-    for (int i = 0; i < length; i++) {
-      Map<VariableElement, DartType> branch = perBranchOverrides[i];
-      branch.forEach((VariableElement variable, DartType branchType) {
-        DartType currentType = currentScope.getType(variable);
-        if (currentType != branchType) {
-          currentScope.resetType(variable);
-        }
-      });
-    }
-  }
-
-  /// Set the overridden type of the given element to the given type
-  ///
-  /// @param element the element whose type might have been overridden
-  /// @param type the overridden type of the given element
-  void setType(VariableElement element, DartType type) {
-    if (currentScope == null) {
-      throw new StateError("Cannot override without a scope");
-    }
-    currentScope.setType(element, type);
-  }
-}
-
-/// Instances of the class `TypeOverrideScope` represent a scope in which the
-/// types of elements can be overridden.
-class TypeOverrideManager_TypeOverrideScope {
-  /// The outer scope in which types might be overridden.
-  final TypeOverrideManager_TypeOverrideScope _outerScope;
-
-  /// A table mapping elements to the overridden type of that element.
-  Map<VariableElement, DartType> _overriddenTypes =
-      new HashMap<VariableElement, DartType>();
-
-  /// Initialize a newly created scope to be an empty child of the given scope.
-  ///
-  /// @param outerScope the outer scope in which types might be overridden
-  TypeOverrideManager_TypeOverrideScope(this._outerScope);
-
-  /// Apply a set of overrides that were previously captured.
-  ///
-  /// @param overrides the overrides to be applied
-  void applyOverrides(Map<VariableElement, DartType> overrides) {
-    _overriddenTypes.addAll(overrides);
-  }
-
-  /// Return a table mapping the elements whose type is overridden in the
-  /// current scope to the overriding type.
-  ///
-  /// @return the overrides in the current scope
-  Map<VariableElement, DartType> captureLocalOverrides() => _overriddenTypes;
-
-  /// Return a map from the elements for the variables in the given list that
-  /// have their types overridden to the overriding type.
-  ///
-  /// @param variableList the list of variables whose overriding types are to be
-  ///        captured
-  /// @return a table mapping elements to their overriding types
-  Map<VariableElement, DartType> captureOverrides(
-      VariableDeclarationList variableList) {
-    Map<VariableElement, DartType> overrides =
-        new HashMap<VariableElement, DartType>();
-    if (variableList.isConst || variableList.isFinal) {
-      for (VariableDeclaration variable in variableList.variables) {
-        VariableElement element = variable.declaredElement;
-        if (element != null) {
-          DartType type = _overriddenTypes[element];
-          if (type != null) {
-            overrides[element] = type;
-          }
-        }
-      }
-    }
-    return overrides;
-  }
-
-  /// Return the overridden type of the given element, or `null` if the type of
-  /// the element has not been overridden.
-  ///
-  /// @param element the element whose type might have been overridden
-  /// @return the overridden type of the given element
-  DartType getType(Element element) {
-    Element nonAccessor =
-        element is PropertyAccessorElement ? element.variable : element;
-    DartType type = _overriddenTypes[nonAccessor];
-    if (_overriddenTypes.containsKey(nonAccessor)) {
-      return type;
-    }
-    return type ?? _outerScope?.getType(element);
-  }
-
-  /// Clears the overridden type of the given [element].
-  void resetType(VariableElement element) {
-    _overriddenTypes[element] = null;
-  }
-
-  /// Set the overridden type of the given element to the given type
-  ///
-  /// @param element the element whose type might have been overridden
-  /// @param type the overridden type of the given element
-  void setType(VariableElement element, DartType type) {
-    _overriddenTypes[element] = type;
-  }
-}
-
 /// This class resolves bounds of type parameters of classes, class and function
 /// type aliases.
 class TypeParameterBoundsResolver {
diff --git a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
index b55d885..23871b8 100644
--- a/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
+++ b/pkg/analyzer/lib/src/generated/static_type_analyzer.dart
@@ -1439,16 +1439,7 @@
 
   @override
   void visitVariableDeclaration(VariableDeclaration node) {
-    Expression initializer = node.initializer;
-    _inferLocalVariableType(node, initializer);
-    if (initializer != null) {
-      DartType rightType = initializer.staticType;
-      SimpleIdentifier name = node.name;
-      VariableElement element = name.staticElement as VariableElement;
-      if (element != null) {
-        _resolver.overrideVariable(element, rightType, true);
-      }
-    }
+    _inferLocalVariableType(node, node.initializer);
   }
 
   /**
@@ -1507,9 +1498,9 @@
   }
 
   DartType _computeElementType(CollectionElement element) {
-    if (element is CollectionForElement) {
+    if (element is ForElement) {
       return _computeElementType(element.body);
-    } else if (element is CollectionIfElement) {
+    } else if (element is IfElement) {
       DartType thenType = _computeElementType(element.thenElement);
       if (element.elseElement == null) {
         return thenType;
@@ -1545,10 +1536,10 @@
     return _dynamicType;
   }
 
-  DartType _computeKeyType(MapElement element) {
-    if (element is MapForElement) {
+  DartType _computeKeyType(CollectionElement element) {
+    if (element is ForElement) {
       return _computeKeyType(element.body);
-    } else if (element is MapIfElement) {
+    } else if (element is IfElement) {
       DartType thenType = _computeKeyType(element.thenElement);
       if (element.elseElement == null) {
         return thenType;
@@ -1635,10 +1626,10 @@
     return returnType.type;
   }
 
-  DartType _computeValueType(MapElement element) {
-    if (element is MapForElement) {
+  DartType _computeValueType(CollectionElement element) {
+    if (element is ForElement) {
       return _computeValueType(element.body);
-    } else if (element is MapIfElement) {
+    } else if (element is IfElement) {
       DartType thenType = _computeValueType(element.thenElement);
       if (element.elseElement == null) {
         return thenType;
diff --git a/pkg/analyzer/lib/src/generated/type_system.dart b/pkg/analyzer/lib/src/generated/type_system.dart
index 0a792c4..30b2925 100644
--- a/pkg/analyzer/lib/src/generated/type_system.dart
+++ b/pkg/analyzer/lib/src/generated/type_system.dart
@@ -67,7 +67,10 @@
  * A type system that implements the type semantics for Dart 2.0.
  */
 class Dart2TypeSystem extends TypeSystem {
-  static bool _comparingTypeParameterBounds = false;
+  /// Track types currently being compared via type parameter bounds so that we
+  /// can detect recursion.
+  static Set<TypeComparison> _typeParameterBoundsComparisons =
+      new HashSet<TypeComparison>();
 
   /**
    * True if implicit casts should be allowed, otherwise false.
@@ -930,14 +933,15 @@
 
   bool _typeParameterBoundsSubtype(
       DartType t1, DartType t2, bool recursionValue) {
-    if (_comparingTypeParameterBounds) {
+    TypeComparison comparison = TypeComparison(t1, t2);
+    if (_typeParameterBoundsComparisons.contains(comparison)) {
       return recursionValue;
     }
-    _comparingTypeParameterBounds = true;
+    _typeParameterBoundsComparisons.add(comparison);
     try {
       return isSubtypeOf(t1, t2);
     } finally {
-      _comparingTypeParameterBounds = false;
+      _typeParameterBoundsComparisons.remove(comparison);
     }
   }
 
@@ -1661,6 +1665,29 @@
   }
 }
 
+/// Used to check for infinite loops, if we repeat the same type comparison.
+class TypeComparison {
+  final DartType lhs;
+  final DartType rhs;
+
+  TypeComparison(this.lhs, this.rhs);
+
+  @override
+  int get hashCode => lhs.hashCode * 11 + rhs.hashCode;
+
+  @override
+  bool operator ==(Object other) {
+    if (other is TypeComparison) {
+      return lhs == other.lhs && rhs == other.rhs;
+    }
+
+    return false;
+  }
+
+  @override
+  String toString() => "$lhs vs $rhs";
+}
+
 /**
  * The interface `TypeSystem` defines the behavior of an object representing
  * the type system.  This provides a common location to put methods that act on
diff --git a/pkg/analyzer/lib/src/lint/analysis.dart b/pkg/analyzer/lib/src/lint/analysis.dart
index 65fde36..c9abd60 100644
--- a/pkg/analyzer/lib/src/lint/analysis.dart
+++ b/pkg/analyzer/lib/src/lint/analysis.dart
@@ -10,6 +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/context/builder.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -27,6 +28,7 @@
 import 'package:analyzer/src/lint/registry.dart';
 import 'package:analyzer/src/services/lint.dart';
 import 'package:analyzer/src/source/package_map_resolver.dart';
+import 'package:analyzer/src/task/options.dart';
 import 'package:analyzer/src/util/sdk.dart';
 import 'package:package_config/packages.dart' show Packages;
 import 'package:package_config/packages_file.dart' as pkgfile show parse;
@@ -34,6 +36,9 @@
 import 'package:path/path.dart' as p;
 import 'package:plugin/manager.dart';
 import 'package:plugin/plugin.dart';
+import 'package:yaml/yaml.dart';
+
+AnalysisOptionsProvider _optionsProvider = new AnalysisOptionsProvider();
 
 Source createSource(Uri sourceUri) {
   return PhysicalResourceProvider.INSTANCE
@@ -49,6 +54,12 @@
 
 AnalysisOptions _buildAnalyzerOptions(LinterOptions options) {
   AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
+  if (options.analysisOptions != null) {
+    YamlMap map =
+        _optionsProvider.getOptionsFromString(options.analysisOptions);
+    applyToAnalysisOptions(analysisOptions, map);
+  }
+
   analysisOptions.hint = false;
   analysisOptions.lint = options.enableLints;
   analysisOptions.generateSdkErrors = options.showSdkWarnings;
diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart
index 348322f..c60b97d1 100644
--- a/pkg/analyzer/lib/src/lint/linter.dart
+++ b/pkg/analyzer/lib/src/lint/linter.dart
@@ -16,7 +16,7 @@
 import 'package:analyzer/src/dart/ast/token.dart';
 import 'package:analyzer/src/dart/error/lint_codes.dart';
 import 'package:analyzer/src/generated/engine.dart'
-    show AnalysisErrorInfo, AnalysisErrorInfoImpl, Logger;
+    show AnalysisErrorInfo, AnalysisErrorInfoImpl, AnalysisOptions, Logger;
 import 'package:analyzer/src/generated/java_engine.dart' show CaughtException;
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/source.dart' show LineInfo;
@@ -199,6 +199,8 @@
 abstract class LinterContext {
   List<LinterContextUnit> get allUnits;
 
+  AnalysisOptions get analysisOptions;
+
   LinterContextUnit get currentUnit;
 
   DeclaredVariables get declaredVariables;
@@ -224,6 +226,9 @@
   final List<LinterContextUnit> allUnits;
 
   @override
+  final AnalysisOptions analysisOptions;
+
+  @override
   final LinterContextUnit currentUnit;
 
   @override
@@ -236,7 +241,7 @@
   final TypeSystem typeSystem;
 
   LinterContextImpl(this.allUnits, this.currentUnit, this.declaredVariables,
-      this.typeProvider, this.typeSystem);
+      this.typeProvider, this.typeSystem, this.analysisOptions);
 
   @override
   bool canBeConst(InstanceCreationExpression expression) {
@@ -291,13 +296,14 @@
 /// Linter options.
 class LinterOptions extends DriverOptions {
   Iterable<LintRule> enabledLints;
+  String analysisOptions;
   LintFilter filter;
   file_system.ResourceProvider resourceProvider;
-  LinterOptions([this.enabledLints]) {
+  // todo (pq): consider migrating to named params (but note Linter dep).
+  LinterOptions([this.enabledLints, this.analysisOptions]) {
     enabledLints ??= Registry.ruleRegistry;
   }
   void configure(LintConfig config) {
-    // TODO(pquitslund): revisit these default-to-on semantics.
     enabledLints = Registry.ruleRegistry.where((LintRule rule) =>
         !config.ruleConfigs.any((rc) => rc.disables(rule.name)));
     filter = new FileGlobFilter(config.fileIncludes, config.fileExcludes);
diff --git a/pkg/analyzer/lib/src/lint/linter_visitor.dart b/pkg/analyzer/lib/src/lint/linter_visitor.dart
index 54d81f6..98ba52c 100644
--- a/pkg/analyzer/lib/src/lint/linter_visitor.dart
+++ b/pkg/analyzer/lib/src/lint/linter_visitor.dart
@@ -109,18 +109,6 @@
   }
 
   @override
-  void visitCollectionForElement(CollectionForElement node) {
-    _runSubscriptions(node, registry._forCollectionForElement);
-    super.visitCollectionForElement(node);
-  }
-
-  @override
-  void visitCollectionIfElement(CollectionIfElement node) {
-    _runSubscriptions(node, registry._forCollectionIfElement);
-    super.visitCollectionIfElement(node);
-  }
-
-  @override
   void visitComment(Comment node) {
     _runSubscriptions(node, registry._forComment);
     super.visitComment(node);
@@ -283,6 +271,12 @@
   }
 
   @override
+  void visitForElement(ForElement node) {
+    _runSubscriptions(node, registry._forForElement);
+    super.visitForElement(node);
+  }
+
+  @override
   void visitFormalParameterList(FormalParameterList node) {
     _runSubscriptions(node, registry._forFormalParameterList);
     super.visitFormalParameterList(node);
@@ -367,6 +361,12 @@
   }
 
   @override
+  void visitIfElement(IfElement node) {
+    _runSubscriptions(node, registry._forIfElement);
+    super.visitIfElement(node);
+  }
+
+  @override
   void visitIfStatement(IfStatement node) {
     _runSubscriptions(node, registry._forIfStatement);
     super.visitIfStatement(node);
@@ -457,18 +457,6 @@
   }
 
   @override
-  void visitMapForElement(MapForElement node) {
-    _runSubscriptions(node, registry._forMapForElement);
-    super.visitMapForElement(node);
-  }
-
-  @override
-  void visitMapIfElement(MapIfElement node) {
-    _runSubscriptions(node, registry._forMapIfElement);
-    super.visitMapIfElement(node);
-  }
-
-  @override
   void visitMapLiteral(MapLiteral node) {
     _runSubscriptions(node, registry._forMapLiteral);
     super.visitMapLiteral(node);
@@ -779,8 +767,6 @@
   final List<_Subscription<CatchClause>> _forCatchClause = [];
   final List<_Subscription<ClassDeclaration>> _forClassDeclaration = [];
   final List<_Subscription<ClassTypeAlias>> _forClassTypeAlias = [];
-  final List<_Subscription<CollectionForElement>> _forCollectionForElement = [];
-  final List<_Subscription<CollectionIfElement>> _forCollectionIfElement = [];
   final List<_Subscription<Comment>> _forComment = [];
   final List<_Subscription<CommentReference>> _forCommentReference = [];
   final List<_Subscription<CompilationUnit>> _forCompilationUnit = [];
@@ -816,6 +802,7 @@
   final List<_Subscription<ForEachPartsWithIdentifier>>
       _forForEachPartsWithIdentifier = [];
   final List<_Subscription<ForEachStatement>> _forForEachStatement = [];
+  final List<_Subscription<ForElement>> _forForElement = [];
   final List<_Subscription<FormalParameterList>> _forFormalParameterList = [];
   final List<_Subscription<ForPartsWithDeclarations>>
       _forForPartsWithDeclarations = [];
@@ -835,6 +822,7 @@
   final List<_Subscription<GenericFunctionType>> _forGenericFunctionType = [];
   final List<_Subscription<GenericTypeAlias>> _forGenericTypeAlias = [];
   final List<_Subscription<HideCombinator>> _forHideCombinator = [];
+  final List<_Subscription<IfElement>> _forIfElement = [];
   final List<_Subscription<IfStatement>> _forIfStatement = [];
   final List<_Subscription<ImplementsClause>> _forImplementsClause = [];
   final List<_Subscription<ImportDirective>> _forImportDirective = [];
@@ -852,8 +840,6 @@
   final List<_Subscription<LibraryIdentifier>> _forLibraryIdentifier = [];
   final List<_Subscription<ListLiteral>> _forListLiteral = [];
   final List<_Subscription<ListLiteral2>> _forListLiteral2 = [];
-  final List<_Subscription<MapForElement>> _forMapForElement = [];
-  final List<_Subscription<MapIfElement>> _forMapIfElement = [];
   final List<_Subscription<MapLiteral>> _forMapLiteral = [];
   final List<_Subscription<MapLiteral2>> _forMapLiteral2 = [];
   final List<_Subscription<MapLiteralEntry>> _forMapLiteralEntry = [];
@@ -981,16 +967,6 @@
         .add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
 
-  void addCollectionForElement(LintRule linter, AstVisitor visitor) {
-    _forCollectionForElement
-        .add(new _Subscription(linter, visitor, _getTimer(linter)));
-  }
-
-  void addCollectionIfElement(LintRule linter, AstVisitor visitor) {
-    _forCollectionIfElement
-        .add(new _Subscription(linter, visitor, _getTimer(linter)));
-  }
-
   void addComment(LintRule linter, AstVisitor visitor) {
     _forComment.add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
@@ -1123,6 +1099,10 @@
         .add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
 
+  void addForElement(LintRule linter, AstVisitor visitor) {
+    _forForElement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
   void addFormalParameterList(LintRule linter, AstVisitor visitor) {
     _forFormalParameterList
         .add(new _Subscription(linter, visitor, _getTimer(linter)));
@@ -1192,6 +1172,10 @@
         .add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
 
+  void addIfElement(LintRule linter, AstVisitor visitor) {
+    _forIfElement.add(new _Subscription(linter, visitor, _getTimer(linter)));
+  }
+
   void addIfStatement(LintRule linter, AstVisitor visitor) {
     _forIfStatement.add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
@@ -1262,15 +1246,6 @@
     _forListLiteral2.add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
 
-  void addMapForElement(LintRule linter, AstVisitor visitor) {
-    _forMapForElement
-        .add(new _Subscription(linter, visitor, _getTimer(linter)));
-  }
-
-  void addMapIfElement(LintRule linter, AstVisitor visitor) {
-    _forMapIfElement.add(new _Subscription(linter, visitor, _getTimer(linter)));
-  }
-
   void addMapLiteral(LintRule linter, AstVisitor visitor) {
     _forMapLiteral.add(new _Subscription(linter, visitor, _getTimer(linter)));
   }
diff --git a/pkg/analyzer/lib/src/services/available_declarations.dart b/pkg/analyzer/lib/src/services/available_declarations.dart
index fd417fc..a9056f4 100644
--- a/pkg/analyzer/lib/src/services/available_declarations.dart
+++ b/pkg/analyzer/lib/src/services/available_declarations.dart
@@ -9,6 +9,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
+import 'package:analyzer/source/line_info.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/scanner/reader.dart';
 import 'package:analyzer/src/dart/scanner/scanner.dart';
@@ -20,19 +21,67 @@
 import 'package:analyzer/src/summary/idl.dart' as idl;
 import 'package:analyzer/src/summary/link.dart' as graph
     show DependencyWalker, Node;
+import 'package:analyzer/src/util/comment.dart';
 import 'package:convert/convert.dart';
+import 'package:meta/meta.dart';
 import 'package:yaml/yaml.dart';
 
 /// A top-level public declaration.
 class Declaration {
-  final String name;
+  final String docComplete;
+  final String docSummary;
+  final bool isAbstract;
+  final bool isConst;
+  final bool isDeprecated;
+  final bool isFinal;
   final DeclarationKind kind;
+  final int locationOffset;
+  final String locationPath;
+  final int locationStartColumn;
+  final int locationStartLine;
+  final String name;
+  final String name2;
+  final String parameters;
+  final List<String> parameterNames;
+  final List<String> parameterTypes;
+  final int requiredParameterCount;
+  final String returnType;
+  final String typeParameters;
 
-  Declaration(this.name, this.kind);
+  List<String> _relevanceTags;
+
+  Declaration({
+    @required this.docComplete,
+    @required this.docSummary,
+    @required this.isAbstract,
+    @required this.isConst,
+    @required this.isDeprecated,
+    @required this.isFinal,
+    @required this.kind,
+    @required this.locationOffset,
+    @required this.locationPath,
+    @required this.locationStartColumn,
+    @required this.locationStartLine,
+    @required this.name,
+    @required this.name2,
+    @required this.parameters,
+    @required this.parameterNames,
+    @required this.parameterTypes,
+    @required List<String> relevanceTags,
+    @required this.requiredParameterCount,
+    @required this.returnType,
+    @required this.typeParameters,
+  }) : _relevanceTags = relevanceTags;
+
+  List<String> get relevanceTags => _relevanceTags;
 
   @override
   String toString() {
-    return '($name, $kind)';
+    if (name2 == null) {
+      return '($kind, $name)';
+    } else {
+      return '($kind, $name, $name2)';
+    }
   }
 }
 
@@ -41,9 +90,12 @@
   CLASS,
   CLASS_TYPE_ALIAS,
   ENUM,
+  ENUM_CONSTANT,
   FUNCTION,
   FUNCTION_TYPE_ALIAS,
+  GETTER,
   MIXIN,
+  SETTER,
   VARIABLE
 }
 
@@ -123,7 +175,11 @@
     }
 
     var contextLibraries = <Library>[];
-    _addLibrariesWithPaths(contextLibraries, contextPathList);
+    _addLibrariesWithPaths(
+      contextLibraries,
+      contextPathList,
+      excludingLibraryOfPath: path,
+    );
 
     return Libraries(sdkLibraries, dependencyLibraries, contextLibraries);
   }
@@ -167,8 +223,20 @@
     }
   }
 
-  void _addLibrariesWithPaths(List<Library> libraries, List<String> pathList) {
+  void _addContextFile(String path) {
+    if (!_contextPathList.contains(path)) {
+      _contextPathList.add(path);
+    }
+  }
+
+  void _addLibrariesWithPaths(List<Library> libraries, List<String> pathList,
+      {String excludingLibraryOfPath}) {
+    var excludedFile = _tracker._pathToFile[excludingLibraryOfPath];
+    var excludedLibraryPath = (excludedFile?.library ?? excludedFile)?.path;
+
     for (var path in pathList) {
+      if (path == excludedLibraryPath) continue;
+
       var file = _tracker._pathToFile[path];
       if (file != null && file.isLibrary) {
         var library = _tracker._idToLibrary[file.id];
@@ -293,11 +361,13 @@
     // ignore: deprecated_member_use_from_same_package
     var sdk = _analysisContext.currentSession.sourceFactory.dartSdk;
     for (var uriStr in sdk.uris) {
-      var uri = Uri.parse(uriStr);
-      var path = _resolveUri(uri);
-      if (path != null) {
-        _sdkLibraryPathList.add(path);
-        _tracker._addFile(this, path);
+      if (!uriStr.startsWith('dart:_')) {
+        var uri = Uri.parse(uriStr);
+        var path = _resolveUri(uri);
+        if (path != null) {
+          _sdkLibraryPathList.add(path);
+          _tracker._addFile(this, path);
+        }
       }
     }
   }
@@ -383,9 +453,25 @@
   /// be invoked to send updates to [changes] that reflect changes to the
   /// library of the file, and other libraries that export it.
   void changeFile(String path) {
+    if (!path.endsWith('.dart')) return;
+
     _changedPaths.add(path);
   }
 
+  /// Discard all contexts and libraries, notify the [changes] stream that
+  /// these libraries are removed.
+  void discardContexts() {
+    var libraryIdList = _idToLibrary.keys.toList();
+    _changesController.add(LibraryChange._([], libraryIdList));
+
+    _contexts.clear();
+    _pathToFile.clear();
+    _uriToFile.clear();
+    _idToLibrary.clear();
+    _changedPaths.clear();
+    _scheduledFiles.clear();
+  }
+
   /// Do a single piece of work.
   ///
   /// The client should call this method until [hasWork] returns `false`.
@@ -404,6 +490,12 @@
 
       if (!file.isLibrary) return;
 
+      if (file.isSent) {
+        return;
+      } else {
+        file.isSent = true;
+      }
+
       if (file.exportedDeclarations == null) {
         new _LibraryWalker().walkLibrary(file);
         assert(file.exportedDeclarations != null);
@@ -413,6 +505,7 @@
         file.id,
         file.path,
         file.uri,
+        file.isLibraryDeprecated,
         file.exportedDeclarations,
       );
       _idToLibrary[file.id] = library;
@@ -422,13 +515,15 @@
     }
   }
 
-  /// The [analysisContext] is being disposed, it does not need declarations.
-  void removeContext(AnalysisContext analysisContext) {
-    _contexts.remove(analysisContext);
+  /// Return the context associated with the given [analysisContext], or `null`
+  /// if there is none.
+  DeclarationsContext getContext(AnalysisContext analysisContext) {
+    return _contexts[analysisContext];
+  }
 
-    _scheduledFiles.removeWhere((f) {
-      return f.context._analysisContext == analysisContext;
-    });
+  /// Return the library with the given [id], or `null` if there is none.
+  Library getLibrary(int id) {
+    return _idToLibrary[id];
   }
 
   void _addFile(DeclarationsContext context, String path) {
@@ -448,6 +543,28 @@
     }
   }
 
+  DeclarationsContext _findContextOfPath(String path) {
+    // Prefer the context in which the path is analyzed.
+    for (var context in _contexts.values) {
+      if (context._analysisContext.contextRoot.isAnalyzed(path)) {
+        context._addContextFile(path);
+        return context;
+      }
+    }
+
+    // The path must have the URI with one of the supported URI schemes.
+    for (var context in _contexts.values) {
+      var uri = context._restoreUri(path);
+      if (uri != null) {
+        if (uri.isScheme('dart') || uri.isScheme('package')) {
+          return context;
+        }
+      }
+    }
+
+    return null;
+  }
+
   _File _getFileByPath(DeclarationsContext context, String path) {
     var file = _pathToFile[path];
     if (file == null) {
@@ -488,14 +605,7 @@
   }
 
   void _performChangeFile(String path) {
-    DeclarationsContext containingContext;
-    for (var context in _contexts.values) {
-      var uri = context._restoreUri(path);
-      if (uri != null) {
-        containingContext = context;
-        break;
-      }
-    }
+    var containingContext = _findContextOfPath(path);
     if (containingContext == null) return;
 
     var file = _getFileByPath(containingContext, path);
@@ -517,16 +627,20 @@
 
     var changedLibraries = <Library>[];
     var removedLibraries = <int>[];
-    for (var library in invalidatedLibraries) {
-      if (library.exists) {
-        changedLibraries.add(Library._(
-          library.id,
-          library.path,
-          library.uri,
-          library.exportedDeclarations,
-        ));
+    for (var libraryFile in invalidatedLibraries) {
+      if (libraryFile.exists) {
+        var library = Library._(
+          libraryFile.id,
+          libraryFile.path,
+          libraryFile.uri,
+          libraryFile.isLibraryDeprecated,
+          libraryFile.exportedDeclarations,
+        );
+        _idToLibrary[library.id] = library;
+        changedLibraries.add(library);
       } else {
-        removedLibraries.add(library.id);
+        _idToLibrary.remove(libraryFile.id);
+        removedLibraries.add(libraryFile.id);
       }
     }
     _changesController.add(
@@ -554,14 +668,21 @@
   /// The URI of the library.
   final Uri uri;
 
+  /// Is `true` if the library has `@deprecated` annotation, so it probably
+  /// deprecated.  But we don't actually resolve the annotation, so it might be
+  /// a false positive.
+  final bool isDeprecated;
+
   /// All public declaration that the library declares or (re)exports.
   final List<Declaration> declarations;
 
-  Library._(this.id, this.path, this.uri, this.declarations);
+  Library._(this.id, this.path, this.uri, this.isDeprecated, this.declarations);
+
+  String get uriStr => '$uri';
 
   @override
   String toString() {
-    return '(uri: $uri, path: $path)';
+    return '(id: $id, uri: $uri, path: $path)';
   }
 }
 
@@ -578,6 +699,188 @@
   LibraryChange._(this.changed, this.removed);
 }
 
+class RelevanceTags {
+  static List<String> _forDeclaration(String uriStr, Declaration declaration) {
+    switch (declaration.kind) {
+      case DeclarationKind.CLASS:
+      case DeclarationKind.CLASS_TYPE_ALIAS:
+      case DeclarationKind.ENUM:
+      case DeclarationKind.MIXIN:
+      case DeclarationKind.FUNCTION_TYPE_ALIAS:
+        var name = declaration.name;
+        return <String>['$uriStr::$name'];
+      case DeclarationKind.ENUM_CONSTANT:
+        var name2 = declaration.name2;
+        return <String>['$uriStr::$name2'];
+      default:
+        return null;
+    }
+  }
+
+  static List<String> _forExpression(Expression expression) {
+    if (expression is BooleanLiteral) return const ['dart:core::bool'];
+    if (expression is DoubleLiteral) return const ['dart:core::double'];
+    if (expression is IntegerLiteral) return const ['dart:core::int'];
+    if (expression is StringLiteral) return const ['dart:core::String'];
+
+    if (expression is ListLiteral || expression is ListLiteral2) {
+      return const ['dart:core::List'];
+    }
+    if (expression is MapLiteral || expression is MapLiteral2) {
+      return const ['dart:core::Map'];
+    }
+    if (expression is SetLiteral || expression is SetLiteral2) {
+      return const ['dart:core::Set'];
+    }
+
+    return null;
+  }
+}
+
+class _DeclarationStorage {
+  static const fieldDocMask = 1 << 0;
+  static const fieldName2Mask = 1 << 1;
+  static const fieldParametersMask = 1 << 2;
+  static const fieldReturnTypeMask = 1 << 3;
+  static const fieldTypeParametersMask = 1 << 4;
+
+  static Declaration fromIdl(String path, idl.AvailableDeclaration d) {
+    var fieldMask = d.fieldMask;
+    var hasDoc = fieldMask & fieldDocMask != 0;
+    var hasName2 = fieldMask & fieldName2Mask != 0;
+    var hasParameters = fieldMask & fieldParametersMask != 0;
+    var hasReturnType = fieldMask & fieldReturnTypeMask != 0;
+    var hasTypeParameters = fieldMask & fieldTypeParametersMask != 0;
+
+    var kind = kindFromIdl(d.kind);
+
+    var relevanceTags = d.relevanceTags.toList();
+    if (relevanceTags.isEmpty) {
+      relevanceTags = null;
+    }
+
+    return Declaration(
+      docComplete: hasDoc ? d.docComplete : null,
+      docSummary: hasDoc ? d.docSummary : null,
+      isAbstract: d.isAbstract,
+      isConst: d.isConst,
+      isDeprecated: d.isDeprecated,
+      isFinal: d.isFinal,
+      kind: kind,
+      locationOffset: d.locationOffset,
+      locationPath: path,
+      locationStartColumn: d.locationStartColumn,
+      locationStartLine: d.locationStartLine,
+      name: d.name,
+      name2: hasName2 ? d.name2 : null,
+      parameters: hasParameters ? d.parameters : null,
+      parameterNames: hasParameters ? d.parameterNames : null,
+      parameterTypes: hasParameters ? d.parameterTypes.toList() : null,
+      relevanceTags: relevanceTags,
+      requiredParameterCount: hasParameters ? d.requiredParameterCount : null,
+      returnType: hasReturnType ? d.returnType : null,
+      typeParameters: hasTypeParameters ? d.typeParameters : null,
+    );
+  }
+
+  static DeclarationKind kindFromIdl(idl.AvailableDeclarationKind kind) {
+    switch (kind) {
+      case idl.AvailableDeclarationKind.CLASS:
+        return DeclarationKind.CLASS;
+      case idl.AvailableDeclarationKind.CLASS_TYPE_ALIAS:
+        return DeclarationKind.CLASS_TYPE_ALIAS;
+      case idl.AvailableDeclarationKind.ENUM:
+        return DeclarationKind.ENUM;
+      case idl.AvailableDeclarationKind.ENUM_CONSTANT:
+        return DeclarationKind.ENUM_CONSTANT;
+      case idl.AvailableDeclarationKind.FUNCTION:
+        return DeclarationKind.FUNCTION;
+      case idl.AvailableDeclarationKind.FUNCTION_TYPE_ALIAS:
+        return DeclarationKind.FUNCTION_TYPE_ALIAS;
+      case idl.AvailableDeclarationKind.GETTER:
+        return DeclarationKind.GETTER;
+      case idl.AvailableDeclarationKind.MIXIN:
+        return DeclarationKind.MIXIN;
+      case idl.AvailableDeclarationKind.SETTER:
+        return DeclarationKind.SETTER;
+      case idl.AvailableDeclarationKind.VARIABLE:
+        return DeclarationKind.VARIABLE;
+      default:
+        throw StateError('Unknown kind: $kind');
+    }
+  }
+
+  static idl.AvailableDeclarationKind kindToIdl(DeclarationKind kind) {
+    switch (kind) {
+      case DeclarationKind.CLASS:
+        return idl.AvailableDeclarationKind.CLASS;
+      case DeclarationKind.CLASS_TYPE_ALIAS:
+        return idl.AvailableDeclarationKind.CLASS_TYPE_ALIAS;
+      case DeclarationKind.ENUM:
+        return idl.AvailableDeclarationKind.ENUM;
+      case DeclarationKind.ENUM_CONSTANT:
+        return idl.AvailableDeclarationKind.ENUM_CONSTANT;
+      case DeclarationKind.FUNCTION:
+        return idl.AvailableDeclarationKind.FUNCTION;
+      case DeclarationKind.FUNCTION_TYPE_ALIAS:
+        return idl.AvailableDeclarationKind.FUNCTION_TYPE_ALIAS;
+      case DeclarationKind.GETTER:
+        return idl.AvailableDeclarationKind.GETTER;
+      case DeclarationKind.MIXIN:
+        return idl.AvailableDeclarationKind.MIXIN;
+      case DeclarationKind.SETTER:
+        return idl.AvailableDeclarationKind.SETTER;
+      case DeclarationKind.VARIABLE:
+        return idl.AvailableDeclarationKind.VARIABLE;
+      default:
+        throw StateError('Unknown kind: $kind');
+    }
+  }
+
+  static idl.AvailableDeclarationBuilder toIdl(Declaration d) {
+    var fieldMask = 0;
+    if (d.docComplete != null) {
+      fieldMask |= fieldDocMask;
+    }
+    if (d.name2 != null) {
+      fieldMask |= fieldName2Mask;
+    }
+    if (d.parameters != null) {
+      fieldMask |= fieldParametersMask;
+    }
+    if (d.returnType != null) {
+      fieldMask |= fieldReturnTypeMask;
+    }
+    if (d.typeParameters != null) {
+      fieldMask |= fieldTypeParametersMask;
+    }
+
+    var idlKind = kindToIdl(d.kind);
+    return idl.AvailableDeclarationBuilder(
+      docComplete: d.docComplete,
+      docSummary: d.docSummary,
+      fieldMask: fieldMask,
+      isAbstract: d.isAbstract,
+      isConst: d.isConst,
+      isDeprecated: d.isDeprecated,
+      isFinal: d.isFinal,
+      kind: idlKind,
+      locationOffset: d.locationOffset,
+      locationStartColumn: d.locationStartColumn,
+      locationStartLine: d.locationStartLine,
+      name: d.name,
+      name2: d.name2,
+      parameters: d.parameters,
+      parameterNames: d.parameterNames,
+      parameterTypes: d.parameterTypes,
+      relevanceTags: d.relevanceTags,
+      requiredParameterCount: d.requiredParameterCount,
+      returnType: d.returnType,
+      typeParameters: d.typeParameters,
+    );
+  }
+}
+
 class _Export {
   final Uri uri;
   final List<_ExportCombinator> combinators;
@@ -588,12 +891,13 @@
 
   Iterable<Declaration> filter(List<Declaration> declarations) {
     return declarations.where((d) {
+      var name = d.name2 ?? d.name;
       for (var combinator in combinators) {
         if (combinator.shows.isNotEmpty) {
-          if (!combinator.shows.contains(d.name)) return false;
+          if (!combinator.shows.contains(name)) return false;
         }
         if (combinator.hides.isNotEmpty) {
-          if (combinator.hides.contains(d.name)) return false;
+          if (combinator.hides.contains(name)) return false;
         }
       }
       return true;
@@ -610,7 +914,7 @@
 
 class _File {
   /// The version of data format, should be incremented on every format change.
-  static const int DATA_VERSION = 1;
+  static const int DATA_VERSION = 5;
 
   /// The next value for [id].
   static int _nextId = 0;
@@ -623,6 +927,7 @@
 
   bool exists = false;
   bool isLibrary = false;
+  bool isLibraryDeprecated = false;
   List<_Export> exports = [];
   List<_Part> parts = [];
 
@@ -636,8 +941,13 @@
   List<Declaration> libraryDeclarations = [];
   List<Declaration> exportedDeclarations;
 
+  /// If `true`, then this library has already been sent to the client.
+  bool isSent = false;
+
   _File(this.tracker, this.path, this.uri);
 
+  String get uriStr => uri.toString();
+
   void refresh(DeclarationsContext context) {
     var resource = tracker._resourceProvider.getFile(path);
 
@@ -718,6 +1028,7 @@
       for (var part in parts) {
         libraryDeclarations.addAll(part.file.fileDeclarations);
       }
+      _computeRelevanceTagsForLibraryDeclarations();
     }
   }
 
@@ -728,16 +1039,8 @@
     libraryDeclarations = null;
     exportedDeclarations = null;
 
-    void addDeclaration(Identifier name, DeclarationKind kind) {
-      if (!Identifier.isPrivateName(name.name)) {
-        fileDeclarations.add(Declaration(name.name, kind));
-      }
-    }
-
     for (var astDirective in unit.directives) {
-      if (astDirective is PartOfDirective) {
-        isLibrary = false;
-      } else if (astDirective is ExportDirective) {
+      if (astDirective is ExportDirective) {
         var uri = _uriFromAst(astDirective.uri);
         if (uri == null) continue;
 
@@ -757,35 +1060,191 @@
         }
 
         exports.add(_Export(uri, combinators));
+      } else if (astDirective is LibraryDirective) {
+        isLibraryDeprecated = _hasDeprecatedAnnotation(astDirective);
       } else if (astDirective is PartDirective) {
         var uri = _uriFromAst(astDirective.uri);
         if (uri == null) continue;
 
         parts.add(_Part(uri));
+      } else if (astDirective is PartOfDirective) {
+        isLibrary = false;
+      }
+    }
+
+    var lineInfo = unit.lineInfo;
+
+    String docComplete = null;
+    String docSummary = null;
+
+    void setDartDoc(AnnotatedNode node) {
+      if (node.documentationComment != null) {
+        var rawText = getCommentNodeRawText(node.documentationComment);
+        docComplete = getDartDocPlainText(rawText);
+        docSummary = getDartDocSummary(docComplete);
+      } else {
+        docComplete = null;
+        docSummary = null;
+      }
+    }
+
+    void addDeclaration({
+      bool isAbstract = false,
+      bool isConst = false,
+      bool isDeprecated = false,
+      bool isFinal = false,
+      @required DeclarationKind kind,
+      @required Identifier name,
+      Identifier name2,
+      String parameters,
+      List<String> parameterNames,
+      List<String> parameterTypes,
+      List<String> relevanceTags,
+      int requiredParameterCount,
+      String returnType,
+      String typeParameters,
+    }) {
+      if (!Identifier.isPrivateName(name.name)) {
+        var locationOffset = name.offset;
+        var lineLocation = lineInfo.getLocation(locationOffset);
+        fileDeclarations.add(Declaration(
+          docComplete: docComplete,
+          docSummary: docSummary,
+          isAbstract: isAbstract,
+          isConst: isConst,
+          isDeprecated: isDeprecated,
+          isFinal: isFinal,
+          kind: kind,
+          locationOffset: locationOffset,
+          locationPath: path,
+          name: name.name,
+          name2: name2?.name,
+          locationStartColumn: lineLocation.columnNumber,
+          locationStartLine: lineLocation.lineNumber,
+          parameters: parameters,
+          parameterNames: parameterNames,
+          parameterTypes: parameterTypes,
+          relevanceTags: relevanceTags,
+          requiredParameterCount: requiredParameterCount,
+          returnType: returnType,
+          typeParameters: typeParameters,
+        ));
       }
     }
 
     for (var node in unit.declarations) {
+      setDartDoc(node);
+      var isDeprecated = _hasDeprecatedAnnotation(node);
+
       if (node is ClassDeclaration) {
-        addDeclaration(node.name, DeclarationKind.CLASS);
+        addDeclaration(
+          isAbstract: node.isAbstract,
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.CLASS,
+          name: node.name,
+        );
       } else if (node is ClassTypeAlias) {
-        addDeclaration(node.name, DeclarationKind.CLASS_TYPE_ALIAS);
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.CLASS_TYPE_ALIAS,
+          name: node.name,
+        );
       } else if (node is EnumDeclaration) {
-        addDeclaration(node.name, DeclarationKind.ENUM);
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.ENUM,
+          name: node.name,
+        );
+        for (var constant in node.constants) {
+          setDartDoc(constant);
+          var isDeprecated = _hasDeprecatedAnnotation(constant);
+          addDeclaration(
+            isDeprecated: isDeprecated,
+            kind: DeclarationKind.ENUM_CONSTANT,
+            name: constant.name,
+            name2: node.name,
+          );
+        }
       } else if (node is FunctionDeclaration) {
-        addDeclaration(node.name, DeclarationKind.FUNCTION);
+        var functionExpression = node.functionExpression;
+        var parameters = functionExpression.parameters;
+        if (node.isGetter) {
+          addDeclaration(
+            isDeprecated: isDeprecated,
+            kind: DeclarationKind.GETTER,
+            name: node.name,
+            returnType: _getTypeAnnotationString(node.returnType),
+          );
+        } else if (node.isSetter) {
+          addDeclaration(
+            isDeprecated: isDeprecated,
+            kind: DeclarationKind.SETTER,
+            name: node.name,
+            parameters: parameters.toSource(),
+            parameterNames: _getFormalParameterNames(parameters),
+            parameterTypes: _getFormalParameterTypes(parameters),
+            requiredParameterCount:
+                _getFormalParameterRequiredCount(parameters),
+          );
+        } else {
+          addDeclaration(
+            isDeprecated: isDeprecated,
+            kind: DeclarationKind.FUNCTION,
+            name: node.name,
+            parameters: parameters.toSource(),
+            parameterNames: _getFormalParameterNames(parameters),
+            parameterTypes: _getFormalParameterTypes(parameters),
+            requiredParameterCount:
+                _getFormalParameterRequiredCount(parameters),
+            returnType: _getTypeAnnotationString(node.returnType),
+            typeParameters: functionExpression.typeParameters?.toSource(),
+          );
+        }
       } else if (node is GenericTypeAlias) {
-        addDeclaration(node.name, DeclarationKind.FUNCTION_TYPE_ALIAS);
+        var functionType = node.functionType;
+        var parameters = functionType.parameters;
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.FUNCTION_TYPE_ALIAS,
+          name: node.name,
+          parameters: parameters.toSource(),
+          parameterNames: _getFormalParameterNames(parameters),
+          parameterTypes: _getFormalParameterTypes(parameters),
+          requiredParameterCount: _getFormalParameterRequiredCount(parameters),
+          returnType: _getTypeAnnotationString(functionType.returnType),
+          typeParameters: functionType.typeParameters?.toSource(),
+        );
       } else if (node is MixinDeclaration) {
-        addDeclaration(node.name, DeclarationKind.MIXIN);
+        addDeclaration(
+          isDeprecated: isDeprecated,
+          kind: DeclarationKind.MIXIN,
+          name: node.name,
+        );
       } else if (node is TopLevelVariableDeclaration) {
+        var isConst = node.variables.isConst;
+        var isFinal = node.variables.isFinal;
         for (var variable in node.variables.variables) {
-          addDeclaration(variable.name, DeclarationKind.VARIABLE);
+          addDeclaration(
+            isConst: isConst,
+            isDeprecated: isDeprecated,
+            isFinal: isFinal,
+            kind: DeclarationKind.VARIABLE,
+            name: variable.name,
+            relevanceTags: RelevanceTags._forExpression(variable.initializer),
+            returnType: _getTypeAnnotationString(node.variables.type),
+          );
         }
       }
     }
   }
 
+  void _computeRelevanceTagsForLibraryDeclarations() {
+    for (var declaration in libraryDeclarations) {
+      declaration._relevanceTags ??=
+          RelevanceTags._forDeclaration(uriStr, declaration);
+    }
+  }
+
   /// Return the [_File] for the given [relative] URI, maybe `null`.
   _File _fileForRelativeUri(DeclarationsContext context, Uri relative) {
     var absoluteUri = resolveRelativeUri(uri, relative);
@@ -795,6 +1254,7 @@
   void _putFileDeclarationsToByteStore(String contentKey) {
     var builder = idl.AvailableFileBuilder(
       isLibrary: isLibrary,
+      isLibraryDeprecated: isLibraryDeprecated,
       exports: exports.map((e) {
         return idl.AvailableFileExportBuilder(
           uri: e.uri.toString(),
@@ -806,8 +1266,7 @@
       }).toList(),
       parts: parts.map((p) => p.uri.toString()).toList(),
       declarations: fileDeclarations.map((d) {
-        var idlKind = _kindToIdl(d.kind);
-        return idl.AvailableDeclarationBuilder(kind: idlKind, name: d.name);
+        return _DeclarationStorage.toIdl(d);
       }).toList(),
     );
     var bytes = builder.toBuffer();
@@ -818,6 +1277,7 @@
     var idlFile = idl.AvailableFile.fromBuffer(bytes);
 
     isLibrary = idlFile.isLibrary;
+    isLibraryDeprecated = idlFile.isLibraryDeprecated;
 
     exports = idlFile.exports.map((e) {
       return _Export(
@@ -834,51 +1294,66 @@
     }).toList();
 
     fileDeclarations = idlFile.declarations.map((e) {
-      var kind = _kindFromIdl(e.kind);
-      return Declaration(e.name, kind);
+      return _DeclarationStorage.fromIdl(path, e);
     }).toList();
   }
 
-  static DeclarationKind _kindFromIdl(idl.AvailableDeclarationKind kind) {
-    switch (kind) {
-      case idl.AvailableDeclarationKind.CLASS:
-        return DeclarationKind.CLASS;
-      case idl.AvailableDeclarationKind.CLASS_TYPE_ALIAS:
-        return DeclarationKind.CLASS_TYPE_ALIAS;
-      case idl.AvailableDeclarationKind.ENUM:
-        return DeclarationKind.ENUM;
-      case idl.AvailableDeclarationKind.FUNCTION:
-        return DeclarationKind.FUNCTION;
-      case idl.AvailableDeclarationKind.FUNCTION_TYPE_ALIAS:
-        return DeclarationKind.FUNCTION_TYPE_ALIAS;
-      case idl.AvailableDeclarationKind.MIXIN:
-        return DeclarationKind.MIXIN;
-      case idl.AvailableDeclarationKind.VARIABLE:
-        return DeclarationKind.VARIABLE;
-      default:
-        throw StateError('Unknown kind: $kind');
+  static List<String> _getFormalParameterNames(FormalParameterList parameters) {
+    if (parameters == null) return const <String>[];
+
+    var names = <String>[];
+    for (var parameter in parameters.parameters) {
+      var name = parameter.identifier?.name ?? '';
+      names.add(name);
     }
+    return names;
   }
 
-  static idl.AvailableDeclarationKind _kindToIdl(DeclarationKind kind) {
-    switch (kind) {
-      case DeclarationKind.CLASS:
-        return idl.AvailableDeclarationKind.CLASS;
-      case DeclarationKind.CLASS_TYPE_ALIAS:
-        return idl.AvailableDeclarationKind.CLASS_TYPE_ALIAS;
-      case DeclarationKind.ENUM:
-        return idl.AvailableDeclarationKind.ENUM;
-      case DeclarationKind.FUNCTION:
-        return idl.AvailableDeclarationKind.FUNCTION;
-      case DeclarationKind.FUNCTION_TYPE_ALIAS:
-        return idl.AvailableDeclarationKind.FUNCTION_TYPE_ALIAS;
-      case DeclarationKind.MIXIN:
-        return idl.AvailableDeclarationKind.MIXIN;
-      case DeclarationKind.VARIABLE:
-        return idl.AvailableDeclarationKind.VARIABLE;
-      default:
-        throw StateError('Unknown kind: $kind');
+  static int _getFormalParameterRequiredCount(FormalParameterList parameters) {
+    if (parameters == null) return null;
+
+    return parameters.parameters
+        .takeWhile((parameter) => parameter.isRequired)
+        .length;
+  }
+
+  static String _getFormalParameterType(FormalParameter parameter) {
+    if (parameter is DefaultFormalParameter) {
+      DefaultFormalParameter defaultFormalParameter = parameter;
+      parameter = defaultFormalParameter.parameter;
     }
+    if (parameter is SimpleFormalParameter) {
+      return _getTypeAnnotationString(parameter.type);
+    }
+    return '';
+  }
+
+  static List<String> _getFormalParameterTypes(FormalParameterList parameters) {
+    if (parameters == null) return null;
+
+    var types = <String>[];
+    for (var parameter in parameters.parameters) {
+      var type = _getFormalParameterType(parameter);
+      types.add(type);
+    }
+    return types;
+  }
+
+  static String _getTypeAnnotationString(TypeAnnotation typeAnnotation) {
+    return typeAnnotation?.toSource() ?? '';
+  }
+
+  /// Return `true` if the [node] is probably deprecated.
+  static bool _hasDeprecatedAnnotation(AnnotatedNode node) {
+    for (var annotation in node.metadata) {
+      var name = annotation.name;
+      if (name is SimpleIdentifier) {
+        if (name.name == 'deprecated' || name.name == 'Deprecated') {
+          return true;
+        }
+      }
+    }
+    return false;
   }
 
   static CompilationUnit _parse(String content) {
@@ -890,7 +1365,10 @@
     var token = scanner.tokenize();
 
     var parser = new Parser(source, errorListener, useFasta: true);
-    return parser.parseCompilationUnit(token);
+    var unit = parser.parseCompilationUnit(token);
+    unit.lineInfo = LineInfo(scanner.lineStarts);
+
+    return unit;
   }
 
   static String _readContent(File resource) {
@@ -903,7 +1381,8 @@
 
   static Uri _uriFromAst(StringLiteral astUri) {
     if (astUri is SimpleStringLiteral) {
-      var uriStr = astUri.value;
+      var uriStr = astUri.value.trim();
+      if (uriStr.isEmpty) return null;
       try {
         return Uri.parse(uriStr);
       } catch (_) {}
@@ -986,7 +1465,7 @@
   static Set<Declaration> _newDeclarationSet() {
     return HashSet<Declaration>(
       hashCode: (e) => e.name.hashCode,
-      equals: (a, b) => a.name == b.name,
+      equals: (a, b) => a.name == b.name && a.name2 == b.name2,
     );
   }
 }
diff --git a/pkg/analyzer/lib/src/summary/format.dart b/pkg/analyzer/lib/src/summary/format.dart
index 7bf2bad..7f866ae 100644
--- a/pkg/analyzer/lib/src/summary/format.dart
+++ b/pkg/analyzer/lib/src/summary/format.dart
@@ -2114,8 +2114,48 @@
 class AvailableDeclarationBuilder extends Object
     with _AvailableDeclarationMixin
     implements idl.AvailableDeclaration {
+  String _docComplete;
+  String _docSummary;
+  int _fieldMask;
   idl.AvailableDeclarationKind _kind;
+  bool _isAbstract;
+  bool _isConst;
+  bool _isDeprecated;
+  bool _isFinal;
   String _name;
+  String _name2;
+  int _locationOffset;
+  int _locationStartColumn;
+  int _locationStartLine;
+  List<String> _parameterNames;
+  String _parameters;
+  List<String> _parameterTypes;
+  int _requiredParameterCount;
+  List<String> _relevanceTags;
+  String _returnType;
+  String _typeParameters;
+
+  @override
+  String get docComplete => _docComplete ??= '';
+
+  void set docComplete(String value) {
+    this._docComplete = value;
+  }
+
+  @override
+  String get docSummary => _docSummary ??= '';
+
+  void set docSummary(String value) {
+    this._docSummary = value;
+  }
+
+  @override
+  int get fieldMask => _fieldMask ??= 0;
+
+  void set fieldMask(int value) {
+    assert(value == null || value >= 0);
+    this._fieldMask = value;
+  }
 
   @override
   idl.AvailableDeclarationKind get kind =>
@@ -2127,16 +2167,170 @@
   }
 
   @override
+  bool get isAbstract => _isAbstract ??= false;
+
+  void set isAbstract(bool value) {
+    this._isAbstract = value;
+  }
+
+  @override
+  bool get isConst => _isConst ??= false;
+
+  void set isConst(bool value) {
+    this._isConst = value;
+  }
+
+  @override
+  bool get isDeprecated => _isDeprecated ??= false;
+
+  void set isDeprecated(bool value) {
+    this._isDeprecated = value;
+  }
+
+  @override
+  bool get isFinal => _isFinal ??= false;
+
+  void set isFinal(bool value) {
+    this._isFinal = value;
+  }
+
+  @override
   String get name => _name ??= '';
 
-  /// The name of the declaration.
+  /// The first part of the declaration name, usually the only one, for example
+  /// the name of a class like `MyClass`, or a function like `myFunction`.
   void set name(String value) {
     this._name = value;
   }
 
-  AvailableDeclarationBuilder({idl.AvailableDeclarationKind kind, String name})
-      : _kind = kind,
-        _name = name;
+  @override
+  String get name2 => _name2 ??= '';
+
+  /// The second, optional, part of the declaration name.  For example enum
+  /// constants all have the same [name], but their own [name2].
+  void set name2(String value) {
+    this._name2 = value;
+  }
+
+  @override
+  int get locationOffset => _locationOffset ??= 0;
+
+  void set locationOffset(int value) {
+    assert(value == null || value >= 0);
+    this._locationOffset = value;
+  }
+
+  @override
+  int get locationStartColumn => _locationStartColumn ??= 0;
+
+  void set locationStartColumn(int value) {
+    assert(value == null || value >= 0);
+    this._locationStartColumn = value;
+  }
+
+  @override
+  int get locationStartLine => _locationStartLine ??= 0;
+
+  void set locationStartLine(int value) {
+    assert(value == null || value >= 0);
+    this._locationStartLine = value;
+  }
+
+  @override
+  List<String> get parameterNames => _parameterNames ??= <String>[];
+
+  void set parameterNames(List<String> value) {
+    this._parameterNames = value;
+  }
+
+  @override
+  String get parameters => _parameters ??= '';
+
+  void set parameters(String value) {
+    this._parameters = value;
+  }
+
+  @override
+  List<String> get parameterTypes => _parameterTypes ??= <String>[];
+
+  void set parameterTypes(List<String> value) {
+    this._parameterTypes = value;
+  }
+
+  @override
+  int get requiredParameterCount => _requiredParameterCount ??= 0;
+
+  void set requiredParameterCount(int value) {
+    assert(value == null || value >= 0);
+    this._requiredParameterCount = value;
+  }
+
+  @override
+  List<String> get relevanceTags => _relevanceTags ??= <String>[];
+
+  /// The partial list of relevance tags.  Not every declaration has one (for
+  /// example, function do not currently), and not every declaration has to
+  /// store one (for classes it can be computed when we know the library that
+  /// includes this file).
+  void set relevanceTags(List<String> value) {
+    this._relevanceTags = value;
+  }
+
+  @override
+  String get returnType => _returnType ??= '';
+
+  void set returnType(String value) {
+    this._returnType = value;
+  }
+
+  @override
+  String get typeParameters => _typeParameters ??= '';
+
+  void set typeParameters(String value) {
+    this._typeParameters = value;
+  }
+
+  AvailableDeclarationBuilder(
+      {String docComplete,
+      String docSummary,
+      int fieldMask,
+      idl.AvailableDeclarationKind kind,
+      bool isAbstract,
+      bool isConst,
+      bool isDeprecated,
+      bool isFinal,
+      String name,
+      String name2,
+      int locationOffset,
+      int locationStartColumn,
+      int locationStartLine,
+      List<String> parameterNames,
+      String parameters,
+      List<String> parameterTypes,
+      int requiredParameterCount,
+      List<String> relevanceTags,
+      String returnType,
+      String typeParameters})
+      : _docComplete = docComplete,
+        _docSummary = docSummary,
+        _fieldMask = fieldMask,
+        _kind = kind,
+        _isAbstract = isAbstract,
+        _isConst = isConst,
+        _isDeprecated = isDeprecated,
+        _isFinal = isFinal,
+        _name = name,
+        _name2 = name2,
+        _locationOffset = locationOffset,
+        _locationStartColumn = locationStartColumn,
+        _locationStartLine = locationStartLine,
+        _parameterNames = parameterNames,
+        _parameters = parameters,
+        _parameterTypes = parameterTypes,
+        _requiredParameterCount = requiredParameterCount,
+        _relevanceTags = relevanceTags,
+        _returnType = returnType,
+        _typeParameters = typeParameters;
 
   /**
    * Flush [informative] data recursively.
@@ -2147,21 +2341,153 @@
    * Accumulate non-[informative] data into [signature].
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addString(this._name ?? '');
+    signature.addString(this._docComplete ?? '');
+    signature.addString(this._docSummary ?? '');
+    signature.addInt(this._fieldMask ?? 0);
     signature.addInt(this._kind == null ? 0 : this._kind.index);
+    signature.addBool(this._isAbstract == true);
+    signature.addBool(this._isConst == true);
+    signature.addBool(this._isDeprecated == true);
+    signature.addBool(this._isFinal == true);
+    signature.addString(this._name ?? '');
+    signature.addString(this._name2 ?? '');
+    signature.addInt(this._locationOffset ?? 0);
+    signature.addInt(this._locationStartColumn ?? 0);
+    signature.addInt(this._locationStartLine ?? 0);
+    if (this._parameterNames == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._parameterNames.length);
+      for (var x in this._parameterNames) {
+        signature.addString(x);
+      }
+    }
+    signature.addString(this._parameters ?? '');
+    if (this._parameterTypes == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._parameterTypes.length);
+      for (var x in this._parameterTypes) {
+        signature.addString(x);
+      }
+    }
+    signature.addInt(this._requiredParameterCount ?? 0);
+    if (this._relevanceTags == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._relevanceTags.length);
+      for (var x in this._relevanceTags) {
+        signature.addString(x);
+      }
+    }
+    signature.addString(this._returnType ?? '');
+    signature.addString(this._typeParameters ?? '');
   }
 
   fb.Offset finish(fb.Builder fbBuilder) {
+    fb.Offset offset_docComplete;
+    fb.Offset offset_docSummary;
     fb.Offset offset_name;
+    fb.Offset offset_name2;
+    fb.Offset offset_parameterNames;
+    fb.Offset offset_parameters;
+    fb.Offset offset_parameterTypes;
+    fb.Offset offset_relevanceTags;
+    fb.Offset offset_returnType;
+    fb.Offset offset_typeParameters;
+    if (_docComplete != null) {
+      offset_docComplete = fbBuilder.writeString(_docComplete);
+    }
+    if (_docSummary != null) {
+      offset_docSummary = fbBuilder.writeString(_docSummary);
+    }
     if (_name != null) {
       offset_name = fbBuilder.writeString(_name);
     }
+    if (_name2 != null) {
+      offset_name2 = fbBuilder.writeString(_name2);
+    }
+    if (!(_parameterNames == null || _parameterNames.isEmpty)) {
+      offset_parameterNames = fbBuilder.writeList(
+          _parameterNames.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (_parameters != null) {
+      offset_parameters = fbBuilder.writeString(_parameters);
+    }
+    if (!(_parameterTypes == null || _parameterTypes.isEmpty)) {
+      offset_parameterTypes = fbBuilder.writeList(
+          _parameterTypes.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (!(_relevanceTags == null || _relevanceTags.isEmpty)) {
+      offset_relevanceTags = fbBuilder.writeList(
+          _relevanceTags.map((b) => fbBuilder.writeString(b)).toList());
+    }
+    if (_returnType != null) {
+      offset_returnType = fbBuilder.writeString(_returnType);
+    }
+    if (_typeParameters != null) {
+      offset_typeParameters = fbBuilder.writeString(_typeParameters);
+    }
     fbBuilder.startTable();
+    if (offset_docComplete != null) {
+      fbBuilder.addOffset(0, offset_docComplete);
+    }
+    if (offset_docSummary != null) {
+      fbBuilder.addOffset(1, offset_docSummary);
+    }
+    if (_fieldMask != null && _fieldMask != 0) {
+      fbBuilder.addUint32(2, _fieldMask);
+    }
     if (_kind != null && _kind != idl.AvailableDeclarationKind.CLASS) {
-      fbBuilder.addUint8(1, _kind.index);
+      fbBuilder.addUint8(3, _kind.index);
+    }
+    if (_isAbstract == true) {
+      fbBuilder.addBool(4, true);
+    }
+    if (_isConst == true) {
+      fbBuilder.addBool(5, true);
+    }
+    if (_isDeprecated == true) {
+      fbBuilder.addBool(6, true);
+    }
+    if (_isFinal == true) {
+      fbBuilder.addBool(7, true);
     }
     if (offset_name != null) {
-      fbBuilder.addOffset(0, offset_name);
+      fbBuilder.addOffset(8, offset_name);
+    }
+    if (offset_name2 != null) {
+      fbBuilder.addOffset(9, offset_name2);
+    }
+    if (_locationOffset != null && _locationOffset != 0) {
+      fbBuilder.addUint32(10, _locationOffset);
+    }
+    if (_locationStartColumn != null && _locationStartColumn != 0) {
+      fbBuilder.addUint32(11, _locationStartColumn);
+    }
+    if (_locationStartLine != null && _locationStartLine != 0) {
+      fbBuilder.addUint32(12, _locationStartLine);
+    }
+    if (offset_parameterNames != null) {
+      fbBuilder.addOffset(13, offset_parameterNames);
+    }
+    if (offset_parameters != null) {
+      fbBuilder.addOffset(14, offset_parameters);
+    }
+    if (offset_parameterTypes != null) {
+      fbBuilder.addOffset(15, offset_parameterTypes);
+    }
+    if (_requiredParameterCount != null && _requiredParameterCount != 0) {
+      fbBuilder.addUint32(16, _requiredParameterCount);
+    }
+    if (offset_relevanceTags != null) {
+      fbBuilder.addOffset(17, offset_relevanceTags);
+    }
+    if (offset_returnType != null) {
+      fbBuilder.addOffset(18, offset_returnType);
+    }
+    if (offset_typeParameters != null) {
+      fbBuilder.addOffset(19, offset_typeParameters);
     }
     return fbBuilder.endTable();
   }
@@ -2184,37 +2510,210 @@
 
   _AvailableDeclarationImpl(this._bc, this._bcOffset);
 
+  String _docComplete;
+  String _docSummary;
+  int _fieldMask;
   idl.AvailableDeclarationKind _kind;
+  bool _isAbstract;
+  bool _isConst;
+  bool _isDeprecated;
+  bool _isFinal;
   String _name;
+  String _name2;
+  int _locationOffset;
+  int _locationStartColumn;
+  int _locationStartLine;
+  List<String> _parameterNames;
+  String _parameters;
+  List<String> _parameterTypes;
+  int _requiredParameterCount;
+  List<String> _relevanceTags;
+  String _returnType;
+  String _typeParameters;
+
+  @override
+  String get docComplete {
+    _docComplete ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    return _docComplete;
+  }
+
+  @override
+  String get docSummary {
+    _docSummary ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 1, '');
+    return _docSummary;
+  }
+
+  @override
+  int get fieldMask {
+    _fieldMask ??= const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 2, 0);
+    return _fieldMask;
+  }
 
   @override
   idl.AvailableDeclarationKind get kind {
     _kind ??= const _AvailableDeclarationKindReader()
-        .vTableGet(_bc, _bcOffset, 1, idl.AvailableDeclarationKind.CLASS);
+        .vTableGet(_bc, _bcOffset, 3, idl.AvailableDeclarationKind.CLASS);
     return _kind;
   }
 
   @override
+  bool get isAbstract {
+    _isAbstract ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 4, false);
+    return _isAbstract;
+  }
+
+  @override
+  bool get isConst {
+    _isConst ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 5, false);
+    return _isConst;
+  }
+
+  @override
+  bool get isDeprecated {
+    _isDeprecated ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 6, false);
+    return _isDeprecated;
+  }
+
+  @override
+  bool get isFinal {
+    _isFinal ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 7, false);
+    return _isFinal;
+  }
+
+  @override
   String get name {
-    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 0, '');
+    _name ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 8, '');
     return _name;
   }
+
+  @override
+  String get name2 {
+    _name2 ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 9, '');
+    return _name2;
+  }
+
+  @override
+  int get locationOffset {
+    _locationOffset ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 10, 0);
+    return _locationOffset;
+  }
+
+  @override
+  int get locationStartColumn {
+    _locationStartColumn ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 11, 0);
+    return _locationStartColumn;
+  }
+
+  @override
+  int get locationStartLine {
+    _locationStartLine ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 12, 0);
+    return _locationStartLine;
+  }
+
+  @override
+  List<String> get parameterNames {
+    _parameterNames ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 13, const <String>[]);
+    return _parameterNames;
+  }
+
+  @override
+  String get parameters {
+    _parameters ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 14, '');
+    return _parameters;
+  }
+
+  @override
+  List<String> get parameterTypes {
+    _parameterTypes ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 15, const <String>[]);
+    return _parameterTypes;
+  }
+
+  @override
+  int get requiredParameterCount {
+    _requiredParameterCount ??=
+        const fb.Uint32Reader().vTableGet(_bc, _bcOffset, 16, 0);
+    return _requiredParameterCount;
+  }
+
+  @override
+  List<String> get relevanceTags {
+    _relevanceTags ??= const fb.ListReader<String>(const fb.StringReader())
+        .vTableGet(_bc, _bcOffset, 17, const <String>[]);
+    return _relevanceTags;
+  }
+
+  @override
+  String get returnType {
+    _returnType ??= const fb.StringReader().vTableGet(_bc, _bcOffset, 18, '');
+    return _returnType;
+  }
+
+  @override
+  String get typeParameters {
+    _typeParameters ??=
+        const fb.StringReader().vTableGet(_bc, _bcOffset, 19, '');
+    return _typeParameters;
+  }
 }
 
 abstract class _AvailableDeclarationMixin implements idl.AvailableDeclaration {
   @override
   Map<String, Object> toJson() {
     Map<String, Object> _result = <String, Object>{};
+    if (docComplete != '') _result["docComplete"] = docComplete;
+    if (docSummary != '') _result["docSummary"] = docSummary;
+    if (fieldMask != 0) _result["fieldMask"] = fieldMask;
     if (kind != idl.AvailableDeclarationKind.CLASS)
       _result["kind"] = kind.toString().split('.')[1];
+    if (isAbstract != false) _result["isAbstract"] = isAbstract;
+    if (isConst != false) _result["isConst"] = isConst;
+    if (isDeprecated != false) _result["isDeprecated"] = isDeprecated;
+    if (isFinal != false) _result["isFinal"] = isFinal;
     if (name != '') _result["name"] = name;
+    if (name2 != '') _result["name2"] = name2;
+    if (locationOffset != 0) _result["locationOffset"] = locationOffset;
+    if (locationStartColumn != 0)
+      _result["locationStartColumn"] = locationStartColumn;
+    if (locationStartLine != 0)
+      _result["locationStartLine"] = locationStartLine;
+    if (parameterNames.isNotEmpty) _result["parameterNames"] = parameterNames;
+    if (parameters != '') _result["parameters"] = parameters;
+    if (parameterTypes.isNotEmpty) _result["parameterTypes"] = parameterTypes;
+    if (requiredParameterCount != 0)
+      _result["requiredParameterCount"] = requiredParameterCount;
+    if (relevanceTags.isNotEmpty) _result["relevanceTags"] = relevanceTags;
+    if (returnType != '') _result["returnType"] = returnType;
+    if (typeParameters != '') _result["typeParameters"] = typeParameters;
     return _result;
   }
 
   @override
   Map<String, Object> toMap() => {
+        "docComplete": docComplete,
+        "docSummary": docSummary,
+        "fieldMask": fieldMask,
         "kind": kind,
+        "isAbstract": isAbstract,
+        "isConst": isConst,
+        "isDeprecated": isDeprecated,
+        "isFinal": isFinal,
         "name": name,
+        "name2": name2,
+        "locationOffset": locationOffset,
+        "locationStartColumn": locationStartColumn,
+        "locationStartLine": locationStartLine,
+        "parameterNames": parameterNames,
+        "parameters": parameters,
+        "parameterTypes": parameterTypes,
+        "requiredParameterCount": requiredParameterCount,
+        "relevanceTags": relevanceTags,
+        "returnType": returnType,
+        "typeParameters": typeParameters,
       };
 
   @override
@@ -2227,6 +2726,7 @@
   List<AvailableDeclarationBuilder> _declarations;
   List<AvailableFileExportBuilder> _exports;
   bool _isLibrary;
+  bool _isLibraryDeprecated;
   List<String> _parts;
 
   @override
@@ -2256,6 +2756,14 @@
   }
 
   @override
+  bool get isLibraryDeprecated => _isLibraryDeprecated ??= false;
+
+  /// Is `true` if this file is a library, and it is deprecated.
+  void set isLibraryDeprecated(bool value) {
+    this._isLibraryDeprecated = value;
+  }
+
+  @override
   List<String> get parts => _parts ??= <String>[];
 
   /// URIs of `part` directives.
@@ -2267,10 +2775,12 @@
       {List<AvailableDeclarationBuilder> declarations,
       List<AvailableFileExportBuilder> exports,
       bool isLibrary,
+      bool isLibraryDeprecated,
       List<String> parts})
       : _declarations = declarations,
         _exports = exports,
         _isLibrary = isLibrary,
+        _isLibraryDeprecated = isLibraryDeprecated,
         _parts = parts;
 
   /**
@@ -2285,7 +2795,14 @@
    * Accumulate non-[informative] data into [signature].
    */
   void collectApiSignature(api_sig.ApiSignature signature) {
-    signature.addBool(this._isLibrary == true);
+    if (this._declarations == null) {
+      signature.addInt(0);
+    } else {
+      signature.addInt(this._declarations.length);
+      for (var x in this._declarations) {
+        x?.collectApiSignature(signature);
+      }
+    }
     if (this._exports == null) {
       signature.addInt(0);
     } else {
@@ -2294,6 +2811,8 @@
         x?.collectApiSignature(signature);
       }
     }
+    signature.addBool(this._isLibrary == true);
+    signature.addBool(this._isLibraryDeprecated == true);
     if (this._parts == null) {
       signature.addInt(0);
     } else {
@@ -2302,14 +2821,6 @@
         signature.addString(x);
       }
     }
-    if (this._declarations == null) {
-      signature.addInt(0);
-    } else {
-      signature.addInt(this._declarations.length);
-      for (var x in this._declarations) {
-        x?.collectApiSignature(signature);
-      }
-    }
   }
 
   List<int> toBuffer() {
@@ -2335,16 +2846,19 @@
     }
     fbBuilder.startTable();
     if (offset_declarations != null) {
-      fbBuilder.addOffset(3, offset_declarations);
+      fbBuilder.addOffset(0, offset_declarations);
     }
     if (offset_exports != null) {
       fbBuilder.addOffset(1, offset_exports);
     }
     if (_isLibrary == true) {
-      fbBuilder.addBool(0, true);
+      fbBuilder.addBool(2, true);
+    }
+    if (_isLibraryDeprecated == true) {
+      fbBuilder.addBool(3, true);
     }
     if (offset_parts != null) {
-      fbBuilder.addOffset(2, offset_parts);
+      fbBuilder.addOffset(4, offset_parts);
     }
     return fbBuilder.endTable();
   }
@@ -2374,13 +2888,14 @@
   List<idl.AvailableDeclaration> _declarations;
   List<idl.AvailableFileExport> _exports;
   bool _isLibrary;
+  bool _isLibraryDeprecated;
   List<String> _parts;
 
   @override
   List<idl.AvailableDeclaration> get declarations {
     _declarations ??= const fb.ListReader<idl.AvailableDeclaration>(
             const _AvailableDeclarationReader())
-        .vTableGet(_bc, _bcOffset, 3, const <idl.AvailableDeclaration>[]);
+        .vTableGet(_bc, _bcOffset, 0, const <idl.AvailableDeclaration>[]);
     return _declarations;
   }
 
@@ -2394,14 +2909,21 @@
 
   @override
   bool get isLibrary {
-    _isLibrary ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 0, false);
+    _isLibrary ??= const fb.BoolReader().vTableGet(_bc, _bcOffset, 2, false);
     return _isLibrary;
   }
 
   @override
+  bool get isLibraryDeprecated {
+    _isLibraryDeprecated ??=
+        const fb.BoolReader().vTableGet(_bc, _bcOffset, 3, false);
+    return _isLibraryDeprecated;
+  }
+
+  @override
   List<String> get parts {
     _parts ??= const fb.ListReader<String>(const fb.StringReader())
-        .vTableGet(_bc, _bcOffset, 2, const <String>[]);
+        .vTableGet(_bc, _bcOffset, 4, const <String>[]);
     return _parts;
   }
 }
@@ -2416,6 +2938,8 @@
     if (exports.isNotEmpty)
       _result["exports"] = exports.map((_value) => _value.toJson()).toList();
     if (isLibrary != false) _result["isLibrary"] = isLibrary;
+    if (isLibraryDeprecated != false)
+      _result["isLibraryDeprecated"] = isLibraryDeprecated;
     if (parts.isNotEmpty) _result["parts"] = parts;
     return _result;
   }
@@ -2425,6 +2949,7 @@
         "declarations": declarations,
         "exports": exports,
         "isLibrary": isLibrary,
+        "isLibraryDeprecated": isLibraryDeprecated,
         "parts": parts,
       };
 
diff --git a/pkg/analyzer/lib/src/summary/format.fbs b/pkg/analyzer/lib/src/summary/format.fbs
index 25a04e6..640b861 100644
--- a/pkg/analyzer/lib/src/summary/format.fbs
+++ b/pkg/analyzer/lib/src/summary/format.fbs
@@ -14,12 +14,18 @@
 
   ENUM,
 
+  ENUM_CONSTANT,
+
   FUNCTION,
 
   FUNCTION_TYPE_ALIAS,
 
+  GETTER,
+
   MIXIN,
 
+  SETTER,
+
   VARIABLE
 }
 
@@ -864,26 +870,72 @@
 
 /// Information about a single declaration.
 table AvailableDeclaration {
-  /// The kind of the declaration.
-  kind:AvailableDeclarationKind (id: 1);
+  docComplete:string (id: 0);
 
-  /// The name of the declaration.
-  name:string (id: 0);
+  docSummary:string (id: 1);
+
+  fieldMask:uint (id: 2);
+
+  /// The kind of the declaration.
+  kind:AvailableDeclarationKind (id: 3);
+
+  isAbstract:bool (id: 4);
+
+  isConst:bool (id: 5);
+
+  isDeprecated:bool (id: 6);
+
+  isFinal:bool (id: 7);
+
+  /// The first part of the declaration name, usually the only one, for example
+  /// the name of a class like `MyClass`, or a function like `myFunction`.
+  name:string (id: 8);
+
+  /// The second, optional, part of the declaration name.  For example enum
+  /// constants all have the same [name], but their own [name2].
+  name2:string (id: 9);
+
+  locationOffset:uint (id: 10);
+
+  locationStartColumn:uint (id: 11);
+
+  locationStartLine:uint (id: 12);
+
+  parameterNames:[string] (id: 13);
+
+  parameters:string (id: 14);
+
+  parameterTypes:[string] (id: 15);
+
+  requiredParameterCount:uint (id: 16);
+
+  /// The partial list of relevance tags.  Not every declaration has one (for
+  /// example, function do not currently), and not every declaration has to
+  /// store one (for classes it can be computed when we know the library that
+  /// includes this file).
+  relevanceTags:[string] (id: 17);
+
+  returnType:string (id: 18);
+
+  typeParameters:string (id: 19);
 }
 
 /// Information about an available, even if not yet imported file.
 table AvailableFile {
   /// Declarations of the file.
-  declarations:[AvailableDeclaration] (id: 3);
+  declarations:[AvailableDeclaration] (id: 0);
 
   /// Exports directives of the file.
   exports:[AvailableFileExport] (id: 1);
 
   /// Is `true` if this file is a library.
-  isLibrary:bool (id: 0);
+  isLibrary:bool (id: 2);
+
+  /// Is `true` if this file is a library, and it is deprecated.
+  isLibraryDeprecated:bool (id: 3);
 
   /// URIs of `part` directives.
-  parts:[string] (id: 2);
+  parts:[string] (id: 4);
 }
 
 /// Information about an export directive.
diff --git a/pkg/analyzer/lib/src/summary/idl.dart b/pkg/analyzer/lib/src/summary/idl.dart
index e997afb..6e3a1d8 100644
--- a/pkg/analyzer/lib/src/summary/idl.dart
+++ b/pkg/analyzer/lib/src/summary/idl.dart
@@ -285,13 +285,74 @@
 
 /// Information about a single declaration.
 abstract class AvailableDeclaration extends base.SummaryClass {
-  /// The kind of the declaration.
+  @Id(0)
+  String get docComplete;
+
   @Id(1)
+  String get docSummary;
+
+  @Id(2)
+  int get fieldMask;
+
+  /// The kind of the declaration.
+  @Id(3)
   AvailableDeclarationKind get kind;
 
-  /// The name of the declaration.
-  @Id(0)
+  @Id(4)
+  bool get isAbstract;
+
+  @Id(5)
+  bool get isConst;
+
+  @Id(6)
+  bool get isDeprecated;
+
+  @Id(7)
+  bool get isFinal;
+
+  /// The first part of the declaration name, usually the only one, for example
+  /// the name of a class like `MyClass`, or a function like `myFunction`.
+  @Id(8)
   String get name;
+
+  /// The second, optional, part of the declaration name.  For example enum
+  /// constants all have the same [name], but their own [name2].
+  @Id(9)
+  String get name2;
+
+  @Id(10)
+  int get locationOffset;
+
+  @Id(11)
+  int get locationStartColumn;
+
+  @Id(12)
+  int get locationStartLine;
+
+  @Id(13)
+  List<String> get parameterNames;
+
+  @Id(14)
+  String get parameters;
+
+  @Id(15)
+  List<String> get parameterTypes;
+
+  @Id(16)
+  int get requiredParameterCount;
+
+  /// The partial list of relevance tags.  Not every declaration has one (for
+  /// example, function do not currently), and not every declaration has to
+  /// store one (for classes it can be computed when we know the library that
+  /// includes this file).
+  @Id(17)
+  List<String> get relevanceTags;
+
+  @Id(18)
+  String get returnType;
+
+  @Id(19)
+  String get typeParameters;
 }
 
 /// Enum of declaration kinds in available files.
@@ -299,9 +360,12 @@
   CLASS,
   CLASS_TYPE_ALIAS,
   ENUM,
+  ENUM_CONSTANT,
   FUNCTION,
   FUNCTION_TYPE_ALIAS,
+  GETTER,
   MIXIN,
+  SETTER,
   VARIABLE
 }
 
@@ -312,7 +376,7 @@
       generated.readAvailableFile(buffer);
 
   /// Declarations of the file.
-  @Id(3)
+  @Id(0)
   List<AvailableDeclaration> get declarations;
 
   /// Exports directives of the file.
@@ -320,11 +384,15 @@
   List<AvailableFileExport> get exports;
 
   /// Is `true` if this file is a library.
-  @Id(0)
+  @Id(2)
   bool get isLibrary;
 
+  /// Is `true` if this file is a library, and it is deprecated.
+  @Id(3)
+  bool get isLibraryDeprecated;
+
   /// URIs of `part` directives.
-  @Id(2)
+  @Id(4)
   List<String> get parts;
 }
 
diff --git a/pkg/analyzer/lib/src/task/dart.dart b/pkg/analyzer/lib/src/task/dart.dart
index 81198ab..50e3992 100644
--- a/pkg/analyzer/lib/src/task/dart.dart
+++ b/pkg/analyzer/lib/src/task/dart.dart
@@ -2867,7 +2867,9 @@
 
     unit.accept(new BestPracticesVerifier(
         errorReporter, typeProvider, libraryElement,
-        typeSystem: typeSystem, resourceProvider: resourceProvider));
+        typeSystem: typeSystem,
+        resourceProvider: resourceProvider,
+        analysisOptions: context.analysisOptions));
     unit.accept(new OverrideVerifier(
       inheritanceManager2,
       libraryElement,
@@ -3432,7 +3434,6 @@
         visitor.prepareToResolveMembersInClass(
             resolutionContext.enclosingClassDeclaration);
       }
-      visitor.initForIncrementalResolution();
       initializer.accept(visitor);
       DartType newType = initializer.staticType;
       if (newType == null || newType.isBottom || newType.isDartCoreNull) {
diff --git a/pkg/analyzer/lib/src/task/strong/checker.dart b/pkg/analyzer/lib/src/task/strong/checker.dart
index c3f3647..da18f90 100644
--- a/pkg/analyzer/lib/src/task/strong/checker.dart
+++ b/pkg/analyzer/lib/src/task/strong/checker.dart
@@ -164,6 +164,22 @@
   void checkBoolean(Expression expr) =>
       checkAssignment(expr, typeProvider.boolType);
 
+  void checkCollectionElement(
+      CollectionElement element, DartType expectedType) {
+    if (element is ForElement) {
+      checkCollectionElement(element.body, expectedType);
+    } else if (element is IfElement) {
+      checkCollectionElement(element.thenElement, expectedType);
+      checkCollectionElement(element.elseElement, expectedType);
+    } else if (element is Expression) {
+      checkAssignment(element, expectedType);
+    } else if (element is SpreadElement) {
+      DartType iterableType =
+          typeProvider.iterableType.instantiate([expectedType]);
+      checkAssignment(element.expression, iterableType);
+    }
+  }
+
   void checkForCast(Expression expr, DartType type) {
     if (expr is ParenthesizedExpression) {
       checkForCast(expr.expression, type);
@@ -172,6 +188,23 @@
     }
   }
 
+  void checkMapElement(CollectionElement element, DartType expectedKeyType,
+      DartType expectedValueType) {
+    if (element is ForElement) {
+      checkMapElement(element.body, expectedKeyType, expectedValueType);
+    } else if (element is IfElement) {
+      checkMapElement(element.thenElement, expectedKeyType, expectedValueType);
+      checkMapElement(element.elseElement, expectedKeyType, expectedValueType);
+    } else if (element is MapLiteralEntry) {
+      checkAssignment(element.key, expectedKeyType);
+      checkAssignment(element.value, expectedValueType);
+    } else if (element is SpreadElement) {
+      DartType mapType = typeProvider.mapType
+          .instantiate([expectedKeyType, expectedValueType]);
+      checkAssignment(element.expression, mapType);
+    }
+  }
+
   DartType getAnnotatedType(TypeAnnotation type) {
     return type?.type ?? DynamicTypeImpl.instance;
   }
@@ -344,6 +377,18 @@
   }
 
   @override
+  void visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) {
+    _visitForEachParts(node, node.loopVariable?.identifier);
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitForEachPartsWithIdentifier(ForEachPartsWithIdentifier node) {
+    _visitForEachParts(node, node.identifier);
+    node.visitChildren(this);
+  }
+
+  @override
   void visitForEachStatement(ForEachStatement node) {
     var loopVariable = node.identifier ?? node.loopVariable?.identifier;
 
@@ -384,6 +429,22 @@
   }
 
   @override
+  void visitForPartsWithDeclarations(ForPartsWithDeclarations node) {
+    if (node.condition != null) {
+      checkBoolean(node.condition);
+    }
+    node.visitChildren(this);
+  }
+
+  @override
+  void visitForPartsWithExpression(ForPartsWithExpression node) {
+    if (node.condition != null) {
+      checkBoolean(node.condition);
+    }
+    node.visitChildren(this);
+  }
+
+  @override
   void visitForStatement(ForStatement node) {
     if (node.condition != null) {
       checkBoolean(node.condition);
@@ -464,6 +525,30 @@
   }
 
   @override
+  void visitListLiteral2(ListLiteral2 node) {
+    DartType type = DynamicTypeImpl.instance;
+    if (node.typeArguments != null) {
+      NodeList<TypeAnnotation> targs = node.typeArguments.arguments;
+      if (targs.length > 0) {
+        type = targs[0].type;
+      }
+    } else {
+      DartType staticType = node.staticType;
+      if (staticType is InterfaceType) {
+        List<DartType> targs = staticType.typeArguments;
+        if (targs != null && targs.length > 0) {
+          type = targs[0];
+        }
+      }
+    }
+    NodeList<CollectionElement> elements = node.elements;
+    for (int i = 0; i < elements.length; i++) {
+      checkCollectionElement(elements[i], type);
+    }
+    super.visitListLiteral2(node);
+  }
+
+  @override
   void visitMapLiteral(MapLiteral node) {
     DartType ktype = DynamicTypeImpl.instance;
     DartType vtype = DynamicTypeImpl.instance;
@@ -499,6 +584,39 @@
   }
 
   @override
+  void visitMapLiteral2(MapLiteral2 node) {
+    DartType keyType = DynamicTypeImpl.instance;
+    DartType valueType = DynamicTypeImpl.instance;
+    if (node.typeArguments != null) {
+      NodeList<TypeAnnotation> typeArguments = node.typeArguments.arguments;
+      if (typeArguments.length > 0) {
+        keyType = typeArguments[0].type;
+      }
+      if (typeArguments.length > 1) {
+        valueType = typeArguments[1].type;
+      }
+    } else {
+      DartType staticType = node.staticType;
+      if (staticType is InterfaceType) {
+        List<DartType> typeArguments = staticType.typeArguments;
+        if (typeArguments != null) {
+          if (typeArguments.length > 0) {
+            keyType = typeArguments[0];
+          }
+          if (typeArguments.length > 1) {
+            valueType = typeArguments[1];
+          }
+        }
+      }
+    }
+    NodeList<CollectionElement> entries = node.entries;
+    for (int i = 0; i < entries.length; i++) {
+      checkMapElement(entries[i], keyType, valueType);
+    }
+    super.visitMapLiteral2(node);
+  }
+
+  @override
   visitMethodInvocation(MethodInvocation node) {
     var target = node.realTarget;
     var element = node.methodName.staticElement;
@@ -603,6 +721,30 @@
   }
 
   @override
+  void visitSetLiteral2(SetLiteral2 node) {
+    DartType type = DynamicTypeImpl.instance;
+    if (node.typeArguments != null) {
+      NodeList<TypeAnnotation> targs = node.typeArguments.arguments;
+      if (targs.length > 0) {
+        type = targs[0].type;
+      }
+    } else {
+      DartType staticType = node.staticType;
+      if (staticType is InterfaceType) {
+        List<DartType> typeArguments = staticType.typeArguments;
+        if (typeArguments != null && typeArguments.length > 0) {
+          type = typeArguments[0];
+        }
+      }
+    }
+    NodeList<CollectionElement> elements = node.elements;
+    for (int i = 0; i < elements.length; i++) {
+      checkCollectionElement(elements[i], type);
+    }
+    super.visitSetLiteral2(node);
+  }
+
+  @override
   void visitSuperConstructorInvocation(SuperConstructorInvocation node) {
     var element = node.staticElement;
     if (element != null) {
@@ -1236,6 +1378,51 @@
   void _validateTopLevelInitializer(String name, Expression n) {
     n.accept(new _TopLevelInitializerValidator(this, name));
   }
+
+  void _visitForEachParts(ForEachParts node, SimpleIdentifier loopVariable) {
+    // Safely handle malformed statements.
+    if (loopVariable == null) {
+      return;
+    }
+    Token awaitKeyword;
+    AstNode parent = node.parent;
+    if (parent is ForStatement2) {
+      awaitKeyword = parent.awaitKeyword;
+    } else if (parent is ForElement) {
+      awaitKeyword = parent.awaitKeyword;
+    } else {
+      throw new StateError(
+          'Unexpected parent of ForEachParts: ${parent.runtimeType}');
+    }
+    // Find the element type of the sequence.
+    var sequenceInterface = awaitKeyword != null
+        ? typeProvider.streamType
+        : typeProvider.iterableType;
+    var iterableType = _getExpressionType(node.iterable);
+    var elementType =
+        rules.mostSpecificTypeArgument(iterableType, sequenceInterface);
+
+    // If the sequence is not an Iterable (or Stream for await for) but is a
+    // supertype of it, do an implicit downcast to Iterable<dynamic>. Then
+    // we'll do a separate cast of the dynamic element to the variable's type.
+    if (elementType == null) {
+      var sequenceType =
+          sequenceInterface.instantiate([DynamicTypeImpl.instance]);
+
+      if (rules.isSubtypeOf(sequenceType, iterableType)) {
+        _recordImplicitCast(node.iterable, sequenceType, from: iterableType);
+        elementType = DynamicTypeImpl.instance;
+      }
+    }
+    // If the sequence doesn't implement the interface at all, [ErrorVerifier]
+    // will report the error, so ignore it here.
+    if (elementType != null) {
+      // Insert a cast from the sequence's element type to the loop variable's
+      // if needed.
+      _checkImplicitCast(loopVariable, _getExpressionType(loopVariable),
+          from: elementType);
+    }
+  }
 }
 
 /// Checks for overriding declarations of fields and methods. This is used to
@@ -1726,6 +1913,13 @@
   }
 
   @override
+  visitListLiteral2(ListLiteral2 node) {
+    if (node.typeArguments == null) {
+      super.visitListLiteral2(node);
+    }
+  }
+
+  @override
   visitMapLiteral(MapLiteral node) {
     if (node.typeArguments == null) {
       super.visitMapLiteral(node);
@@ -1733,6 +1927,13 @@
   }
 
   @override
+  visitMapLiteral2(MapLiteral2 node) {
+    if (node.typeArguments == null) {
+      super.visitMapLiteral2(node);
+    }
+  }
+
+  @override
   visitMethodInvocation(MethodInvocation node) {
     node.target?.accept(this);
     var method = node.methodName.staticElement;
@@ -1769,6 +1970,20 @@
   }
 
   @override
+  visitSetLiteral(SetLiteral node) {
+    if (node.typeArguments == null) {
+      super.visitSetLiteral(node);
+    }
+  }
+
+  @override
+  visitSetLiteral2(SetLiteral2 node) {
+    if (node.typeArguments == null) {
+      super.visitSetLiteral2(node);
+    }
+  }
+
+  @override
   visitSimpleIdentifier(SimpleIdentifier node) {
     validateIdentifierElement(node, node.staticElement);
   }
diff --git a/pkg/analyzer/test/src/dart/resolution/find_element.dart b/pkg/analyzer/lib/src/test_utilities/find_element.dart
similarity index 74%
rename from pkg/analyzer/test/src/dart/resolution/find_element.dart
rename to pkg/analyzer/lib/src/test_utilities/find_element.dart
index d0ac7bf..86b3e1f 100644
--- a/pkg/analyzer/test/src/dart/resolution/find_element.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_element.dart
@@ -5,9 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
-import 'package:test/test.dart';
-
-import 'function_ast_visitor.dart';
+import 'package:analyzer/src/test_utilities/function_ast_visitor.dart';
 
 /// Helper for finding elements declared in the resolved [unit].
 class FindElement {
@@ -23,7 +21,21 @@
         return class_;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
+  }
+
+  ClassElement classOrMixin(String name) {
+    for (var class_ in unitElement.types) {
+      if (class_.name == name) {
+        return class_;
+      }
+    }
+    for (var mixin in unitElement.mixins) {
+      if (mixin.name == name) {
+        return mixin;
+      }
+    }
+    throw StateError('Not found: $name');
   }
 
   ConstructorElement constructor(String name, {String of}) {
@@ -34,7 +46,7 @@
         for (var constructor in class_.constructors) {
           if (constructor.name == name) {
             if (result != null) {
-              fail('Not unique: $name');
+              throw StateError('Not unique: $name');
             }
             result = constructor;
           }
@@ -44,7 +56,7 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ClassElement enum_(String name) {
@@ -53,7 +65,7 @@
         return enum_;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ExportElement export(String targetUri) {
@@ -63,7 +75,7 @@
       var exportedUri = export.exportedLibrary.source.uri.toString();
       if (exportedUri == targetUri) {
         if (result != null) {
-          fail('Not unique: $targetUri');
+          throw StateError('Not unique: $targetUri');
         }
         result = export;
       }
@@ -72,7 +84,7 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $targetUri');
+    throw StateError('Not found: $targetUri');
   }
 
   FieldElement field(String name, {String of}) {
@@ -82,7 +94,7 @@
       for (var field in fields) {
         if (field.name == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = field;
         }
@@ -113,7 +125,11 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
+  }
+
+  FieldFormalParameterElement fieldFormalParameter(String name) {
+    return parameter(name) as FieldFormalParameterElement;
   }
 
   FunctionElement function(String name) {
@@ -122,7 +138,7 @@
         return function;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   GenericTypeAliasElement genericTypeAlias(String name) {
@@ -131,7 +147,7 @@
         return element;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   PropertyAccessorElement getter(String name, {String of}) {
@@ -141,7 +157,7 @@
       for (var accessor in accessors) {
         if (accessor.isGetter && accessor.displayName == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = accessor;
         }
@@ -172,7 +188,7 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ImportElement import(String targetUri) {
@@ -182,7 +198,7 @@
       var importedUri = import.importedLibrary.source.uri.toString();
       if (importedUri == targetUri) {
         if (importElement != null) {
-          fail('Not unique: $targetUri');
+          throw StateError('Not unique: $targetUri');
         }
         importElement = import;
       }
@@ -191,7 +207,12 @@
     if (importElement != null) {
       return importElement;
     }
-    fail('Not found: $targetUri');
+    throw StateError('Not found: $targetUri');
+  }
+
+  ImportFindElement importFind(String targetUri) {
+    var import = this.import(targetUri);
+    return ImportFindElement(import);
   }
 
   InterfaceType interfaceType(String name) {
@@ -206,7 +227,7 @@
         var element = node.functionDeclaration.declaredElement;
         if (element is FunctionElement) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = element;
         }
@@ -214,7 +235,7 @@
     ));
 
     if (result == null) {
-      fail('Not found: $name');
+      throw StateError('Not found: $name');
     }
     return result;
   }
@@ -227,7 +248,7 @@
         var element = node.declaredElement;
         if (element is LocalVariableElement && element.name == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = element;
         }
@@ -235,7 +256,7 @@
     ));
 
     if (result == null) {
-      fail('Not found: $name');
+      throw StateError('Not found: $name');
     }
     return result;
   }
@@ -247,7 +268,7 @@
       for (var method in methods) {
         if (method.name == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = method;
         }
@@ -271,7 +292,7 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ClassElement mixin(String name) {
@@ -280,7 +301,7 @@
         return mixin;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ParameterElement parameter(String name) {
@@ -290,7 +311,7 @@
       for (var parameter in parameters) {
         if (parameter.name == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = parameter;
         }
@@ -316,12 +337,15 @@
       for (var method in class_.methods) {
         findIn(method.parameters);
       }
+      for (var accessor in class_.accessors) {
+        findIn(accessor.parameters);
+      }
     }
 
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   PrefixElement prefix(String name) {
@@ -331,7 +355,7 @@
         return prefix;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   PropertyAccessorElement setter(String name, {String of}) {
@@ -341,7 +365,7 @@
       for (var accessor in accessors) {
         if (accessor.isSetter && accessor.displayName == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = accessor;
         }
@@ -365,7 +389,7 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   FunctionElement topFunction(String name) {
@@ -374,7 +398,7 @@
         return function;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   PropertyAccessorElement topGet(String name) {
@@ -391,7 +415,7 @@
         return variable;
       }
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   TypeParameterElement typeParameter(String name) {
@@ -401,7 +425,7 @@
       for (var typeParameter in typeParameters) {
         if (typeParameter.name == name) {
           if (result != null) {
-            fail('Not unique: $name');
+            throw StateError('Not unique: $name');
           }
           result = typeParameter;
         }
@@ -426,10 +450,52 @@
     if (result != null) {
       return result;
     }
-    fail('Not found: $name');
+    throw StateError('Not found: $name');
   }
 
   ConstructorElement unnamedConstructor(String name) {
     return class_(name).unnamedConstructor;
   }
 }
+
+/// Helper for searching imported elements.
+class ImportFindElement {
+  final ImportElement import;
+
+  ImportFindElement(this.import);
+
+  CompilationUnitElement get definingUnit {
+    return importedLibrary.definingCompilationUnit;
+  }
+
+  LibraryElement get importedLibrary => import.importedLibrary;
+
+  PrefixElement get prefix => import.prefix;
+
+  ClassElement class_(String name) {
+    for (var class_ in definingUnit.types) {
+      if (class_.name == name) {
+        return class_;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
+
+  FunctionElement topFunction(String name) {
+    for (var function in definingUnit.functions) {
+      if (function.name == name) {
+        return function;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
+
+  PropertyAccessorElement topGetter(String name) {
+    for (var accessor in definingUnit.accessors) {
+      if (accessor.name == name && accessor.isGetter) {
+        return accessor;
+      }
+    }
+    throw StateError('Not found: $name');
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolution/find_node.dart b/pkg/analyzer/lib/src/test_utilities/find_node.dart
similarity index 60%
rename from pkg/analyzer/test/src/dart/resolution/find_node.dart
rename to pkg/analyzer/lib/src/test_utilities/find_node.dart
index 574553d..9bf696b 100644
--- a/pkg/analyzer/test/src/dart/resolution/find_node.dart
+++ b/pkg/analyzer/lib/src/test_utilities/find_node.dart
@@ -4,7 +4,6 @@
 
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
-import 'package:test/test.dart';
 
 class FindNode {
   final String content;
@@ -20,10 +19,26 @@
     return _node(search, (n) => n is Annotation);
   }
 
+  AstNode any(String search) {
+    return _node(search, (n) => true);
+  }
+
   AssignmentExpression assignment(String search) {
     return _node(search, (n) => n is AssignmentExpression);
   }
 
+  BinaryExpression binary(String search) {
+    return _node(search, (n) => n is BinaryExpression);
+  }
+
+  Block block(String search) {
+    return _node(search, (n) => n is Block);
+  }
+
+  BreakStatement breakStatement(String search) {
+    return _node(search, (n) => n is BreakStatement);
+  }
+
   CascadeExpression cascade(String search) {
     return _node(search, (n) => n is CascadeExpression);
   }
@@ -36,10 +51,30 @@
     return _node(search, (n) => n is CommentReference);
   }
 
+  ConditionalExpression conditionalExpression(String search) {
+    return _node(search, (n) => n is ConditionalExpression);
+  }
+
   ConstructorDeclaration constructor(String search) {
     return _node(search, (n) => n is ConstructorDeclaration);
   }
 
+  ConstructorFieldInitializer constructorFieldInitializer(String search) {
+    return _node(search, (n) => n is ConstructorFieldInitializer);
+  }
+
+  ContinueStatement continueStatement(String search) {
+    return _node(search, (n) => n is ContinueStatement);
+  }
+
+  DefaultFormalParameter defaultParameter(String search) {
+    return _node(search, (n) => n is DefaultFormalParameter);
+  }
+
+  DoStatement doStatement(String search) {
+    return _node(search, (n) => n is DoStatement);
+  }
+
   ExportDirective export(String search) {
     return _node(search, (n) => n is ExportDirective);
   }
@@ -48,18 +83,38 @@
     return _node(search, (n) => n is Expression);
   }
 
+  ExpressionStatement expressionStatement(String search) {
+    return _node(search, (n) => n is ExpressionStatement);
+  }
+
   FieldFormalParameter fieldFormalParameter(String search) {
     return _node(search, (n) => n is FieldFormalParameter);
   }
 
+  ForEachStatement forEachStatement(String search) {
+    return _node(search, (n) => n is ForEachStatement);
+  }
+
+  ForStatement forStatement(String search) {
+    return _node(search, (n) => n is ForStatement);
+  }
+
   FunctionBody functionBody(String search) {
     return _node(search, (n) => n is FunctionBody);
   }
 
+  FunctionDeclaration functionDeclaration(String search) {
+    return _node(search, (n) => n is FunctionDeclaration);
+  }
+
   FunctionExpression functionExpression(String search) {
     return _node(search, (n) => n is FunctionExpression);
   }
 
+  FunctionTypeAlias functionTypeAlias(String search) {
+    return _node(search, (n) => n is FunctionTypeAlias);
+  }
+
   GenericFunctionType genericFunctionType(String search) {
     return _node(search, (n) => n is GenericFunctionType);
   }
@@ -68,10 +123,18 @@
     return _node(search, (n) => n is ImportDirective);
   }
 
+  IndexExpression index(String search) {
+    return _node(search, (n) => n is IndexExpression);
+  }
+
   InstanceCreationExpression instanceCreation(String search) {
     return _node(search, (n) => n is InstanceCreationExpression);
   }
 
+  LibraryDirective library(String search) {
+    return _node(search, (n) => n is LibraryDirective);
+  }
+
   ListLiteral listLiteral(String search) {
     return _node(search, (n) => n is ListLiteral);
   }
@@ -124,6 +187,10 @@
     return _node(search, (n) => n is RethrowExpression);
   }
 
+  SetLiteral setLiteral(String search) {
+    return _node(search, (n) => n is SetLiteral);
+  }
+
   SimpleIdentifier simple(String search) {
     return _node(search, (_) => true);
   }
@@ -144,6 +211,10 @@
     return _node(search, (n) => n is SuperExpression);
   }
 
+  SwitchStatement switchStatement(String search) {
+    return _node(search, (n) => n is SwitchStatement);
+  }
+
   ThisExpression this_(String search) {
     return _node(search, (n) => n is ThisExpression);
   }
@@ -152,6 +223,27 @@
     return _node(search, (n) => n is ThrowExpression);
   }
 
+  TopLevelVariableDeclaration topLevelVariableDeclaration(String search) {
+    return _node(search, (n) => n is TopLevelVariableDeclaration);
+  }
+
+  VariableDeclaration topVariableDeclarationByName(String name) {
+    for (var declaration in unit.declarations) {
+      if (declaration is TopLevelVariableDeclaration) {
+        for (var variable in declaration.variables.variables) {
+          if (variable.name.name == name) {
+            return variable;
+          }
+        }
+      }
+    }
+    throw StateError('$name');
+  }
+
+  TypeAnnotation typeAnnotation(String search) {
+    return _node(search, (n) => n is TypeAnnotation);
+  }
+
   TypeName typeName(String search) {
     return _node(search, (n) => n is TypeName);
   }
@@ -164,18 +256,30 @@
     return _node(search, (n) => n is VariableDeclaration);
   }
 
+  WhileStatement whileStatement(String search) {
+    return _node(search, (n) => n is WhileStatement);
+  }
+
   AstNode _node(String search, bool Function(AstNode) predicate) {
     var index = content.indexOf(search);
     if (content.indexOf(search, index + 1) != -1) {
-      fail('The pattern |$search| is not unique in:\n$content');
+      throw new StateError('The pattern |$search| is not unique in:\n$content');
     }
-    expect(index, greaterThanOrEqualTo(0));
+    if (index < 0) {
+      throw new StateError('The pattern |$search| is not found in:\n$content');
+    }
 
     var node = new NodeLocator2(index).searchWithin(unit);
-    expect(node, isNotNull);
+    if (node == null) {
+      throw new StateError(
+          'The pattern |$search| had no corresponding node in:\n$content');
+    }
 
     var result = node.thisOrAncestorMatching(predicate);
-    expect(result, isNotNull);
+    if (result == null) {
+      throw new StateError(
+          'The node for |$search| had no matching ancestor in:\n$content');
+    }
     return result;
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart b/pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
similarity index 100%
rename from pkg/analyzer/test/src/dart/resolution/function_ast_visitor.dart
rename to pkg/analyzer/lib/src/test_utilities/function_ast_visitor.dart
diff --git a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
index 7420ee9..94f6ed8 100644
--- a/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
+++ b/pkg/analyzer/lib/src/test_utilities/mock_sdk.dart
@@ -105,7 +105,12 @@
 library dart.collection;
 
 abstract class HashMap<K, V> implements Map<K, V> {}
-abstract class LinkedHashMap<K, V> implements Map<K, V> {}
+abstract class LinkedHashMap<K, V> implements Map<K, V> {
+  factory LinkedHashMap(
+      {bool equals(K key1, K key2),
+      int hashCode(K key),
+      bool isValidKey(potentialKey)}) => null;
+}
 abstract class HashSet<E> implements Set<E> {}
 abstract class LinkedHashSet<E> implements Set<E> {}
 ''');
@@ -235,6 +240,8 @@
 
   List<E> toList();
 
+  Set<E> toSet();
+
   Iterable<E> where(bool test(E element));
 }
 
@@ -259,6 +266,9 @@
 }
 
 class Map<K, V> {
+  factory Map() => {}
+  factory Map.fromIterable(Iterable iterable,
+      {K key(element), V value(element)}) => {}
   Iterable<K> get keys => null;
   int get length => 0;
   Iterable<V> get values => null;
@@ -312,6 +322,10 @@
 }
 
 abstract class Set<E> implements Iterable<E> {
+  factory Set() => null;
+  factory Set.identity() => null;
+  factory Set.from(Iterable elements) => null;
+  factory Set.of(Iterable<E> elements) => null;
   Set<R> cast<R>();
 }
 
diff --git a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
index 4eba2df..8f20457 100644
--- a/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
+++ b/pkg/analyzer/lib/src/test_utilities/resource_provider_mixin.dart
@@ -2,8 +2,6 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:io' hide File;
-
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/memory_file_system.dart';
 import 'package:analyzer/src/dart/analysis/context_locator.dart';
@@ -16,26 +14,6 @@
 mixin ResourceProviderMixin {
   MemoryResourceProvider resourceProvider = new MemoryResourceProvider();
 
-  /// Convert the given [path] to be a valid import uri for this provider's path context.
-  /// The URI will use forward slashes on all platforms and absolute paths on Windows
-  /// will be formatted as /X:/path/file.dart
-  String convertAbsolutePathToUri(String path) {
-    path = convertPath(path);
-
-    // On Windows, absolute import paths are not quite the same as a normal fs path.
-    // C:\test.dart must be imported as one of:
-    //   import "file:///C:/test.dart"
-    //   import "/C:/test.dart"
-    if (Platform.isWindows && resourceProvider.pathContext.isAbsolute(path)) {
-      // The .path on a file Uri is in the form "/C:/test.dart"
-      path = new Uri.file(path).path;
-    }
-
-    // Since this returns a URI for imports, it should always be forward slashes
-    // even for relative paths on Windows.
-    return path.replaceAll(r'\', '/');
-  }
-
   String convertPath(String path) => resourceProvider.convertPath(path);
 
   void deleteFile(String path) {
@@ -103,4 +81,8 @@
     path = convertPath(path);
     return resourceProvider.pathContext.toUri(path);
   }
+
+  String toUriStr(String path) {
+    return toUri(path).toString();
+  }
 }
diff --git a/pkg/analyzer/lib/src/util/comment.dart b/pkg/analyzer/lib/src/util/comment.dart
new file mode 100644
index 0000000..8e61774
--- /dev/null
+++ b/pkg/analyzer/lib/src/util/comment.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.
+
+import 'package:analyzer/dart/ast/ast.dart';
+
+/// Return the raw text of the given comment node.
+String getCommentNodeRawText(Comment node) {
+  if (node == null) return null;
+
+  return node.tokens
+      .map((token) => token.lexeme)
+      .join('\n')
+      .replaceAll('\r\n', '\n');
+}
+
+/// Return the plain text from the given DartDoc [rawText], without delimiters.
+String getDartDocPlainText(String rawText) {
+  if (rawText == null) return null;
+
+  // Remove /** */.
+  if (rawText.startsWith('/**')) {
+    rawText = rawText.substring(3);
+  }
+  if (rawText.endsWith('*/')) {
+    rawText = rawText.substring(0, rawText.length - 2);
+  }
+  rawText = rawText.trim();
+
+  // Remove leading '* ' and '/// '.
+  var result = new StringBuffer();
+  var lines = rawText.split('\n');
+  for (var line in lines) {
+    line = line.trim();
+    if (line.startsWith('*')) {
+      line = line.substring(1);
+      if (line.startsWith(' ')) {
+        line = line.substring(1);
+      }
+    } else if (line.startsWith('///')) {
+      line = line.substring(3);
+      if (line.startsWith(' ')) {
+        line = line.substring(1);
+      }
+    }
+    if (result.isNotEmpty) {
+      result.write('\n');
+    }
+    result.write(line);
+  }
+
+  return result.toString();
+}
+
+/// Return the DartDoc summary, i.e. the portion before the first empty line.
+String getDartDocSummary(String completeText) {
+  if (completeText == null) return null;
+
+  var result = new StringBuffer();
+  var lines = completeText.split('\n');
+  for (var line in lines) {
+    if (result.isNotEmpty) {
+      if (line.isEmpty) {
+        return result.toString();
+      }
+      result.write('\n');
+    }
+    result.write(line);
+  }
+  return result.toString();
+}
diff --git a/pkg/analyzer/pubspec.yaml b/pkg/analyzer/pubspec.yaml
index 053be37..38d06b9 100644
--- a/pkg/analyzer/pubspec.yaml
+++ b/pkg/analyzer/pubspec.yaml
@@ -1,5 +1,5 @@
 name: analyzer
-version: 0.35.0-dev
+version: 0.35.1
 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.9
+  front_end: 0.1.11
   glob: ^1.0.3
   html: '>=0.12.0 <1.14.0'
-  kernel: 0.3.9
+  kernel: 0.3.11
   meta: ^1.0.2
   package_config: '>=0.1.5 <2.0.0'
   path: '>=0.9.0 <2.0.0'
@@ -24,5 +24,7 @@
   watcher: '>=0.9.6 <0.10.0'
   yaml: ^2.1.2
 dev_dependencies:
+  analysis_tool:
+    path: ../analysis_tool
   test: ^1.0.0
   test_reflective_loader: ^0.1.8
diff --git a/pkg/analyzer/test/dart/element/builder_test.dart b/pkg/analyzer/test/dart/element/builder_test.dart
index b476b61..ca9248f 100644
--- a/pkg/analyzer/test/dart/element/builder_test.dart
+++ b/pkg/analyzer/test/dart/element/builder_test.dart
@@ -23,6 +23,7 @@
 
 import '../../generated/parser_test.dart';
 import '../../generated/test_support.dart';
+import '../../util/element_type_matchers.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -878,7 +879,7 @@
     FunctionElement initializerElement = fieldElement.initializer;
     expect(initializerElement, isNotNull);
     expect(initializerElement.hasImplicitReturnType, isTrue);
-    expect(initializer.declaredElement, new TypeMatcher<FunctionElement>());
+    expect(initializer.declaredElement, isFunctionElement);
     LocalVariableElement variableElement = variable.declaredElement;
     expect(variableElement.hasImplicitType, isTrue);
     expect(variableElement.isConst, isFalse);
diff --git a/pkg/analyzer/test/error/error_reporter_test.dart b/pkg/analyzer/test/error/error_reporter_test.dart
new file mode 100644
index 0000000..eeb2468
--- /dev/null
+++ b/pkg/analyzer/test/error/error_reporter_test.dart
@@ -0,0 +1,218 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:source_span/source_span.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../generated/test_support.dart';
+import '../src/dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ErrorReporterTest);
+  });
+}
+
+@reflectiveTest
+class ErrorReporterTest extends DriverResolutionTest {
+  var listener = GatheringErrorListener();
+
+  test_creation() async {
+    var source = TestSource();
+    expect(ErrorReporter(listener, source), isNotNull);
+  }
+
+  test_reportErrorForElement_named() async {
+    addTestFile('class A {}');
+    await resolveTestFile();
+
+    var element = findElement.class_('A');
+    var reporter = ErrorReporter(listener, element.source);
+    reporter.reportErrorForElement(
+      StaticWarningCode.CAST_TO_NON_TYPE,
+      element,
+      ['A'],
+    );
+
+    var error = listener.errors[0];
+    expect(error.offset, element.nameOffset);
+  }
+
+  test_reportErrorForElement_unnamed() async {
+    addTestFile(r'''
+import 'dart:async';
+import 'dart:math';
+''');
+    await resolveTestFile();
+
+    var element = findElement.import('dart:math');
+
+    var reporter = ErrorReporter(listener, element.source);
+    reporter.reportErrorForElement(
+      StaticWarningCode.CAST_TO_NON_TYPE,
+      element,
+      ['A'],
+    );
+
+    var error = listener.errors[0];
+    expect(error.offset, element.nameOffset);
+  }
+
+  test_reportErrorForSpan() async {
+    var source = TestSource();
+    var reporter = ErrorReporter(listener, source);
+
+    var text = '''
+foo: bar
+zap: baz
+''';
+
+    var offset = text.indexOf('baz');
+    var length = 'baz'.length;
+
+    var span = SourceSpanBase(
+      SourceLocation(offset),
+      SourceLocation(offset + length),
+      'baz',
+    );
+
+    reporter.reportErrorForSpan(
+      AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE,
+      span,
+      ['test', 'zip', 'zap'],
+    );
+    expect(listener.errors, hasLength(1));
+    expect(listener.errors.first.offset, offset);
+    expect(listener.errors.first.length, length);
+  }
+
+  test_reportTypeErrorForNode_differentNames() async {
+    newFile('/test/lib/a.dart', content: 'class A {}');
+    newFile('/test/lib/b.dart', content: 'class B {}');
+    addTestFile(r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+
+main() {
+  x;
+}
+''');
+    await resolveTestFile();
+
+    var aImport = findElement.importFind('package:test/a.dart');
+    var bImport = findElement.importFind('package:test/b.dart');
+
+    var firstType = aImport.class_('A').type;
+    var secondType = bImport.class_('B').type;
+
+    var reporter = ErrorReporter(listener, firstType.element.source);
+
+    reporter.reportTypeErrorForNode(
+      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+      findNode.simple('x'),
+      [firstType, secondType],
+    );
+
+    var error = listener.errors[0];
+    expect(error.message, isNot(contains('(')));
+  }
+
+  test_reportTypeErrorForNode_sameName() async {
+    newFile('/test/lib/a.dart', content: 'class A {}');
+    newFile('/test/lib/b.dart', content: 'class A {}');
+    addTestFile(r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+
+main() {
+  x;
+}
+''');
+    await resolveTestFile();
+
+    var aImport = findElement.importFind('package:test/a.dart');
+    var bImport = findElement.importFind('package:test/b.dart');
+
+    var firstType = aImport.class_('A').type;
+    var secondType = bImport.class_('A').type;
+
+    var reporter = ErrorReporter(listener, firstType.element.source);
+    reporter.reportTypeErrorForNode(
+      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+      findNode.simple('x'),
+      [firstType, secondType],
+    );
+
+    var error = listener.errors[0];
+    expect(error.message, contains('('));
+  }
+
+  test_reportTypeErrorForNode_sameName_functionType() async {
+    newFile('/test/lib/a.dart', content: 'class A{}');
+    newFile('/test/lib/b.dart', content: 'class A{}');
+    addTestFile(r'''
+import 'a.dart' as a;
+import 'b.dart' as b;
+
+a.A Function() fa;
+b.A Function() fb;
+
+main() {
+  x;
+}
+''');
+    await resolveTestFile();
+
+    var fa = findNode.topLevelVariableDeclaration('fa');
+    var fb = findNode.topLevelVariableDeclaration('fb');
+
+    var source = result.unit.declaredElement.source;
+    var reporter = ErrorReporter(listener, source);
+    reporter.reportTypeErrorForNode(
+      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+      findNode.simple('x'),
+      [fa.variables.type.type, fb.variables.type.type],
+    );
+
+    var error = listener.errors[0];
+    expect(error.message, contains('a.dart'));
+    expect(error.message, contains('b.dart'));
+  }
+
+  test_reportTypeErrorForNode_sameName_nested() async {
+    newFile('/test/lib/a.dart', content: 'class A{}');
+    newFile('/test/lib/b.dart', content: 'class A{}');
+    addTestFile(r'''
+import 'a.dart' as a;
+import 'b.dart' as b;
+
+B<a.A> ba;
+B<b.A> bb;
+class B<T> {}
+
+main() {
+  x;
+}
+''');
+    await resolveTestFile();
+
+    var ba = findNode.topLevelVariableDeclaration('ba');
+    var bb = findNode.topLevelVariableDeclaration('bb');
+
+    var source = result.unit.declaredElement.source;
+    var reporter = ErrorReporter(listener, source);
+    reporter.reportTypeErrorForNode(
+      StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
+      findNode.simple('x'),
+      [ba.variables.type.type, bb.variables.type.type],
+    );
+
+    var error = listener.errors[0];
+    expect(error.message, contains('a.dart'));
+    expect(error.message, contains('b.dart'));
+  }
+}
diff --git a/pkg/analyzer/test/error/test_all.dart b/pkg/analyzer/test/error/test_all.dart
index bf82c24..aeadc12 100644
--- a/pkg/analyzer/test/error/test_all.dart
+++ b/pkg/analyzer/test/error/test_all.dart
@@ -4,10 +4,12 @@
 
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import 'error_reporter_test.dart' as error_reporter;
 import 'error_test.dart' as error_test;
 
 main() {
   defineReflectiveSuite(() {
+    error_reporter.main();
     error_test.main();
   }, name: 'error');
 }
diff --git a/pkg/analyzer/test/generated/all_the_rest_test.dart b/pkg/analyzer/test/generated/all_the_rest_test.dart
index a759002..a860794 100644
--- a/pkg/analyzer/test/generated/all_the_rest_test.dart
+++ b/pkg/analyzer/test/generated/all_the_rest_test.dart
@@ -2,44 +2,30 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'dart:async';
-
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/token.dart';
 import 'package:analyzer/dart/element/element.dart';
-import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/file_system/physical_file_system.dart';
-import 'package:analyzer/src/dart/ast/utilities.dart' hide ConstantEvaluator;
 import 'package:analyzer/src/dart/element/builder.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/dart/sdk/sdk.dart' hide SdkLibrariesReader;
-import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/java_engine_io.dart';
 import 'package:analyzer/src/generated/java_io.dart';
 import 'package:analyzer/src/generated/resolver.dart';
 import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/sdk_io.dart'; // ignore: deprecated_member_use
+import 'package:analyzer/src/generated/sdk_io.dart'; // ignore: deprecated_member_use_from_same_package
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/element_factory.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/generated/testing/token_factory.dart';
 import 'package:analyzer/src/generated/utilities_dart.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-import 'package:path/path.dart' as path;
-import 'package:source_span/source_span.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../util/element_type_matchers.dart';
-import 'parser_test.dart';
-import 'resolver_test_case.dart';
 import 'test_support.dart';
 
 main() {
@@ -48,13 +34,8 @@
     // ignore: deprecated_member_use_from_same_package
     defineReflectiveTests(CustomUriResolverTest);
     defineReflectiveTests(DartUriResolverTest);
-    defineReflectiveTests(ElementLocatorTest);
     defineReflectiveTests(EnumMemberBuilderTest);
-    defineReflectiveTests(ErrorReporterTest);
-    defineReflectiveTests(ErrorReporterTest2);
     defineReflectiveTests(ErrorSeverityTest);
-    defineReflectiveTests(ExitDetectorTest);
-    defineReflectiveTests(ExitDetectorTest2);
     defineReflectiveTests(FileBasedSourceTest);
     defineReflectiveTests(ResolveRelativeUriTest);
     // ignore: deprecated_member_use_from_same_package
@@ -165,385 +146,6 @@
   }
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
-@reflectiveTest
-class ElementLocatorTest extends ResolverTestCase {
-  void fail_locate_Identifier_partOfDirective() {
-    // Can't resolve the library element without the library declaration.
-    //    AstNode id = findNodeIn("foo", "part of foo.bar;");
-    //    Element element = ElementLocator.locate(id);
-    //    assertInstanceOf(LibraryElement.class, element);
-    fail("Test this case");
-  }
-
-  @override
-  void reset() {
-    AnalysisOptionsImpl analysisOptions = new AnalysisOptionsImpl();
-    analysisOptions.hint = false;
-    resetWith(options: analysisOptions);
-  }
-
-  test_locate_AssignmentExpression() async {
-    AstNode id = await _findNodeIn("+=", r'''
-int x = 0;
-void main() {
-  x += 1;
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_BinaryExpression() async {
-    AstNode id = await _findNodeIn("+", "var x = 3 + 4;");
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_ClassDeclaration() async {
-    AstNode id = await _findNodeIn("class", "class A { }");
-    Element element = ElementLocator.locate(id);
-    expect(element, isClassElement);
-  }
-
-  test_locate_CompilationUnit() async {
-    CompilationUnit cu = await _resolveContents("// only comment");
-    expect(cu.declaredElement, isNotNull);
-    Element element = ElementLocator.locate(cu);
-    expect(element, same(cu.declaredElement));
-  }
-
-  test_locate_ConstructorDeclaration() async {
-    AstNode id = await _findNodeIndexedIn("bar", 0, r'''
-class A {
-  A.bar() {}
-}''');
-    ConstructorDeclaration declaration =
-        id.thisOrAncestorOfType<ConstructorDeclaration>();
-    Element element = ElementLocator.locate(declaration);
-    expect(element, isConstructorElement);
-  }
-
-  test_locate_ExportDirective() async {
-    AstNode id = await _findNodeIn("export", "export 'dart:core';");
-    Element element = ElementLocator.locate(id);
-    expect(element, isExportElement);
-  }
-
-  test_locate_FunctionDeclaration() async {
-    AstNode id = await _findNodeIn("f", "int f() => 3;");
-    FunctionDeclaration declaration =
-        id.thisOrAncestorOfType<FunctionDeclaration>();
-    Element element = ElementLocator.locate(declaration);
-    expect(element, isFunctionElement);
-  }
-
-  test_locate_Identifier_annotationClass_namedConstructor_forSimpleFormalParameter() async {
-    AstNode id = await _findNodeIndexedIn("Class", 2, r'''
-class Class {
-  const Class.name();
-}
-void main(@Class.name() parameter) {
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isClassElement);
-  }
-
-  test_locate_Identifier_annotationClass_unnamedConstructor_forSimpleFormalParameter() async {
-    AstNode id = await _findNodeIndexedIn("Class", 2, r'''
-class Class {
-  const Class();
-}
-void main(@Class() parameter) {
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isConstructorElement);
-  }
-
-  test_locate_Identifier_className() async {
-    AstNode id = await _findNodeIn("A", "class A { }");
-    Element element = ElementLocator.locate(id);
-    expect(element, isClassElement);
-  }
-
-  test_locate_Identifier_constructor_named() async {
-    AstNode id = await _findNodeIndexedIn("bar", 0, r'''
-class A {
-  A.bar() {}
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isConstructorElement);
-  }
-
-  test_locate_Identifier_constructor_unnamed() async {
-    AstNode id = await _findNodeIndexedIn("A", 1, r'''
-class A {
-  A() {}
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isConstructorElement);
-  }
-
-  test_locate_Identifier_fieldName() async {
-    AstNode id = await _findNodeIn("x", "class A { var x; }");
-    Element element = ElementLocator.locate(id);
-    expect(element, isFieldElement);
-  }
-
-  test_locate_Identifier_libraryDirective() async {
-    AstNode id = await _findNodeIn("foo", "library foo.bar;");
-    Element element = ElementLocator.locate(id);
-    expect(element, isLibraryElement);
-  }
-
-  test_locate_Identifier_propertyAccess() async {
-    AstNode id = await _findNodeIn("length", r'''
-void main() {
- int x = 'foo'.length;
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isPropertyAccessorElement);
-  }
-
-  test_locate_ImportDirective() async {
-    AstNode id = await _findNodeIn("import", "import 'dart:core';");
-    Element element = ElementLocator.locate(id);
-    expect(element, isImportElement);
-  }
-
-  test_locate_IndexExpression() async {
-    AstNode id = await _findNodeIndexedIn("\\[", 1, r'''
-void main() {
-  List x = [1, 2];
-  var y = x[0];
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_InstanceCreationExpression() async {
-    AstNode node = await _findNodeIndexedIn("A(", 0, r'''
-class A {}
-void main() {
- new A();
-}''');
-    Element element = ElementLocator.locate(node);
-    expect(element, isConstructorElement);
-  }
-
-  test_locate_InstanceCreationExpression_type_prefixedIdentifier() async {
-    // prepare: new pref.A()
-    SimpleIdentifier identifier = AstTestFactory.identifier3("A");
-    PrefixedIdentifier prefixedIdentifier =
-        AstTestFactory.identifier4("pref", identifier);
-    InstanceCreationExpression creation =
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.NEW, AstTestFactory.typeName3(prefixedIdentifier));
-    // set ClassElement
-    ClassElement classElement = ElementFactory.classElement2("A");
-    identifier.staticElement = classElement;
-    // set ConstructorElement
-    ConstructorElement constructorElement =
-        ElementFactory.constructorElement2(classElement, null);
-    creation.constructorName.staticElement = constructorElement;
-    // verify that "A" is resolved to ConstructorElement
-    Element element = ElementLocator.locate(identifier);
-    expect(element, same(classElement));
-  }
-
-  test_locate_InstanceCreationExpression_type_simpleIdentifier() async {
-    // prepare: new A()
-    SimpleIdentifier identifier = AstTestFactory.identifier3("A");
-    InstanceCreationExpression creation =
-        AstTestFactory.instanceCreationExpression2(
-            Keyword.NEW, AstTestFactory.typeName3(identifier));
-    // set ClassElement
-    ClassElement classElement = ElementFactory.classElement2("A");
-    identifier.staticElement = classElement;
-    // set ConstructorElement
-    ConstructorElement constructorElement =
-        ElementFactory.constructorElement2(classElement, null);
-    creation.constructorName.staticElement = constructorElement;
-    // verify that "A" is resolved to ConstructorElement
-    Element element = ElementLocator.locate(identifier);
-    expect(element, same(classElement));
-  }
-
-  test_locate_LibraryDirective() async {
-    AstNode id = await _findNodeIn("library", "library foo;");
-    Element element = ElementLocator.locate(id);
-    expect(element, isLibraryElement);
-  }
-
-  test_locate_MethodDeclaration() async {
-    AstNode id = await _findNodeIn("m", r'''
-class A {
-  void m() {}
-}''');
-    MethodDeclaration declaration =
-        id.thisOrAncestorOfType<MethodDeclaration>();
-    Element element = ElementLocator.locate(declaration);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_MethodInvocation_method() async {
-    AstNode id = await _findNodeIndexedIn("bar", 1, r'''
-class A {
-  int bar() => 42;
-}
-void main() {
- var f = new A().bar();
-}''');
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_MethodInvocation_topLevel() async {
-    String code = r'''
-foo(x) {}
-void main() {
- foo(0);
-}''';
-    CompilationUnit cu = await _resolveContents(code);
-    int offset = code.indexOf('foo(0)');
-    AstNode node = new NodeLocator(offset).searchWithin(cu);
-    MethodInvocation invocation = node.thisOrAncestorOfType<MethodInvocation>();
-    Element element = ElementLocator.locate(invocation);
-    expect(element, isFunctionElement);
-  }
-
-  test_locate_PartOfDirective() async {
-    Source librarySource = addNamedSource('/lib.dart', '''
-library my.lib;
-part 'part.dart';
-''');
-    Source unitSource = addNamedSource('/part.dart', '''
-part of my.lib;
-''');
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit2(unitSource, librarySource);
-    PartOfDirective partOf = unit.directives.first;
-    Element element = ElementLocator.locate(partOf);
-    expect(element, isLibraryElement);
-  }
-
-  test_locate_PostfixExpression() async {
-    AstNode id = await _findNodeIn("++", "int addOne(int x) => x++;");
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_PrefixedIdentifier() async {
-    AstNode id = await _findNodeIn("int", r'''
-import 'dart:core' as core;
-core.int value;''');
-    PrefixedIdentifier identifier =
-        id.thisOrAncestorOfType<PrefixedIdentifier>();
-    Element element = ElementLocator.locate(identifier);
-    expect(element, isClassElement);
-  }
-
-  test_locate_PrefixExpression() async {
-    AstNode id = await _findNodeIn("++", "int addOne(int x) => ++x;");
-    Element element = ElementLocator.locate(id);
-    expect(element, isMethodElement);
-  }
-
-  test_locate_StringLiteral_exportUri() async {
-    addNamedSource("/foo.dart", "library foo;");
-    AstNode id = await _findNodeIn("'foo.dart'", "export 'foo.dart';");
-    Element element = ElementLocator.locate(id);
-    expect(element, isLibraryElement);
-  }
-
-  test_locate_StringLiteral_expression() async {
-    AstNode id = await _findNodeIn("abc", "var x = 'abc';");
-    Element element = ElementLocator.locate(id);
-    expect(element, isNull);
-  }
-
-  test_locate_StringLiteral_importUri() async {
-    addNamedSource("/foo.dart", "library foo; class A {}");
-    AstNode id = await _findNodeIn(
-        "'foo.dart'", "import 'foo.dart'; class B extends A {}");
-    Element element = ElementLocator.locate(id);
-    expect(element, isLibraryElement);
-  }
-
-  test_locate_StringLiteral_partUri() async {
-    addNamedSource("/foo.dart", "part of app;");
-    AstNode id =
-        await _findNodeIn("'foo.dart'", "library app; part 'foo.dart';");
-    Element element = ElementLocator.locate(id);
-    expect(element, isCompilationUnitElement);
-  }
-
-  test_locate_VariableDeclaration() async {
-    AstNode id = await _findNodeIn("x", "var x = 'abc';");
-    VariableDeclaration declaration =
-        id.thisOrAncestorOfType<VariableDeclaration>();
-    Element element = ElementLocator.locate(declaration);
-    expect(element, isTopLevelVariableElement);
-  }
-
-  /**
-   * Find the first AST node matching a pattern in the resolved AST for the given source.
-   *
-   * [nodePattern] the (unique) pattern used to identify the node of interest.
-   * [code] the code to resolve.
-   * Returns the matched node in the resolved AST for the given source lines.
-   */
-  Future<AstNode> _findNodeIn(String nodePattern, String code) async {
-    return await _findNodeIndexedIn(nodePattern, 0, code);
-  }
-
-  /**
-   * Find the AST node matching the given indexed occurrence of a pattern in the resolved AST for
-   * the given source.
-   *
-   * [nodePattern] the pattern used to identify the node of interest.
-   * [index] the index of the pattern match of interest.
-   * [code] the code to resolve.
-   * Returns the matched node in the resolved AST for the given source lines
-   */
-  Future<AstNode> _findNodeIndexedIn(
-      String nodePattern, int index, String code) async {
-    CompilationUnit cu = await _resolveContents(code);
-    int start = _getOffsetOfMatch(code, nodePattern, index);
-    int end = start + nodePattern.length;
-    return new NodeLocator(start, end).searchWithin(cu);
-  }
-
-  int _getOffsetOfMatch(String contents, String pattern, int matchIndex) {
-    if (matchIndex == 0) {
-      return contents.indexOf(pattern);
-    }
-    Iterable<Match> matches = new RegExp(pattern).allMatches(contents);
-    Match match = matches.toList()[matchIndex];
-    return match.start;
-  }
-
-  /**
-   * Parse, resolve and verify the given source lines to produce a fully
-   * resolved AST.
-   *
-   * [code] the code to resolve.
-   *
-   * Returns the result of resolving the AST structure representing the content
-   * of the source.
-   *
-   * Throws if source cannot be verified.
-   */
-  Future<CompilationUnit> _resolveContents(String code) async {
-    Source source = addSource(code);
-    LibraryElement library = resolve2(source);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    return analysisContext.resolveCompilationUnit(source, library);
-  }
-}
-
 @reflectiveTest
 class EnumMemberBuilderTest extends EngineTestCase {
   test_visitEnumDeclaration_multiple() async {
@@ -639,168 +241,6 @@
 }
 
 @reflectiveTest
-class ErrorReporterTest extends EngineTestCase {
-  /**
-   * Return a newly created interface type with the given [typeName] in a
-   * compilation unit with the given [fileName].
-   */
-  InterfaceType createType(String fileName, String typeName) {
-    CompilationUnitElementImpl unit = ElementFactory.compilationUnit(fileName);
-    ClassElementImpl element = ElementFactory.classElement2(typeName);
-    unit.types = <ClassElement>[element];
-    return element.type;
-  }
-
-  test_creation() async {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    TestSource source = new TestSource();
-    expect(new ErrorReporter(listener, source), isNotNull);
-  }
-
-  test_reportErrorForElement_named() async {
-    DartType type = createType("/test1.dart", "A");
-    ClassElement element = type.element;
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter = new ErrorReporter(listener, element.source);
-    reporter.reportErrorForElement(
-        StaticWarningCode.CAST_TO_NON_TYPE, element, ['A']);
-    AnalysisError error = listener.errors[0];
-    expect(error.offset, element.nameOffset);
-  }
-
-  test_reportErrorForElement_unnamed() async {
-    ImportElementImpl element =
-        ElementFactory.importFor(ElementFactory.library(null, ''), null);
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter = new ErrorReporter(
-        listener,
-        new NonExistingSource(
-            '/test.dart', path.toUri('/test.dart'), UriKind.FILE_URI));
-    reporter.reportErrorForElement(
-        StaticWarningCode.CAST_TO_NON_TYPE, element, ['A']);
-    AnalysisError error = listener.errors[0];
-    expect(error.offset, element.nameOffset);
-  }
-
-  test_reportErrorForSpan() async {
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter = new ErrorReporter(listener, new TestSource());
-
-    var src = '''
-foo: bar
-zap: baz
-''';
-
-    int offset = src.indexOf('baz');
-    int length = 'baz'.length;
-
-    SourceSpan span = new SourceSpanBase(
-        new SourceLocation(offset), new SourceLocation(offset + length), 'baz');
-
-    reporter.reportErrorForSpan(
-        AnalysisOptionsWarningCode.UNSUPPORTED_OPTION_WITH_LEGAL_VALUE,
-        span,
-        ['test', 'zip', 'zap']);
-    expect(listener.errors, hasLength(1));
-    expect(listener.errors.first.offset, offset);
-    expect(listener.errors.first.length, length);
-  }
-
-  test_reportTypeErrorForNode_differentNames() async {
-    DartType firstType = createType("/test1.dart", "A");
-    DartType secondType = createType("/test2.dart", "B");
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter =
-        new ErrorReporter(listener, firstType.element.source);
-    reporter.reportTypeErrorForNode(
-        StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        AstTestFactory.identifier3("x"),
-        [firstType, secondType]);
-    AnalysisError error = listener.errors[0];
-    expect(error.message.contains("("), isFalse);
-  }
-
-  test_reportTypeErrorForNode_sameName() async {
-    String typeName = "A";
-    DartType firstType = createType("/test1.dart", typeName);
-    DartType secondType = createType("/test2.dart", typeName);
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter =
-        new ErrorReporter(listener, firstType.element.source);
-    reporter.reportTypeErrorForNode(
-        StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        AstTestFactory.identifier3("x"),
-        [firstType, secondType]);
-    AnalysisError error = listener.errors[0];
-    expect(error.message.contains("("), isTrue);
-  }
-}
-
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
-@reflectiveTest
-class ErrorReporterTest2 extends ResolverTestCase {
-  test_reportTypeErrorForNode_sameName_functionType() async {
-    addNamedSource('/a.dart', '''
-class A {}
-''');
-    addNamedSource('/b.dart', '''
-class A {}
-''');
-    CompilationUnit unit = await resolveSource('''
-import 'a.dart' as a;
-import 'b.dart' as b;
-
-a.A Function() fa;
-b.A Function() fb;
-''');
-
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter =
-        new ErrorReporter(listener, unit.declaredElement.source);
-    TopLevelVariableDeclaration fa = unit.declarations[0];
-    TopLevelVariableDeclaration fb = unit.declarations[1];
-    reporter.reportTypeErrorForNode(
-        StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        AstTestFactory.identifier3('x'),
-        [fa.variables.type.type, fb.variables.type.type]);
-    AnalysisError error = listener.errors[0];
-    expect(error.message.contains('a.dart'), isTrue);
-    expect(error.message.contains('b.dart'), isTrue);
-  }
-
-  test_reportTypeErrorForNode_sameName_nested() async {
-    addNamedSource('/a.dart', '''
-class A {}
-''');
-    addNamedSource('/b.dart', '''
-class A {}
-''');
-    CompilationUnit unit = await resolveSource('''
-import 'a.dart' as a;
-import 'b.dart' as b;
-
-B<a.A> ba;
-B<b.A> bb;
-class B<T> {}
-''');
-
-    GatheringErrorListener listener = new GatheringErrorListener();
-    ErrorReporter reporter =
-        new ErrorReporter(listener, unit.declaredElement.source);
-    TopLevelVariableDeclaration fa = unit.declarations[0];
-    TopLevelVariableDeclaration fb = unit.declarations[1];
-    reporter.reportTypeErrorForNode(
-        StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE,
-        AstTestFactory.identifier3('x'),
-        [fa.variables.type.type, fb.variables.type.type]);
-    AnalysisError error = listener.errors[0];
-    expect(error.message.contains('a.dart'), isTrue);
-    expect(error.message.contains('b.dart'), isTrue);
-  }
-}
-
-@reflectiveTest
 class ErrorSeverityTest extends EngineTestCase {
   test_max_error_error() async {
     expect(ErrorSeverity.ERROR.max(ErrorSeverity.ERROR),
@@ -848,924 +288,6 @@
   }
 }
 
-/**
- * Tests for the [ExitDetector] that do not require that the AST be resolved.
- *
- * See [ExitDetectorTest2] for tests that require the AST to be resolved.
- */
-@reflectiveTest
-class ExitDetectorTest extends ParserTestCase {
-  test_asExpression() async {
-    _assertFalse("a as Object;");
-  }
-
-  test_asExpression_throw() async {
-    _assertTrue("throw '' as Object;");
-  }
-
-  test_assertStatement() async {
-    _assertFalse("assert(a);");
-  }
-
-  test_assertStatement_throw() async {
-    _assertFalse("assert((throw 0));");
-  }
-
-  test_assignmentExpression() async {
-    _assertFalse("v = 1;");
-  }
-
-  test_assignmentExpression_compound_lazy() async {
-    enableLazyAssignmentOperators = true;
-    _assertFalse("v ||= false;");
-  }
-
-  test_assignmentExpression_lhs_throw() async {
-    _assertTrue("a[throw ''] = 0;");
-  }
-
-  test_assignmentExpression_rhs_throw() async {
-    _assertTrue("v = throw '';");
-  }
-
-  test_await_false() async {
-    _assertFalse("await x;");
-  }
-
-  test_await_throw_true() async {
-    _assertTrue("bool b = await (throw '' || true);");
-  }
-
-  test_binaryExpression_and() async {
-    _assertFalse("a && b;");
-  }
-
-  test_binaryExpression_and_lhs() async {
-    _assertTrue("throw '' && b;");
-  }
-
-  test_binaryExpression_and_rhs() async {
-    _assertFalse("a && (throw '');");
-  }
-
-  test_binaryExpression_and_rhs2() async {
-    _assertFalse("false && (throw '');");
-  }
-
-  test_binaryExpression_and_rhs3() async {
-    _assertTrue("true && (throw '');");
-  }
-
-  test_binaryExpression_ifNull() async {
-    _assertFalse("a ?? b;");
-  }
-
-  test_binaryExpression_ifNull_lhs() async {
-    _assertTrue("throw '' ?? b;");
-  }
-
-  test_binaryExpression_ifNull_rhs() async {
-    _assertFalse("a ?? (throw '');");
-  }
-
-  test_binaryExpression_ifNull_rhs2() async {
-    _assertFalse("null ?? (throw '');");
-  }
-
-  test_binaryExpression_or() async {
-    _assertFalse("a || b;");
-  }
-
-  test_binaryExpression_or_lhs() async {
-    _assertTrue("throw '' || b;");
-  }
-
-  test_binaryExpression_or_rhs() async {
-    _assertFalse("a || (throw '');");
-  }
-
-  test_binaryExpression_or_rhs2() async {
-    _assertFalse("true || (throw '');");
-  }
-
-  test_binaryExpression_or_rhs3() async {
-    _assertTrue("false || (throw '');");
-  }
-
-  test_block_empty() async {
-    _assertFalse("{}");
-  }
-
-  test_block_noReturn() async {
-    _assertFalse("{ int i = 0; }");
-  }
-
-  test_block_return() async {
-    _assertTrue("{ return 0; }");
-  }
-
-  test_block_returnNotLast() async {
-    _assertTrue("{ return 0; throw 'a'; }");
-  }
-
-  test_block_throwNotLast() async {
-    _assertTrue("{ throw 0; x = null; }");
-  }
-
-  test_cascadeExpression_argument() async {
-    _assertTrue("a..b(throw '');");
-  }
-
-  test_cascadeExpression_index() async {
-    _assertTrue("a..[throw ''];");
-  }
-
-  test_cascadeExpression_target() async {
-    _assertTrue("throw ''..b();");
-  }
-
-  test_conditional_ifElse_bothThrows() async {
-    _assertTrue("c ? throw '' : throw '';");
-  }
-
-  test_conditional_ifElse_elseThrows() async {
-    _assertFalse("c ? i : throw '';");
-  }
-
-  test_conditional_ifElse_noThrow() async {
-    _assertFalse("c ? i : j;");
-  }
-
-  test_conditional_ifElse_thenThrow() async {
-    _assertFalse("c ? throw '' : j;");
-  }
-
-  test_conditionalAccess() async {
-    _assertFalse("a?.b;");
-  }
-
-  test_conditionalAccess_lhs() async {
-    _assertTrue("(throw '')?.b;");
-  }
-
-  test_conditionalAccessAssign() async {
-    _assertFalse("a?.b = c;");
-  }
-
-  test_conditionalAccessAssign_lhs() async {
-    _assertTrue("(throw '')?.b = c;");
-  }
-
-  test_conditionalAccessAssign_rhs() async {
-    _assertFalse("a?.b = throw '';");
-  }
-
-  test_conditionalAccessAssign_rhs2() async {
-    _assertFalse("null?.b = throw '';");
-  }
-
-  test_conditionalAccessIfNullAssign() async {
-    _assertFalse("a?.b ??= c;");
-  }
-
-  test_conditionalAccessIfNullAssign_lhs() async {
-    _assertTrue("(throw '')?.b ??= c;");
-  }
-
-  test_conditionalAccessIfNullAssign_rhs() async {
-    _assertFalse("a?.b ??= throw '';");
-  }
-
-  test_conditionalAccessIfNullAssign_rhs2() async {
-    _assertFalse("null?.b ??= throw '';");
-  }
-
-  test_conditionalCall() async {
-    _assertFalse("a?.b(c);");
-  }
-
-  test_conditionalCall_lhs() async {
-    _assertTrue("(throw '')?.b(c);");
-  }
-
-  test_conditionalCall_rhs() async {
-    _assertFalse("a?.b(throw '');");
-  }
-
-  test_conditionalCall_rhs2() async {
-    _assertFalse("null?.b(throw '');");
-  }
-
-  test_creation() async {
-    expect(new ExitDetector(), isNotNull);
-  }
-
-  test_doStatement_break_and_throw() async {
-    _assertFalse("{ do { if (1==1) break; throw 'T'; } while (0==1); }");
-  }
-
-  test_doStatement_continue_and_throw() async {
-    _assertFalse("{ do { if (1==1) continue; throw 'T'; } while (0==1); }");
-  }
-
-  test_doStatement_continueDoInSwitch_and_throw() async {
-    _assertFalse('''
-{
-  D: do {
-    switch (1) {
-      L: case 0: continue D;
-      M: case 1: break;
-    }
-    throw 'T';
-  } while (0 == 1);
-}''');
-  }
-
-  test_doStatement_continueInSwitch_and_throw() async {
-    _assertFalse('''
-{
-  do {
-    switch (1) {
-      L: case 0: continue;
-      M: case 1: break;
-    }
-    throw 'T';
-  } while (0 == 1);
-}''');
-  }
-
-  test_doStatement_return() async {
-    _assertTrue("{ do { return null; } while (1 == 2); }");
-  }
-
-  test_doStatement_throwCondition() async {
-    _assertTrue("{ do {} while (throw ''); }");
-  }
-
-  test_doStatement_true_break() async {
-    _assertFalse("{ do { break; } while (true); }");
-  }
-
-  test_doStatement_true_continue() async {
-    _assertTrue("{ do { continue; } while (true); }");
-  }
-
-  test_doStatement_true_continueWithLabel() async {
-    _assertTrue("{ x: do { continue x; } while (true); }");
-  }
-
-  test_doStatement_true_if_return() async {
-    _assertTrue("{ do { if (true) {return null;} } while (true); }");
-  }
-
-  test_doStatement_true_noBreak() async {
-    _assertTrue("{ do {} while (true); }");
-  }
-
-  test_doStatement_true_return() async {
-    _assertTrue("{ do { return null; } while (true);  }");
-  }
-
-  test_emptyStatement() async {
-    _assertFalse(";");
-  }
-
-  test_forEachStatement() async {
-    _assertFalse("for (element in list) {}");
-  }
-
-  test_forEachStatement_throw() async {
-    _assertTrue("for (element in throw '') {}");
-  }
-
-  test_forStatement_condition() async {
-    _assertTrue("for (; throw 0;) {}");
-  }
-
-  test_forStatement_implicitTrue() async {
-    _assertTrue("for (;;) {}");
-  }
-
-  test_forStatement_implicitTrue_break() async {
-    _assertFalse("for (;;) { break; }");
-  }
-
-  test_forStatement_implicitTrue_if_break() async {
-    _assertFalse("{ for (;;) { if (1==2) { var a = 1; } else { break; } } }");
-  }
-
-  test_forStatement_initialization() async {
-    _assertTrue("for (i = throw 0;;) {}");
-  }
-
-  test_forStatement_true() async {
-    _assertTrue("for (; true; ) {}");
-  }
-
-  test_forStatement_true_break() async {
-    _assertFalse("{ for (; true; ) { break; } }");
-  }
-
-  test_forStatement_true_continue() async {
-    _assertTrue("{ for (; true; ) { continue; } }");
-  }
-
-  test_forStatement_true_if_return() async {
-    _assertTrue("{ for (; true; ) { if (true) {return null;} } }");
-  }
-
-  test_forStatement_true_noBreak() async {
-    _assertTrue("{ for (; true; ) {} }");
-  }
-
-  test_forStatement_updaters() async {
-    _assertTrue("for (;; i++, throw 0) {}");
-  }
-
-  test_forStatement_variableDeclaration() async {
-    _assertTrue("for (int i = throw 0;;) {}");
-  }
-
-  test_functionExpression() async {
-    _assertFalse("(){};");
-  }
-
-  test_functionExpression_bodyThrows() async {
-    _assertFalse("(int i) => throw '';");
-  }
-
-  test_functionExpressionInvocation() async {
-    _assertFalse("f(g);");
-  }
-
-  test_functionExpressionInvocation_argumentThrows() async {
-    _assertTrue("f(throw '');");
-  }
-
-  test_functionExpressionInvocation_targetThrows() async {
-    _assertTrue("throw ''(g);");
-  }
-
-  test_identifier_prefixedIdentifier() async {
-    _assertFalse("a.b;");
-  }
-
-  test_identifier_simpleIdentifier() async {
-    _assertFalse("a;");
-  }
-
-  test_if_false_else_return() async {
-    _assertTrue("if (false) {} else { return 0; }");
-  }
-
-  test_if_false_noReturn() async {
-    _assertFalse("if (false) {}");
-  }
-
-  test_if_false_return() async {
-    _assertFalse("if (false) { return 0; }");
-  }
-
-  test_if_noReturn() async {
-    _assertFalse("if (c) i++;");
-  }
-
-  test_if_return() async {
-    _assertFalse("if (c) return 0;");
-  }
-
-  test_if_true_noReturn() async {
-    _assertFalse("if (true) {}");
-  }
-
-  test_if_true_return() async {
-    _assertTrue("if (true) { return 0; }");
-  }
-
-  test_ifElse_bothReturn() async {
-    _assertTrue("if (c) return 0; else return 1;");
-  }
-
-  test_ifElse_elseReturn() async {
-    _assertFalse("if (c) i++; else return 1;");
-  }
-
-  test_ifElse_noReturn() async {
-    _assertFalse("if (c) i++; else j++;");
-  }
-
-  test_ifElse_thenReturn() async {
-    _assertFalse("if (c) return 0; else j++;");
-  }
-
-  test_ifNullAssign() async {
-    _assertFalse("a ??= b;");
-  }
-
-  test_ifNullAssign_rhs() async {
-    _assertFalse("a ??= throw '';");
-  }
-
-  test_indexExpression() async {
-    _assertFalse("a[b];");
-  }
-
-  test_indexExpression_index() async {
-    _assertTrue("a[throw ''];");
-  }
-
-  test_indexExpression_target() async {
-    _assertTrue("throw ''[b];");
-  }
-
-  test_instanceCreationExpression() async {
-    _assertFalse("new A(b);");
-  }
-
-  test_instanceCreationExpression_argumentThrows() async {
-    _assertTrue("new A(throw '');");
-  }
-
-  test_isExpression() async {
-    _assertFalse("A is B;");
-  }
-
-  test_isExpression_throws() async {
-    _assertTrue("throw '' is B;");
-  }
-
-  test_labeledStatement() async {
-    _assertFalse("label: a;");
-  }
-
-  test_labeledStatement_throws() async {
-    _assertTrue("label: throw '';");
-  }
-
-  test_literal_boolean() async {
-    _assertFalse("true;");
-  }
-
-  test_literal_double() async {
-    _assertFalse("1.1;");
-  }
-
-  test_literal_integer() async {
-    _assertFalse("1;");
-  }
-
-  test_literal_null() async {
-    _assertFalse("null;");
-  }
-
-  test_literal_String() async {
-    _assertFalse("'str';");
-  }
-
-  test_methodInvocation() async {
-    _assertFalse("a.b(c);");
-  }
-
-  test_methodInvocation_argument() async {
-    _assertTrue("a.b(throw '');");
-  }
-
-  test_methodInvocation_target() async {
-    _assertTrue("throw ''.b(c);");
-  }
-
-  test_parenthesizedExpression() async {
-    _assertFalse("(a);");
-  }
-
-  test_parenthesizedExpression_throw() async {
-    _assertTrue("(throw '');");
-  }
-
-  test_propertyAccess() async {
-    _assertFalse("new Object().a;");
-  }
-
-  test_propertyAccess_throws() async {
-    _assertTrue("(throw '').a;");
-  }
-
-  test_rethrow() async {
-    _assertTrue("rethrow;");
-  }
-
-  test_return() async {
-    _assertTrue("return 0;");
-  }
-
-  test_superExpression() async {
-    _assertFalse("super.a;");
-  }
-
-  test_switch_allReturn() async {
-    _assertTrue("switch (i) { case 0: return 0; default: return 1; }");
-  }
-
-  test_switch_defaultWithNoStatements() async {
-    _assertFalse("switch (i) { case 0: return 0; default: }");
-  }
-
-  test_switch_fallThroughToNotReturn() async {
-    _assertFalse("switch (i) { case 0: case 1: break; default: return 1; }");
-  }
-
-  test_switch_fallThroughToReturn() async {
-    _assertTrue("switch (i) { case 0: case 1: return 0; default: return 1; }");
-  }
-
-  // The ExitDetector could conceivably follow switch continue labels and
-  // determine that `case 0` exits, `case 1` continues to an exiting case, and
-  // `default` exits, so the switch exits.
-  @failingTest
-  test_switch_includesContinue() async {
-    _assertTrue('''
-switch (i) {
-  zero: case 0: return 0;
-  case 1: continue zero;
-  default: return 1;
-}''');
-  }
-
-  test_switch_noDefault() async {
-    _assertFalse("switch (i) { case 0: return 0; }");
-  }
-
-  test_switch_nonReturn() async {
-    _assertFalse("switch (i) { case 0: i++; default: return 1; }");
-  }
-
-  test_thisExpression() async {
-    _assertFalse("this.a;");
-  }
-
-  test_throwExpression() async {
-    _assertTrue("throw new Object();");
-  }
-
-  test_tryStatement_noReturn() async {
-    _assertFalse("try {} catch (e, s) {} finally {}");
-  }
-
-  test_tryStatement_noReturn_noFinally() async {
-    _assertFalse("try {} catch (e, s) {}");
-  }
-
-  test_tryStatement_return_catch() async {
-    _assertFalse("try {} catch (e, s) { return 1; } finally {}");
-  }
-
-  test_tryStatement_return_catch_noFinally() async {
-    _assertFalse("try {} catch (e, s) { return 1; }");
-  }
-
-  test_tryStatement_return_finally() async {
-    _assertTrue("try {} catch (e, s) {} finally { return 1; }");
-  }
-
-  test_tryStatement_return_try_noCatch() async {
-    _assertTrue("try { return 1; } finally {}");
-  }
-
-  test_tryStatement_return_try_oneCatchDoesNotExit() async {
-    _assertFalse("try { return 1; } catch (e, s) {} finally {}");
-  }
-
-  test_tryStatement_return_try_oneCatchDoesNotExit_noFinally() async {
-    _assertFalse("try { return 1; } catch (e, s) {}");
-  }
-
-  test_tryStatement_return_try_oneCatchExits() async {
-    _assertTrue("try { return 1; } catch (e, s) { return 1; } finally {}");
-  }
-
-  test_tryStatement_return_try_oneCatchExits_noFinally() async {
-    _assertTrue("try { return 1; } catch (e, s) { return 1; }");
-  }
-
-  test_tryStatement_return_try_twoCatchesDoExit() async {
-    _assertTrue('''
-try { return 1; }
-on int catch (e, s) { return 1; }
-on String catch (e, s) { return 1; }
-finally {}''');
-  }
-
-  test_tryStatement_return_try_twoCatchesDoExit_noFinally() async {
-    _assertTrue('''
-try { return 1; }
-on int catch (e, s) { return 1; }
-on String catch (e, s) { return 1; }''');
-  }
-
-  test_tryStatement_return_try_twoCatchesDoNotExit() async {
-    _assertFalse('''
-try { return 1; }
-on int catch (e, s) {}
-on String catch (e, s) {}
-finally {}''');
-  }
-
-  test_tryStatement_return_try_twoCatchesDoNotExit_noFinally() async {
-    _assertFalse('''
-try { return 1; }
-on int catch (e, s) {}
-on String catch (e, s) {}''');
-  }
-
-  test_tryStatement_return_try_twoCatchesMixed() async {
-    _assertFalse('''
-try { return 1; }
-on int catch (e, s) {}
-on String catch (e, s) { return 1; }
-finally {}''');
-  }
-
-  test_tryStatement_return_try_twoCatchesMixed_noFinally() async {
-    _assertFalse('''
-try { return 1; }
-on int catch (e, s) {}
-on String catch (e, s) { return 1; }''');
-  }
-
-  test_variableDeclarationStatement_noInitializer() async {
-    _assertFalse("int i;");
-  }
-
-  test_variableDeclarationStatement_noThrow() async {
-    _assertFalse("int i = 0;");
-  }
-
-  test_variableDeclarationStatement_throw() async {
-    _assertTrue("int i = throw new Object();");
-  }
-
-  test_whileStatement_false_nonReturn() async {
-    _assertFalse("{ while (false) {} }");
-  }
-
-  test_whileStatement_throwCondition() async {
-    _assertTrue("{ while (throw '') {} }");
-  }
-
-  test_whileStatement_true_break() async {
-    _assertFalse("{ while (true) { break; } }");
-  }
-
-  test_whileStatement_true_break_and_throw() async {
-    _assertFalse("{ while (true) { if (1==1) break; throw 'T'; } }");
-  }
-
-  test_whileStatement_true_continue() async {
-    _assertTrue("{ while (true) { continue; } }");
-  }
-
-  test_whileStatement_true_continueWithLabel() async {
-    _assertTrue("{ x: while (true) { continue x; } }");
-  }
-
-  test_whileStatement_true_doStatement_scopeRequired() async {
-    _assertTrue("{ while (true) { x: do { continue x; } while (true); } }");
-  }
-
-  test_whileStatement_true_if_return() async {
-    _assertTrue("{ while (true) { if (true) {return null;} } }");
-  }
-
-  test_whileStatement_true_noBreak() async {
-    _assertTrue("{ while (true) {} }");
-  }
-
-  test_whileStatement_true_return() async {
-    _assertTrue("{ while (true) { return null; } }");
-  }
-
-  test_whileStatement_true_throw() async {
-    _assertTrue("{ while (true) { throw ''; } }");
-  }
-
-  void _assertFalse(String source) {
-    _assertHasReturn(false, source);
-  }
-
-  void _assertHasReturn(bool expectedResult, String source) {
-    Statement statement = parseStatement(source,
-        enableLazyAssignmentOperators: enableLazyAssignmentOperators);
-    expect(ExitDetector.exits(statement), expectedResult);
-  }
-
-  void _assertTrue(String source) {
-    _assertHasReturn(true, source);
-  }
-}
-
-/**
- * Tests for the [ExitDetector] that require that the AST be resolved.
- *
- * See [ExitDetectorTest] for tests that do not require the AST to be resolved.
- * TODO(paulberry): migrate this test away from the task model.
- * See dartbug.com/35734.
- */
-@reflectiveTest
-class ExitDetectorTest2 extends ResolverTestCase {
-  test_forStatement_implicitTrue_breakWithLabel() async {
-    Source source = addSource(r'''
-void f() {
-  x: for (;;) {
-    if (1 < 2) {
-      break x;
-    }
-    return;
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_switch_withEnum_false_noDefault() async {
-    Source source = addSource(r'''
-enum E { A, B }
-String f(E e) {
-  var x;
-  switch (e) {
-    case A:
-      x = 'A';
-    case B:
-      x = 'B';
-  }
-  return x;
-}
-''');
-    _assertNthStatementDoesNotExit(source, 1);
-  }
-
-  test_switch_withEnum_false_withDefault() async {
-    Source source = addSource(r'''
-enum E { A, B }
-String f(E e) {
-  var x;
-  switch (e) {
-    case A:
-      x = 'A';
-    default:
-      x = '?';
-  }
-  return x;
-}
-''');
-    _assertNthStatementDoesNotExit(source, 1);
-  }
-
-  test_switch_withEnum_true_noDefault() async {
-    Source source = addSource(r'''
-enum E { A, B }
-String f(E e) {
-  switch (e) {
-    case A:
-      return 'A';
-    case B:
-      return 'B';
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_switch_withEnum_true_withExitingDefault() async {
-    Source source = addSource(r'''
-enum E { A, B }
-String f(E e) {
-  switch (e) {
-    case A:
-      return 'A';
-    default:
-      return '?';
-  }
-}
-''');
-    _assertNthStatementExits(source, 0);
-  }
-
-  test_switch_withEnum_true_withNonExitingDefault() async {
-    Source source = addSource(r'''
-enum E { A, B }
-String f(E e) {
-  var x;
-  switch (e) {
-    case A:
-      return 'A';
-    default:
-      x = '?';
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 1);
-  }
-
-  test_whileStatement_breakWithLabel() async {
-    Source source = addSource(r'''
-void f() {
-  x: while (true) {
-    if (1 < 2) {
-      break x;
-    }
-    return;
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_whileStatement_breakWithLabel_afterExiting() async {
-    Source source = addSource(r'''
-void f() {
-  x: while (true) {
-    return;
-    if (1 < 2) {
-      break x;
-    }
-  }
-}
-''');
-    _assertNthStatementExits(source, 0);
-  }
-
-  test_whileStatement_switchWithBreakWithLabel() async {
-    Source source = addSource(r'''
-void f() {
-  x: while (true) {
-    switch (true) {
-      case false: break;
-      case true: break x;
-    }
-  }
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_yieldStatement_plain() async {
-    Source source = addSource(r'''
-void f() sync* {
-  yield 1;
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_yieldStatement_star_plain() async {
-    Source source = addSource(r'''
-void f() sync* {
-  yield* 1;
-}
-''');
-    _assertNthStatementDoesNotExit(source, 0);
-  }
-
-  test_yieldStatement_star_throw() async {
-    Source source = addSource(r'''
-void f() sync* {
-  yield* throw '';
-}
-''');
-    _assertNthStatementExits(source, 0);
-  }
-
-  test_yieldStatement_throw() async {
-    Source source = addSource(r'''
-void f() sync* {
-  yield throw '';
-}
-''');
-    _assertNthStatementExits(source, 0);
-  }
-
-  void _assertHasReturn(bool expectedResult, Source source, int n) {
-    LibraryElement element = resolve2(source);
-    CompilationUnit unit = resolveCompilationUnit(source, element);
-    FunctionDeclaration function = unit.declarations.last;
-    BlockFunctionBody body = function.functionExpression.body;
-    Statement statement = body.block.statements[n];
-    expect(ExitDetector.exits(statement), expectedResult);
-  }
-
-  // Assert that the [n]th statement in the last function declaration of
-  // [source] exits.
-  void _assertNthStatementDoesNotExit(Source source, int n) {
-    _assertHasReturn(false, source, n);
-  }
-
-  // Assert that the [n]th statement in the last function declaration of
-  // [source] does not exit.
-  void _assertNthStatementExits(Source source, int n) {
-    _assertHasReturn(true, source, n);
-  }
-}
-
 @reflectiveTest
 class FileBasedSourceTest {
   test_equals_false_differentFiles() async {
diff --git a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
index 472a581..9c33cd5 100644
--- a/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
+++ b/pkg/analyzer/test/generated/compile_time_error_code_driver_test.dart
@@ -3,6 +3,7 @@
 // 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/source.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -14,6 +15,7 @@
   defineReflectiveSuite(() {
     defineReflectiveTests(CompileTimeErrorCodeTest_Driver);
     defineReflectiveTests(ConstSetElementTypeImplementsEqualsTest);
+    defineReflectiveTests(ControlFlowCollectionsTest);
     defineReflectiveTests(InvalidTypeArgumentInConstSetTest);
     defineReflectiveTests(NonConstSetElementFromDeferredLibraryTest);
     defineReflectiveTests(NonConstSetElementTest);
@@ -202,6 +204,343 @@
 }
 
 @reflectiveTest
+class ControlFlowCollectionsTest extends ResolverTestCase {
+  @override
+  List<String> get enabledExperiments =>
+      [EnableString.control_flow_collections, EnableString.set_literals];
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_awaitForIn_declaredVariableWrongType() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+f() async {
+  Stream<String> stream;
+  await for (int i in stream) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+  }
+
+  test_awaitForIn_existingVariableWrongType() async {
+    await assertErrorsInCode('''
+import 'dart:async';
+f() async {
+  Stream<String> stream;
+  int i;
+  await for (i in stream) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+  }
+
+  test_awaitForIn_notStream() async {
+    await assertErrorsInCode('''
+f() async {
+  await for (var i in true) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+  }
+
+  test_duplicateDefinition_for_initializers() async {
+    Source source = addSource(r'''
+f() {
+  for (int i = 0, i = 0; i < 5;) {}
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.DUPLICATE_DEFINITION]);
+    verify([source]);
+  }
+
+  test_expectedOneListTypeArgument() async {
+    await assertErrorsInCode(r'''
+main() {
+  <int, int>[];
+}''', [StaticTypeWarningCode.EXPECTED_ONE_LIST_TYPE_ARGUMENTS]);
+  }
+
+  test_expectedOneSetTypeArgument() async {
+    await assertErrorsInCode(r'''
+main() {
+  <int, int, int>{2, 3};
+}''', [StaticTypeWarningCode.EXPECTED_ONE_SET_TYPE_ARGUMENTS]);
+  }
+
+  test_expectedTwoMapTypeArguments_three() async {
+    await assertErrorsInCode(r'''
+main() {
+  <int, int, int>{};
+}''', [StaticTypeWarningCode.EXPECTED_TWO_MAP_TYPE_ARGUMENTS]);
+  }
+
+  test_forIn_declaredVariableWrongType() async {
+    await assertErrorsInCode('''
+f() {
+  for (int i in <String>[]) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+  }
+
+  test_forIn_existingVariableWrongType() async {
+    await assertErrorsInCode('''
+f() {
+  int i;
+  for (i in <String>[]) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+  }
+
+  test_forIn_notIterable() async {
+    await assertErrorsInCode('''
+f() {
+  for (var i in true) {}
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_TYPE]);
+  }
+
+  test_forIn_typeBoundBad() async {
+    await assertErrorsInCode('''
+class Foo<T extends Iterable<int>> {
+  void method(T iterable) {
+    for (String i in iterable) {}
+  }
+}
+''', [StaticTypeWarningCode.FOR_IN_OF_INVALID_ELEMENT_TYPE]);
+  }
+
+  test_forInWithConstVariable_forEach_identifier() async {
+    Source source = addSource(r'''
+f() {
+  const x = 0;
+  for (x in [0, 1, 2]) {}
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+    verify([source]);
+  }
+
+  test_forInWithConstVariable_forEach_loopVariable() async {
+    Source source = addSource(r'''
+f() {
+  for (const x in [0, 1, 2]) {}
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [CompileTimeErrorCode.FOR_IN_WITH_CONST_VARIABLE]);
+    verify([source]);
+  }
+
+  test_generalizedVoid_useOfInForeachIterableError() async {
+    Source source = addSource(r'''
+void main() {
+  void x;
+  for (var v in x) {}
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+  }
+
+  test_generalizedVoid_useOfVoidInForeachVariableError() async {
+    Source source = addSource(r'''
+void main() {
+  void x;
+  var y;
+  for (y in x) {}
+}
+''');
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.USE_OF_VOID_RESULT]);
+  }
+
+  test_invalidTypeArgumentInConstList() async {
+    Source source = addSource(r'''
+class A<E> {
+  m() {
+    return const <E>[];
+  }
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_LIST]);
+    verify([source]);
+  }
+
+  test_invalidTypeArgumentInConstMap_key() async {
+    Source source = addSource(r'''
+class A<E> {
+  m() {
+    return const <E, String>{};
+  }
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+    verify([source]);
+  }
+
+  test_invalidTypeArgumentInConstMap_value() async {
+    Source source = addSource(r'''
+class A<E> {
+  m() {
+    return const <String, E>{};
+  }
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_MAP]);
+    verify([source]);
+  }
+
+  test_invalidTypeArgumentInConstSet_class() async {
+    Source source = addSource(r'''
+class A<E> {
+  m() {
+    return const <E>{};
+  }
+}''');
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CompileTimeErrorCode.INVALID_TYPE_ARGUMENT_IN_CONST_SET]);
+    verify([source]);
+  }
+
+  test_listElementTypeNotAssignable_const() async {
+    Source source = addSource("var v = const <String>[42];");
+    await computeAnalysisResult(source);
+    assertErrors(source,
+        [CheckedModeCompileTimeErrorCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_listElementTypeNotAssignable_nonConst() async {
+    Source source = addSource("var v = <String> [42];");
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.LIST_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_mapKeyTypeNotAssignable_const() async {
+    Source source = addSource("var v = const <String, int >{1 : 2};");
+    await computeAnalysisResult(source);
+    assertErrors(
+        source, [CheckedModeCompileTimeErrorCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_mapKeyTypeNotAssignable_nonConst() async {
+    Source source = addSource("var v = <String, int >{1 : 2};");
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.MAP_KEY_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_mapValueTypeNotAssignable_const() async {
+    Source source = addSource("var v = const <String, String>{'a' : 2};");
+    await computeAnalysisResult(source);
+    assertErrors(source,
+        [CheckedModeCompileTimeErrorCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_mapValueTypeNotAssignable_nonConst() async {
+    Source source = addSource("var v = <String, String>{'a' : 2};");
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.MAP_VALUE_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_nonBoolCondition_for_declaration() async {
+    // https://github.com/dart-lang/sdk/issues/24713
+    await assertErrorsInCode(r'''
+f() {
+  for (int i = 0; 3;) {}
+}
+''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+  }
+
+  test_nonBoolCondition_for_expression() async {
+    // https://github.com/dart-lang/sdk/issues/24713
+    await assertErrorsInCode(r'''
+f() {
+  int i;
+  for (i = 0; 3;) {}
+}''', [StaticTypeWarningCode.NON_BOOL_CONDITION]);
+  }
+
+  test_nonConstMapAsExpressionStatement_begin() async {
+    Source source = addSource(r'''
+f() {
+  {'a' : 0, 'b' : 1}.length;
+}''');
+    await computeAnalysisResult(source);
+    // TODO(danrubel) Fasta is not recovering.
+    assertErrors(source, [
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+//    assertErrors(
+//        source, [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]);
+    verify([source]);
+  }
+
+  test_nonConstMapAsExpressionStatement_only() async {
+    Source source = addSource(r'''
+f() {
+  {'a' : 0, 'b' : 1};
+}''');
+    await computeAnalysisResult(source);
+    // TODO(danrubel) Fasta is not recovering.
+    assertErrors(source, [
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.UNEXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.EXPECTED_TOKEN,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER,
+      ParserErrorCode.MISSING_IDENTIFIER
+    ]);
+//    assertErrors(
+//        source, [CompileTimeErrorCode.NON_CONST_MAP_AS_EXPRESSION_STATEMENT]);
+    verify([source]);
+  }
+
+  test_setElementTypeNotAssignable_const() async {
+    Source source = addSource("var v = const <String>{42};");
+    await computeAnalysisResult(source);
+    assertErrors(source,
+        [CheckedModeCompileTimeErrorCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+
+  test_setElementTypeNotAssignable_nonConst() async {
+    Source source = addSource("var v = <String>{42};");
+    await computeAnalysisResult(source);
+    assertErrors(source, [StaticWarningCode.SET_ELEMENT_TYPE_NOT_ASSIGNABLE]);
+    verify([source]);
+  }
+}
+
+@reflectiveTest
 class InvalidTypeArgumentInConstSetTest extends ResolverTestCase {
   @override
   List<String> get enabledExperiments => [EnableString.set_literals];
diff --git a/pkg/analyzer/test/generated/constant_test.dart b/pkg/analyzer/test/generated/constant_test.dart
index 5d3312f..d4e7df3 100644
--- a/pkg/analyzer/test/generated/constant_test.dart
+++ b/pkg/analyzer/test/generated/constant_test.dart
@@ -5,16 +5,12 @@
 @deprecated
 library analyzer.test.constant_test;
 
-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/generated/constant.dart';
-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(() {
@@ -22,112 +18,26 @@
   });
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class ConstantEvaluatorTest extends ResolverTestCase {
-  void fail_identifier_class() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
+class ConstantEvaluatorTest extends DriverResolutionTest {
+  test_bitAnd_int_int() async {
+    await _assertValueInt(74 & 42, "74 & 42");
   }
 
-  void fail_identifier_function() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
+  test_bitNot() async {
+    await _assertValueInt(~42, "~42");
   }
 
-  void fail_identifier_static() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
+  test_bitOr_int_int() async {
+    await _assertValueInt(74 | 42, "74 | 42");
   }
 
-  void fail_identifier_staticMethod() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
+  test_bitXor_int_int() async {
+    await _assertValueInt(74 ^ 42, "74 ^ 42");
   }
 
-  void fail_identifier_topLevel() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_identifier_typeParameter() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_prefixedIdentifier_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_prefixedIdentifier_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_propertyAccess_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_propertyAccess_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_simpleIdentifier_invalid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void fail_simpleIdentifier_valid() {
-    EvaluationResult result = _getExpressionValue("?");
-    expect(result.isValid, isTrue);
-    DartObject value = result.value;
-    expect(value, null);
-  }
-
-  void test_bitAnd_int_int() {
-    _assertValue3(74 & 42, "74 & 42");
-  }
-
-  void test_bitNot() {
-    _assertValue3(~42, "~42");
-  }
-
-  void test_bitOr_int_int() {
-    _assertValue3(74 | 42, "74 | 42");
-  }
-
-  void test_bitXor_int_int() {
-    _assertValue3(74 ^ 42, "74 ^ 42");
-  }
-
-  void test_constructorInvocation_assert_false() {
-    EvaluationResult result = _getExpressionValue("const C(0)", context: '''
+  test_constructorInvocation_assert_false() async {
+    var result = await _getExpressionValue("const C(0)", context: '''
 class C {
   const C(int x) : assert(x > 0);
 }
@@ -136,8 +46,9 @@
   }
 
   test_constructorInvocation_assert_inherited() async {
-    EvaluationResult result =
-        _getExpressionValue("const Center(name: 'v')", context: '''
+    var result = await _getExpressionValue(
+      "const Center(name: 'v')",
+      context: '''
 class Align {
   final double widthFactor;
   const Align({String name, this.widthFactor})
@@ -147,7 +58,8 @@
   const Center({String name})
     : super(name: name);
 }
-''');
+''',
+    );
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value, isNotNull);
@@ -158,8 +70,8 @@
     expect(widthFactor.isNull, isTrue);
   }
 
-  void test_constructorInvocation_assert_true() {
-    EvaluationResult result = _getExpressionValue("const C(3)", context: '''
+  test_constructorInvocation_assert_true() async {
+    var result = await _getExpressionValue("const C(3)", context: '''
 class C {
   const C(int x) : assert(x > 0);
 }
@@ -170,8 +82,8 @@
     expect(value.type.name, 'C');
   }
 
-  void test_constructorInvocation_fieldInitializer() {
-    EvaluationResult result = _getExpressionValue("const C(2)", context: '''
+  test_constructorInvocation_fieldInitializer() async {
+    var result = await _getExpressionValue("const C(2)", context: '''
 class C {
   final int x;
   const C(this.x);
@@ -187,25 +99,29 @@
     expect(x.toIntValue(), 2);
   }
 
-  void test_constructorInvocation_noArgs() {
-    EvaluationResult result =
-        _getExpressionValue("const C()", context: 'class C {const C();}');
+  test_constructorInvocation_noArgs() async {
+    var result = await _getExpressionValue(
+      "const C()",
+      context: 'class C {const C();}',
+    );
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value, isNotNull);
     expect(value.type.name, 'C');
   }
 
-  void test_constructorInvocation_noConstConstructor() {
-    EvaluationResult result =
-        _getExpressionValue("const C()", context: 'class C {}');
+  test_constructorInvocation_noConstConstructor() async {
+    var result = await _getExpressionValue(
+      "const C()",
+      context: 'class C {}',
+    );
     expect(result.isValid, isFalse);
     DartObject value = result.value;
     expect(value, isNull);
   }
 
-  void test_constructorInvocation_simpleArgs() {
-    EvaluationResult result = _getExpressionValue("const C(1)", context: '''
+  test_constructorInvocation_simpleArgs() async {
+    var result = await _getExpressionValue("const C(1)", context: '''
 class C {
   const C(int x);
 }
@@ -216,254 +132,351 @@
     expect(value.type.name, 'C');
   }
 
-  void test_divide_double_double() {
-    _assertValue2(3.2 / 2.3, "3.2 / 2.3");
+  test_divide_double_double() async {
+    await _assertValueDouble(3.2 / 2.3, "3.2 / 2.3");
   }
 
-  void test_divide_double_double_byZero() {
-    EvaluationResult result = _getExpressionValue("3.2 / 0.0");
+  test_divide_double_double_byZero() async {
+    var result = await _getExpressionValue("3.2 / 0.0");
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value.type.name, "double");
     expect(value.toDoubleValue().isInfinite, isTrue);
   }
 
-  void test_divide_int_int() {
-    _assertValue2(1.5, "3 / 2");
+  test_divide_int_int() async {
+    await _assertValueDouble(1.5, "3 / 2");
   }
 
-  void test_divide_int_int_byZero() {
-    EvaluationResult result = _getExpressionValue("3 / 0");
+  test_divide_int_int_byZero() async {
+    var result = await _getExpressionValue("3 / 0");
     expect(result.isValid, isTrue);
   }
 
-  void test_equal_boolean_boolean() {
-    _assertValue(false, "true == false");
+  test_equal_boolean_boolean() async {
+    await _assertValueBool(false, "true == false");
   }
 
-  void test_equal_int_int() {
-    _assertValue(false, "2 == 3");
+  test_equal_int_int() async {
+    await _assertValueBool(false, "2 == 3");
   }
 
-  void test_equal_invalidLeft() {
-    EvaluationResult result = _getExpressionValue("a == 3");
+  test_equal_invalidLeft() async {
+    var result = await _getExpressionValue("a == 3");
     expect(result.isValid, isFalse);
   }
 
-  void test_equal_invalidRight() {
-    EvaluationResult result = _getExpressionValue("2 == a");
+  test_equal_invalidRight() async {
+    var result = await _getExpressionValue("2 == a");
     expect(result.isValid, isFalse);
   }
 
-  void test_equal_string_string() {
-    _assertValue(false, "'a' == 'b'");
+  test_equal_string_string() async {
+    await _assertValueBool(false, "'a' == 'b'");
   }
 
-  void test_greaterThan_int_int() {
-    _assertValue(false, "2 > 3");
+  test_greaterThan_int_int() async {
+    await _assertValueBool(false, "2 > 3");
   }
 
-  void test_greaterThanOrEqual_int_int() {
-    _assertValue(false, "2 >= 3");
+  test_greaterThanOrEqual_int_int() async {
+    await _assertValueBool(false, "2 >= 3");
   }
 
-  void test_leftShift_int_int() {
-    _assertValue3(64, "16 << 2");
+  @failingTest
+  test_identifier_class() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_lessThan_int_int() {
-    _assertValue(true, "2 < 3");
+  @failingTest
+  test_identifier_function() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_lessThanOrEqual_int_int() {
-    _assertValue(true, "2 <= 3");
+  @failingTest
+  test_identifier_static() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_literal_boolean_false() {
-    _assertValue(false, "false");
+  @failingTest
+  test_identifier_staticMethod() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_literal_boolean_true() {
-    _assertValue(true, "true");
+  @failingTest
+  test_identifier_topLevel() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_literal_list() {
-    EvaluationResult result = _getExpressionValue("const ['a', 'b', 'c']");
+  @failingTest
+  test_identifier_typeParameter() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
+  }
+
+  test_leftShift_int_int() async {
+    await _assertValueInt(64, "16 << 2");
+  }
+
+  test_lessThan_int_int() async {
+    await _assertValueBool(true, "2 < 3");
+  }
+
+  test_lessThanOrEqual_int_int() async {
+    await _assertValueBool(true, "2 <= 3");
+  }
+
+  test_literal_boolean_false() async {
+    await _assertValueBool(false, "false");
+  }
+
+  test_literal_boolean_true() async {
+    await _assertValueBool(true, "true");
+  }
+
+  test_literal_list() async {
+    var result = await _getExpressionValue("const ['a', 'b', 'c']");
     expect(result.isValid, isTrue);
   }
 
-  void test_literal_map() {
-    EvaluationResult result =
-        _getExpressionValue("const {'a' : 'm', 'b' : 'n', 'c' : 'o'}");
+  test_literal_map() async {
+    var result = await _getExpressionValue(
+      "const {'a' : 'm', 'b' : 'n', 'c' : 'o'}",
+    );
     expect(result.isValid, isTrue);
     Map<DartObject, DartObject> map = result.value.toMapValue();
     expect(map.keys.map((k) => k.toStringValue()), ['a', 'b', 'c']);
   }
 
-  void test_literal_null() {
-    EvaluationResult result = _getExpressionValue("null");
+  test_literal_null() async {
+    var result = await _getExpressionValue("null");
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value.isNull, isTrue);
   }
 
-  void test_literal_number_double() {
-    _assertValue2(3.45, "3.45");
+  test_literal_number_double() async {
+    await _assertValueDouble(3.45, "3.45");
   }
 
-  void test_literal_number_integer() {
-    _assertValue3(42, "42");
+  test_literal_number_integer() async {
+    await _assertValueInt(42, "42");
   }
 
-  void test_literal_string_adjacent() {
-    _assertValue4("abcdef", "'abc' 'def'");
+  test_literal_string_adjacent() async {
+    await _assertValueString("abcdef", "'abc' 'def'");
   }
 
-  void test_literal_string_interpolation_invalid() {
-    EvaluationResult result = _getExpressionValue("'a\${f()}c'");
+  test_literal_string_interpolation_invalid() async {
+    var result = await _getExpressionValue("'a\${f()}c'");
     expect(result.isValid, isFalse);
   }
 
-  void test_literal_string_interpolation_valid() {
-    _assertValue4("a3c", "'a\${3}c'");
+  test_literal_string_interpolation_valid() async {
+    await _assertValueString("a3c", "'a\${3}c'");
   }
 
-  void test_literal_string_simple() {
-    _assertValue4("abc", "'abc'");
+  test_literal_string_simple() async {
+    await _assertValueString("abc", "'abc'");
   }
 
-  void test_logicalAnd() {
-    _assertValue(false, "true && false");
+  test_logicalAnd() async {
+    await _assertValueBool(false, "true && false");
   }
 
-  void test_logicalNot() {
-    _assertValue(false, "!true");
+  test_logicalNot() async {
+    await _assertValueBool(false, "!true");
   }
 
-  void test_logicalOr() {
-    _assertValue(true, "true || false");
+  test_logicalOr() async {
+    await _assertValueBool(true, "true || false");
   }
 
-  void test_minus_double_double() {
-    _assertValue2(3.2 - 2.3, "3.2 - 2.3");
+  test_minus_double_double() async {
+    await _assertValueDouble(3.2 - 2.3, "3.2 - 2.3");
   }
 
-  void test_minus_int_int() {
-    _assertValue3(1, "3 - 2");
+  test_minus_int_int() async {
+    await _assertValueInt(1, "3 - 2");
   }
 
-  void test_negated_boolean() {
-    EvaluationResult result = _getExpressionValue("-true");
+  test_negated_boolean() async {
+    var result = await _getExpressionValue("-true");
     expect(result.isValid, isFalse);
   }
 
-  void test_negated_double() {
-    _assertValue2(-42.3, "-42.3");
+  test_negated_double() async {
+    await _assertValueDouble(-42.3, "-42.3");
   }
 
-  void test_negated_integer() {
-    _assertValue3(-42, "-42");
+  test_negated_integer() async {
+    await _assertValueInt(-42, "-42");
   }
 
-  void test_notEqual_boolean_boolean() {
-    _assertValue(true, "true != false");
+  test_notEqual_boolean_boolean() async {
+    await _assertValueBool(true, "true != false");
   }
 
-  void test_notEqual_int_int() {
-    _assertValue(true, "2 != 3");
+  test_notEqual_int_int() async {
+    await _assertValueBool(true, "2 != 3");
   }
 
-  void test_notEqual_invalidLeft() {
-    EvaluationResult result = _getExpressionValue("a != 3");
+  test_notEqual_invalidLeft() async {
+    var result = await _getExpressionValue("a != 3");
     expect(result.isValid, isFalse);
   }
 
-  void test_notEqual_invalidRight() {
-    EvaluationResult result = _getExpressionValue("2 != a");
+  test_notEqual_invalidRight() async {
+    var result = await _getExpressionValue("2 != a");
     expect(result.isValid, isFalse);
   }
 
-  void test_notEqual_string_string() {
-    _assertValue(true, "'a' != 'b'");
+  test_notEqual_string_string() async {
+    await _assertValueBool(true, "'a' != 'b'");
   }
 
-  void test_parenthesizedExpression() {
-    _assertValue4("a", "('a')");
+  test_parenthesizedExpression() async {
+    await _assertValueString("a", "('a')");
   }
 
-  void test_plus_double_double() {
-    _assertValue2(2.3 + 3.2, "2.3 + 3.2");
+  test_plus_double_double() async {
+    await _assertValueDouble(2.3 + 3.2, "2.3 + 3.2");
   }
 
-  void test_plus_int_int() {
-    _assertValue3(5, "2 + 3");
+  test_plus_int_int() async {
+    await _assertValueInt(5, "2 + 3");
   }
 
-  void test_plus_string_string() {
-    _assertValue4("ab", "'a' + 'b'");
+  test_plus_string_string() async {
+    await _assertValueString("ab", "'a' + 'b'");
   }
 
-  void test_remainder_double_double() {
-    _assertValue2(3.2 % 2.3, "3.2 % 2.3");
+  @failingTest
+  test_prefixedIdentifier_invalid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_remainder_int_int() {
-    _assertValue3(2, "8 % 3");
+  @failingTest
+  test_prefixedIdentifier_valid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_rightShift() {
-    _assertValue3(16, "64 >> 2");
+  @failingTest
+  test_propertyAccess_invalid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_stringLength_complex() {
-    _assertValue3(6, "('qwe' + 'rty').length");
+  @failingTest
+  test_propertyAccess_valid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_stringLength_simple() {
-    _assertValue3(6, "'Dvorak'.length");
+  test_remainder_double_double() async {
+    await _assertValueDouble(3.2 % 2.3, "3.2 % 2.3");
   }
 
-  void test_times_double_double() {
-    _assertValue2(2.3 * 3.2, "2.3 * 3.2");
+  test_remainder_int_int() async {
+    await _assertValueInt(2, "8 % 3");
   }
 
-  void test_times_int_int() {
-    _assertValue3(6, "2 * 3");
+  test_rightShift() async {
+    await _assertValueInt(16, "64 >> 2");
   }
 
-  void test_truncatingDivide_double_double() {
-    _assertValue3(1, "3.2 ~/ 2.3");
+  @failingTest
+  test_simpleIdentifier_invalid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void test_truncatingDivide_int_int() {
-    _assertValue3(3, "10 ~/ 3");
+  @failingTest
+  test_simpleIdentifier_valid() async {
+    var result = await _getExpressionValue("?");
+    expect(result.isValid, isTrue);
+    DartObject value = result.value;
+    expect(value, null);
   }
 
-  void _assertValue(bool expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
+  test_stringLength_complex() async {
+    await _assertValueInt(6, "('qwe' + 'rty').length");
+  }
+
+  test_stringLength_simple() async {
+    await _assertValueInt(6, "'Dvorak'.length");
+  }
+
+  test_times_double_double() async {
+    await _assertValueDouble(2.3 * 3.2, "2.3 * 3.2");
+  }
+
+  test_times_int_int() async {
+    await _assertValueInt(6, "2 * 3");
+  }
+
+  test_truncatingDivide_double_double() async {
+    await _assertValueInt(1, "3.2 ~/ 2.3");
+  }
+
+  test_truncatingDivide_int_int() async {
+    await _assertValueInt(3, "10 ~/ 3");
+  }
+
+  Future<void> _assertValueBool(bool expectedValue, String contents) async {
+    var result = await _getExpressionValue(contents);
     DartObject value = result.value;
     expect(value.type.name, "bool");
     expect(value.toBoolValue(), expectedValue);
   }
 
-  void _assertValue2(double expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
+  Future<void> _assertValueDouble(double expectedValue, String contents) async {
+    var result = await _getExpressionValue(contents);
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value.type.name, "double");
     expect(value.toDoubleValue(), expectedValue);
   }
 
-  void _assertValue3(int expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
+  Future<void> _assertValueInt(int expectedValue, String contents) async {
+    var result = await _getExpressionValue(contents);
     expect(result.isValid, isTrue);
     DartObject value = result.value;
     expect(value.type.name, "int");
     expect(value.toIntValue(), expectedValue);
   }
 
-  void _assertValue4(String expectedValue, String contents) {
-    EvaluationResult result = _getExpressionValue(contents);
+  Future<void> _assertValueString(String expectedValue, String contents) async {
+    var result = await _getExpressionValue(contents);
     DartObject value = result.value;
     expect(value, isNotNull);
     ParameterizedType type = value.type;
@@ -472,19 +485,26 @@
     expect(value.toStringValue(), expectedValue);
   }
 
-  EvaluationResult _getExpressionValue(String contents, {String context: ''}) {
-    Source source = addSource("var x = $contents;$context");
-    LibraryElement library = resolve2(source);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, library);
-    expect(unit, isNotNull);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    TopLevelVariableDeclaration declaration = declarations[0];
-    NodeList<VariableDeclaration> variables = declaration.variables.variables;
-    expect(variables, hasLength(1));
-    ConstantEvaluator evaluator = new ConstantEvaluator(
-        source, analysisContext.typeProvider,
-        typeSystem: analysisContext.typeSystem);
-    return evaluator.evaluate(variables[0].initializer);
+  Future<EvaluationResult> _getExpressionValue(String expressionCode,
+      {String context: ''}) async {
+    var path = convertPath('/test/lib/test.dart');
+
+    var file = newFile(path, content: '''
+var x = $expressionCode;
+
+$context
+''');
+
+    await resolveTestFile();
+
+    var expression = findNode.variableDeclaration('x =').initializer;
+
+    var evaluator = ConstantEvaluator(
+      file.createSource(result.uri),
+      result.typeProvider,
+      typeSystem: result.typeSystem,
+    );
+
+    return evaluator.evaluate(expression);
   }
 }
diff --git a/pkg/analyzer/test/generated/declaration_resolver_test.dart b/pkg/analyzer/test/generated/declaration_resolver_test.dart
index cf9bb77..db29c01 100644
--- a/pkg/analyzer/test/generated/declaration_resolver_test.dart
+++ b/pkg/analyzer/test/generated/declaration_resolver_test.dart
@@ -10,20 +10,19 @@
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/element.dart';
 import 'package:analyzer/src/generated/declaration_resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/task/api/dart.dart';
-import 'package:analyzer/src/task/dart.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import 'resolver_test_case.dart';
+import '../src/dart/resolution/driver_resolution.dart';
+import '../util/element_type_matchers.dart';
 import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(DeclarationResolverMetadataTest);
     defineReflectiveTests(DeclarationResolverTest);
-    defineReflectiveTests(StrongModeDeclarationResolverTest);
   });
 }
 
@@ -33,16 +32,8 @@
   return clonedUnit;
 }
 
-SimpleIdentifier _findSimpleIdentifier(
-    AstNode root, String code, String search) {
-  return EngineTestCase.findNode(
-      root, code, search, (n) => n is SimpleIdentifier);
-}
-
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class DeclarationResolverMetadataTest extends ResolverTestCase {
+class DeclarationResolverMetadataTest extends DriverResolutionTest {
   String code;
   CompilationUnit unit;
   CompilationUnit unit2;
@@ -62,53 +53,57 @@
 
   Future<void> setupCode(String code) async {
     this.code = code;
-    unit = await resolveSource(code + ' const a = null;');
+
+    addTestFile(code + ' const a = null;');
+    await resolveTestFile();
+
+    unit = result.unit;
     unit2 = _cloneResolveUnit(unit);
   }
 
-  test_metadata_classDeclaration() async {
+  test_classDeclaration() async {
     await setupCode('@a class C {}');
     checkMetadata('C');
   }
 
-  test_metadata_classTypeAlias() async {
+  test_classTypeAlias() async {
     await setupCode('@a class C = D with E; class D {} class E {}');
     checkMetadata('C');
   }
 
-  test_metadata_constructorDeclaration_named() async {
+  test_constructorDeclaration_named() async {
     await setupCode('class C { @a C.x(); }');
     checkMetadata('x');
   }
 
-  test_metadata_constructorDeclaration_unnamed() async {
+  test_constructorDeclaration_unnamed() async {
     await setupCode('class C { @a C(); }');
     checkMetadata('C()');
   }
 
-  test_metadata_declaredIdentifier() async {
+  test_declaredIdentifier() async {
     await setupCode('f(x, y) { for (@a var x in y) {} }');
     checkMetadata('var', expectDifferent: true);
   }
 
-  test_metadata_enumDeclaration() async {
+  test_enumDeclaration() async {
     await setupCode('@a enum E { v }');
     checkMetadata('E');
   }
 
-  test_metadata_enumDeclaration_constant() async {
+  test_enumDeclaration_constant() async {
     await setupCode('enum E { @a v }');
     checkMetadata('v');
   }
 
-  test_metadata_exportDirective() async {
-    addNamedSource('/foo.dart', 'class C {}');
+  test_exportDirective() async {
+    newFile('/test/lib/foo.dart', content: 'class C {}');
     await setupCode('@a export "foo.dart";');
     checkMetadata('export');
   }
 
-  test_metadata_exportDirective_resynthesized() async {
-    CompilationUnit unit = await resolveSource(r'''
+  test_exportDirective_resynthesized() async {
+    addTestFile(r'''
 @a
 export "dart:async";
 
@@ -118,15 +113,20 @@
 const a = null;
 const b = null;
 ''');
+    await resolveTestFile();
+    unit = result.unit;
+
     expect(unit.directives[0].metadata.single.name.name, 'a');
     expect(unit.directives[1].metadata.single.name.name, 'b');
     var unitElement = unit.declaredElement as CompilationUnitElementImpl;
+
     // Damage the unit element - as if "setAnnotations" were not called.
     // The ExportElement(s) still have the metadata, we should use it.
     unitElement.setAnnotations(unit.directives[0].offset, []);
     unitElement.setAnnotations(unit.directives[1].offset, []);
     expect(unitElement.library.exports[0].metadata, hasLength(1));
     expect(unitElement.library.exports[1].metadata, hasLength(1));
+
     // DeclarationResolver on the clone should succeed.
     CompilationUnit clonedUnit = AstCloner.clone(unit);
     new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
@@ -134,70 +134,59 @@
     expect(unit.directives[1].metadata.single.name.name, 'b');
   }
 
-  test_metadata_fieldDeclaration() async {
+  test_fieldDeclaration() async {
     await setupCode('class C { @a int x; }');
     checkMetadata('x');
   }
 
-  test_metadata_fieldFormalParameter() async {
+  test_fieldFormalParameter() async {
     await setupCode('class C { var x; C(@a this.x); }');
     checkMetadata('this');
   }
 
-  test_metadata_fieldFormalParameter_withDefault() async {
+  test_fieldFormalParameter_withDefault() async {
     await setupCode('class C { var x; C([@a this.x = null]); }');
     checkMetadata('this');
   }
 
-  test_metadata_functionDeclaration_function() async {
+  test_functionDeclaration_function() async {
     await setupCode('@a f() {}');
     checkMetadata('f');
   }
 
-  test_metadata_functionDeclaration_getter() async {
+  test_functionDeclaration_getter() async {
     await setupCode('@a get f() => null;');
     checkMetadata('f');
   }
 
-  test_metadata_functionDeclaration_setter() async {
+  test_functionDeclaration_setter() async {
     await setupCode('@a set f(value) {}');
     checkMetadata('f');
   }
 
-  test_metadata_functionTypeAlias() async {
+  test_functionTypeAlias() async {
     await setupCode('@a typedef F();');
     checkMetadata('F');
   }
 
-  test_metadata_functionTypedFormalParameter() async {
+  test_functionTypedFormalParameter() async {
     await setupCode('f(@a g()) {}');
     checkMetadata('g');
   }
 
-  test_metadata_functionTypedFormalParameter_withDefault() async {
+  test_functionTypedFormalParameter_withDefault() async {
     await setupCode('f([@a g() = null]) {}');
     checkMetadata('g');
   }
 
-  test_metadata_importDirective() async {
-    addNamedSource('/foo.dart', 'class C {}');
+  test_importDirective() async {
+    newFile('/test/lib/foo.dart', content: 'class C {}');
     await setupCode('@a import "foo.dart";');
     checkMetadata('import');
   }
 
-  test_metadata_importDirective_partiallyResolved() async {
-    addNamedSource('/foo.dart', 'class C {}');
-    this.code = 'const a = null; @a import "foo.dart";';
-    Source source = addNamedSource('/test.dart', code);
-    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    analysisContext.computeResult(source, LIBRARY_ELEMENT1);
-    unit = analysisContext.computeResult(target, RESOLVED_UNIT1);
-    unit2 = _cloneResolveUnit(unit);
-    checkMetadata('import');
-  }
-
-  test_metadata_importDirective_resynthesized() async {
-    CompilationUnit unit = await resolveSource(r'''
+  test_importDirective_resynthesized() async {
+    addTestFile(r'''
 @a
 import "dart:async";
 
@@ -207,15 +196,20 @@
 const a = null;
 const b = null;
 ''');
+    await resolveTestFile();
+    unit = result.unit;
+
     expect(unit.directives[0].metadata.single.name.name, 'a');
     expect(unit.directives[1].metadata.single.name.name, 'b');
     var unitElement = unit.declaredElement as CompilationUnitElementImpl;
+
     // Damage the unit element - as if "setAnnotations" were not called.
     // The ImportElement(s) still have the metadata, we should use it.
     unitElement.setAnnotations(unit.directives[0].offset, []);
     unitElement.setAnnotations(unit.directives[1].offset, []);
     expect(unitElement.library.imports[0].metadata, hasLength(1));
     expect(unitElement.library.imports[1].metadata, hasLength(1));
+
     // DeclarationResolver on the clone should succeed.
     CompilationUnit clonedUnit = AstCloner.clone(unit);
     new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
@@ -223,70 +217,75 @@
     expect(unit.directives[1].metadata.single.name.name, 'b');
   }
 
-  test_metadata_libraryDirective() async {
+  test_libraryDirective() async {
     await setupCode('@a library L;');
     checkMetadata('L');
   }
 
-  test_metadata_libraryDirective_resynthesized() async {
-    CompilationUnit unit = await resolveSource('@a library L; const a = null;');
+  test_libraryDirective_resynthesized() async {
+    addTestFile('@a library L; const a = null;');
+    await resolveTestFile();
+    unit = result.unit;
+
     expect(unit.directives.single.metadata.single.name.name, 'a');
     var unitElement = unit.declaredElement as CompilationUnitElementImpl;
+
     // Damage the unit element - as if "setAnnotations" were not called.
     // The LibraryElement still has the metadata, we should use it.
     unitElement.setAnnotations(unit.directives.single.offset, []);
     expect(unitElement.library.metadata, hasLength(1));
+
     // DeclarationResolver on the clone should succeed.
     CompilationUnit clonedUnit = AstCloner.clone(unit);
     new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
     expect(clonedUnit.directives.single.metadata.single.name.name, 'a');
   }
 
-  test_metadata_localFunctionDeclaration() async {
+  test_localFunctionDeclaration() async {
     await setupCode('f() { @a g() {} }');
     // Note: metadata on local function declarations is ignored by the
     // analyzer.  TODO(paulberry): is this a bug?
     FunctionDeclaration node = EngineTestCase.findNode(
         unit, code, 'g', (AstNode n) => n is FunctionDeclaration);
     NodeList<Annotation> metadata = (node as FunctionDeclarationImpl).metadata;
-    if (usingFastaParser) {
+    if (Parser.useFasta) {
       expect(metadata, hasLength(1));
     } else {
       expect(metadata, isEmpty);
     }
   }
 
-  test_metadata_localVariableDeclaration() async {
+  test_localVariableDeclaration() async {
     await setupCode('f() { @a int x; }');
     checkMetadata('x', expectDifferent: true);
   }
 
-  test_metadata_methodDeclaration_getter() async {
+  test_methodDeclaration_getter() async {
     await setupCode('class C { @a get m => null; }');
     checkMetadata('m');
   }
 
-  test_metadata_methodDeclaration_method() async {
+  test_methodDeclaration_method() async {
     await setupCode('class C { @a m() {} }');
     checkMetadata('m');
   }
 
-  test_metadata_methodDeclaration_setter() async {
+  test_methodDeclaration_setter() async {
     await setupCode('class C { @a set m(value) {} }');
     checkMetadata('m');
   }
 
-  test_metadata_partDirective() async {
-    addNamedSource('/foo.dart', 'part of L;');
+  test_partDirective() async {
+    newFile('/test/lib/foo.dart', content: 'part of L;');
     await setupCode('library L; @a part "foo.dart";');
     checkMetadata('part');
   }
 
-  test_metadata_partDirective_resynthesized() async {
-    addNamedSource('/part_a.dart', 'part of L;');
-    addNamedSource('/part_b.dart', 'part of L;');
+  test_partDirective_resynthesized() async {
+    newFile('/test/lib/part_a.dart', content: 'part of L;');
+    newFile('/test/lib/part_b.dart', content: 'part of L;');
 
-    CompilationUnit unit = await resolveSource(r'''
+    addTestFile(r'''
 library L;
 
 @a
@@ -298,15 +297,20 @@
 const a = null;
 const b = null;
 ''');
+    await resolveTestFile();
+    unit = result.unit;
+
     expect(unit.directives[1].metadata.single.name.name, 'a');
     expect(unit.directives[2].metadata.single.name.name, 'b');
     var unitElement = unit.declaredElement as CompilationUnitElementImpl;
+
     // Damage the unit element - as if "setAnnotations" were not called.
     // The ImportElement(s) still have the metadata, we should use it.
     unitElement.setAnnotations(unit.directives[1].offset, []);
     unitElement.setAnnotations(unit.directives[2].offset, []);
     expect(unitElement.library.parts[0].metadata, hasLength(1));
     expect(unitElement.library.parts[1].metadata, hasLength(1));
+
     // DeclarationResolver on the clone should succeed.
     CompilationUnit clonedUnit = AstCloner.clone(unit);
     new DeclarationResolver().resolve(clonedUnit, unit.declaredElement);
@@ -314,37 +318,37 @@
     expect(unit.directives[2].metadata.single.name.name, 'b');
   }
 
-  test_metadata_simpleFormalParameter() async {
+  test_simpleFormalParameter() async {
     await setupCode('f(@a x) {}) {}');
     checkMetadata('x');
   }
 
-  test_metadata_simpleFormalParameter_withDefault() async {
+  test_simpleFormalParameter_withDefault() async {
     await setupCode('f([@a x = null]) {}');
     checkMetadata('x');
   }
 
-  test_metadata_topLevelVariableDeclaration() async {
+  test_topLevelVariableDeclaration() async {
     await setupCode('@a int x;');
     checkMetadata('x');
   }
 
-  test_metadata_typeParameter_ofClass() async {
+  test_typeParameter_ofClass() async {
     await setupCode('class C<@a T> {}');
     checkMetadata('T');
   }
 
-  test_metadata_typeParameter_ofClassTypeAlias() async {
+  test_typeParameter_ofClassTypeAlias() async {
     await setupCode('class C<@a T> = D with E; class D {} class E {}');
     checkMetadata('T');
   }
 
-  test_metadata_typeParameter_ofFunction() async {
+  test_typeParameter_ofFunction() async {
     await setupCode('f<@a T>() {}');
     checkMetadata('T');
   }
 
-  test_metadata_typeParameter_ofTypedef() async {
+  test_typeParameter_ofTypedef() async {
     await setupCode('typedef F<@a T>();');
     checkMetadata('T');
   }
@@ -365,32 +369,25 @@
   }
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class DeclarationResolverTest extends ResolverTestCase {
-  @override
-  void setUp() {
-    super.setUp();
-  }
-
+class DeclarationResolverTest extends DriverResolutionTest {
   test_closure_inside_catch_block() async {
-    String code = '''
+    addTestFile('''
 f() {
   try {
   } catch (e) {
     return () => null;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_labeled_statement() async {
-    String code = '''
+    addTestFile('''
 f(b) {
   foo: while (true) {
     if (b) {
@@ -399,15 +396,15 @@
     return () => null;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_switch_case() async {
-    String code = '''
+    addTestFile('''
 void f(k, m) {
   switch (k) {
     case 0:
@@ -415,15 +412,15 @@
     break;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_closure_inside_switch_default() async {
-    String code = '''
+    addTestFile('''
 void f(k, m) {
   switch (k) {
     default:
@@ -431,142 +428,132 @@
     break;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
-  test_enumConstant_partiallyResolved() async {
-    String code = r'''
-enum Fruit {apple, pear}
-''';
-    Source source = addNamedSource('/test.dart', code);
-    LibrarySpecificUnit target = new LibrarySpecificUnit(source, source);
-    analysisContext.computeResult(source, LIBRARY_ELEMENT1);
-    CompilationUnit unit =
-        analysisContext.computeResult(target, RESOLVED_UNIT1);
-    _cloneResolveUnit(unit);
-  }
-
   test_functionDeclaration_getter() async {
-    String code = r'''
+    addTestFile(r'''
 int get zzz => 42;
-''';
-    CompilationUnit unit = await resolveSource(code);
-    PropertyAccessorElement getterElement =
-        _findSimpleIdentifier(unit, code, 'zzz =>').staticElement;
+''');
+    await resolveTestFile();
+
+    var getterElement = findElement.topGet('zzz');
     expect(getterElement.isGetter, isTrue);
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var getterName = FindNode(result.content, unit2).simple('zzz =>');
     expect(getterName.staticElement, same(getterElement));
   }
 
   test_functionDeclaration_setter() async {
-    String code = r'''
+    addTestFile(r'''
 void set zzz(_) {}
-''';
-    CompilationUnit unit = await resolveSource(code);
-    PropertyAccessorElement setterElement =
-        _findSimpleIdentifier(unit, code, 'zzz(_)').staticElement;
+''');
+    await resolveTestFile();
+
+    var setterElement = findElement.topSet('zzz');
     expect(setterElement.isSetter, isTrue);
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz(_)');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var getterName = FindNode(result.content, unit2).simple('zzz(_)');
     expect(getterName.staticElement, same(setterElement));
   }
 
   test_genericFunction_asFunctionReturnType() async {
-    String code = r'''
+    addTestFile(r'''
 Function(int, String) f() => null;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asGenericFunctionReturnType() async {
-    String code = r'''
+    addTestFile(r'''
 typedef F<T> = int Function(T t, S s) Function<S>(int);
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asMethodReturnType() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   Function(int, String) m() => null;
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asParameterReturnType() async {
-    String code = r'''
+    addTestFile(r'''
 f(Function(int, String) p) => null;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTopLevelVariableType() async {
-    String code = r'''
+    addTestFile(r'''
 int Function(int, String) v;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument() async {
-    String code = r'''
+    addTestFile(r'''
 List<Function(int)> v;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_lessNodes() async {
-    String code = r'''
+    addTestFile(r'''
 Map<Function<int>> v;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_moreNodes() async {
-    String code = r'''
+    addTestFile(r'''
 List<Function<int>, Function<String>> v;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_genericFunction_asTypeArgument_noNodes() async {
-    String code = r'''
+    addTestFile(r'''
 List v;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
@@ -574,302 +561,253 @@
     String code = r'''
 var v = <Function(int)>[];
 ''';
-    CompilationUnit unit = await resolveSource(code);
-    CompilationUnit newUnit = _cloneResolveUnit(unit);
-    var v = newUnit.declarations[0] as TopLevelVariableDeclaration;
-    var initializer = v.variables.variables[0].initializer as ListLiteral;
+    addTestFile(code);
+    await resolveTestFile();
+
+    var newUnit = _cloneResolveUnit(result.unit);
+    var initializer = FindNode(result.content, newUnit).listLiteral('>[]');
     expect(initializer.typeArguments.arguments[0].type, isNotNull);
   }
 
   test_genericFunction_invalid_missingParameterName() async {
-    String code = r'''
+    addTestFile(r'''
 typedef F = Function({int});
-''';
-    CompilationUnit unit = await resolveSource(code);
-    _cloneResolveUnit(unit);
+''');
+    await resolveTestFile();
+    // re-resolve
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_invalid_functionDeclaration_getter_inFunction() async {
-    String code = r'''
+    addTestFile(r'''
 var v = (() {
   main() {
     int get zzz => 42;
   }
 });
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'zzz =>');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var getterName = FindNode(result.content, unit2).simple('zzz =>');
+
     // Local getters are not allowed, so a FunctionElement is created.
-    expect(getterName.staticElement, new TypeMatcher<FunctionElement>());
+    expect(getterName.staticElement, isFunctionElement);
   }
 
   test_invalid_functionDeclaration_setter_inFunction() async {
-    String code = r'''
+    addTestFile(r'''
 var v = (() {
   main() {
     set zzz(x) {}
   }
 });
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier setterName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var setterName = FindNode(result.content, unit2).simple('zzz(x)');
+
     // Local getters are not allowed, so a FunctionElement is created.
-    expect(setterName.staticElement, new TypeMatcher<FunctionElement>());
+    expect(setterName.staticElement, isFunctionElement);
   }
 
   test_visitExportDirective_notExistingSource() async {
-    String code = r'''
+    addTestFile(r'''
 export 'foo.dart';
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitExportDirective_unresolvedUri() async {
-    String code = r'''
+    addTestFile(r'''
 export 'package:foo/bar.dart';
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitFunctionExpression() async {
-    String code = r'''
+    addTestFile(r'''
 main(List<String> items) {
   items.forEach((item) {});
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_0() async {
-    String code = r'''
+    addTestFile(r'''
 typedef F<T> = Function<S>(List<S> list, Function<A>(A), T);
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_1() async {
-    String code = r'''
+    addTestFile(r'''
 typedef F = Function({int});
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitGenericTypeAlias_2() async {
-    String code = r'''
+    addTestFile(r'''
 typedef F = int;
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitImportDirective_notExistingSource() async {
-    String code = r'''
+    addTestFile(r'''
 import 'foo.dart';
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitImportDirective_unresolvedUri() async {
-    String code = r'''
+    addTestFile(r'''
 import 'package:foo/bar.dart';
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitMethodDeclaration_getter_duplicate() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   int get zzz => 1;
   String get zzz => null;
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    PropertyAccessorElement firstElement =
-        _findSimpleIdentifier(unit, code, 'zzz => 1').staticElement;
-    PropertyAccessorElement secondElement =
-        _findSimpleIdentifier(unit, code, 'zzz => null').staticElement;
+''');
+    await resolveTestFile();
+
+    var firstElement = findNode.simple('zzz => 1').staticElement;
+    var secondElement = findNode.simple('zzz => null').staticElement;
+    expect(firstElement, isNot(same(secondElement)));
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz => 1');
-    SimpleIdentifier secondName =
-        _findSimpleIdentifier(unit2, code, 'zzz => null');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var findNode2 = FindNode(result.content, unit2);
+    var firstName = findNode2.simple('zzz => 1');
+    var secondName = findNode2.simple('zzz => null');
     expect(firstName.staticElement, same(firstElement));
     expect(secondName.staticElement, same(secondElement));
   }
 
   test_visitMethodDeclaration_getterSetter() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   int _field = 0;
   int get field => _field;
   void set field(value) {_field = value;}
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    FieldElement getterElement =
-        _findSimpleIdentifier(unit, code, 'field =').staticElement;
-    PropertyAccessorElement setterElement =
-        _findSimpleIdentifier(unit, code, 'field(').staticElement;
+''');
+    await resolveTestFile();
+
+    var getterElement = findElement.getter('field');
+    var setterElement = findElement.setter('field');
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier getterName = _findSimpleIdentifier(unit2, code, 'field =');
-    SimpleIdentifier setterName = _findSimpleIdentifier(unit2, code, 'field(');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var findNode2 = FindNode(result.content, unit2);
+    var getterName = findNode2.simple('field =>');
+    var setterName = findNode2.simple('field(value)');
     expect(getterName.staticElement, same(getterElement));
     expect(setterName.staticElement, same(setterElement));
   }
 
   test_visitMethodDeclaration_method_duplicate() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   void zzz(x) {}
   void zzz(y) {}
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
-    MethodElement firstElement =
-        _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
-    MethodElement secondElement =
-        _findSimpleIdentifier(unit, code, 'zzz(y)').staticElement;
+''');
+    await resolveTestFile();
+
+    MethodElement firstElement = findNode.simple('zzz(x)').staticElement;
+    MethodElement secondElement = findNode.simple('zzz(y)').staticElement;
+    expect(firstElement, isNot(same(secondElement)));
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
-    SimpleIdentifier secondName = _findSimpleIdentifier(unit2, code, 'zzz(y)');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var findNode2 = FindNode(result.content, unit2);
+    var firstName = findNode2.simple('zzz(x)');
+    var secondName = findNode2.simple('zzz(y)');
     expect(firstName.staticElement, same(firstElement));
     expect(secondName.staticElement, same(secondElement));
   }
 
   test_visitMethodDeclaration_setter_duplicate() async {
     // https://github.com/dart-lang/sdk/issues/25601
-    String code = r'''
+    addTestFile(r'''
 class C {
   set zzz(x) {}
   set zzz(y) {}
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
+
     PropertyAccessorElement firstElement =
-        _findSimpleIdentifier(unit, code, 'zzz(x)').staticElement;
+        findNode.simple('zzz(x)').staticElement;
     PropertyAccessorElement secondElement =
-        _findSimpleIdentifier(unit, code, 'zzz(y)').staticElement;
+        findNode.simple('zzz(y)').staticElement;
+    expect(firstElement, isNot(same(secondElement)));
+
     // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    SimpleIdentifier firstName = _findSimpleIdentifier(unit2, code, 'zzz(x)');
-    SimpleIdentifier secondName = _findSimpleIdentifier(unit2, code, 'zzz(y)');
+    var unit2 = _cloneResolveUnit(result.unit);
+    var findNode2 = FindNode(result.content, unit2);
+    var firstName = findNode2.simple('zzz(x)');
+    var secondName = findNode2.simple('zzz(y)');
     expect(firstName.staticElement, same(firstElement));
     expect(secondName.staticElement, same(secondElement));
   }
 
   test_visitMethodDeclaration_unaryMinus() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   C operator -() => null;
   C operator -(C other) => null;
 }
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 
   test_visitPartDirective_notExistingSource() async {
-    String code = r'''
+    addTestFile(r'''
 part 'foo.bar';
-''';
-    CompilationUnit unit = await resolveSource(code);
+''');
+    await resolveTestFile();
     // re-resolve
-    _cloneResolveUnit(unit);
+    _cloneResolveUnit(result.unit);
     // no other validations than built into DeclarationResolver
   }
 }
-
-/**
- * Strong mode DeclarationResolver tests
- * TODO(paulberry): migrate this test away from the task model.
- * See dartbug.com/35734.
- */
-@reflectiveTest
-class StrongModeDeclarationResolverTest extends ResolverTestCase {
-  @override
-  void setUp() {
-    reset();
-  }
-
-  test_genericFunction_typeParameter() async {
-    // Fasta ignores generic type comments
-    if (usingFastaParser) return;
-    String code = r'''
-/*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
-''';
-    CompilationUnit unit = await resolveSource(code);
-    FunctionDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
-    TypeParameter t = node.functionExpression.typeParameters.typeParameters[0];
-
-    FunctionElement element = node.name.staticElement;
-    TypeParameterElement tElement = element.typeParameters[0];
-    expect(tElement, isNotNull);
-    expect(element.typeParameters.toString(), "[T]");
-    expect(element.type.toString(), "<T>(T, T) → T");
-    expect(t.declaredElement, same(tElement));
-
-    // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    node = _findSimpleIdentifier(unit2, code, 'max').parent;
-    t = node.functionExpression.typeParameters.typeParameters[0];
-    expect(t.declaredElement, same(tElement));
-  }
-
-  test_genericMethod_typeParameter() async {
-    // Fasta ignores generic type comments
-    if (usingFastaParser) return;
-    String code = r'''
-class C {
-  /*=T*/ max/*<T>*/(/*=T*/ x, /*=T*/ y) => null;
-}
-''';
-    CompilationUnit unit = await resolveSource(code);
-    MethodDeclaration node = _findSimpleIdentifier(unit, code, 'max').parent;
-    TypeParameter t = node.typeParameters.typeParameters[0];
-
-    MethodElement element = node.name.staticElement;
-    TypeParameterElement tElement = element.typeParameters[0];
-    expect(tElement, isNotNull);
-    expect(element.typeParameters.toString(), "[T]");
-    expect(element.type.toString(), "<T>(T, T) → T");
-    expect(t.declaredElement, same(tElement));
-
-    // re-resolve
-    CompilationUnit unit2 = _cloneResolveUnit(unit);
-    node = _findSimpleIdentifier(unit2, code, 'max').parent;
-    t = node.typeParameters.typeParameters[0];
-    expect(t.declaredElement, same(tElement));
-  }
-}
diff --git a/pkg/analyzer/test/generated/element_resolver_test.dart b/pkg/analyzer/test/generated/element_resolver_test.dart
index 4987c63..4808365 100644
--- a/pkg/analyzer/test/generated/element_resolver_test.dart
+++ b/pkg/analyzer/test/generated/element_resolver_test.dart
@@ -23,6 +23,8 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../src/dart/resolution/driver_resolution.dart';
+import '../util/element_type_matchers.dart';
 import '../utils.dart';
 import 'analysis_context_factory.dart';
 import 'resolver_test_case.dart';
@@ -30,16 +32,12 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ElementResolverCodeTest);
+    defineReflectiveTests(AnnotationElementResolverTest);
     defineReflectiveTests(ElementResolverTest);
     defineReflectiveTests(PreviewDart2Test);
   });
 }
 
-const _isClassElement = const TypeMatcher<ClassElement>();
-
-const _isConstructorElement = const TypeMatcher<ConstructorElement>();
-
 /// Wrapper around the test package's `fail` function.
 ///
 /// Unlike the test package's `fail` function, this function is not annotated
@@ -49,12 +47,10 @@
   fail(message);
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class ElementResolverCodeTest extends ResolverTestCase {
-  test_annotation_class_namedConstructor() async {
-    addNamedSource('/a.dart', r'''
+class AnnotationElementResolverTest extends DriverResolutionTest {
+  test_class_namedConstructor() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   const A.named();
 }
@@ -64,10 +60,10 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<ClassElement>());
+      expect(name1.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<ConstructorElement>());
+      expect(name2.staticElement, isConstructorElement);
       expect(
           resolutionMap.staticElementForIdentifier(name2).displayName, 'named');
       expect(name3, isNull);
@@ -83,8 +79,8 @@
     });
   }
 
-  test_annotation_class_prefixed_namedConstructor() async {
-    addNamedSource('/a.dart', r'''
+  test_class_prefixed_namedConstructor() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   const A.named();
 }
@@ -94,13 +90,13 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<PrefixElement>());
+      expect(name1.staticElement, isPrefixElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<ClassElement>());
+      expect(name2.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
       expect(name3, isNotNull);
-      expect(name3.staticElement, new TypeMatcher<ConstructorElement>());
+      expect(name3.staticElement, isConstructorElement);
       expect(
           resolutionMap.staticElementForIdentifier(name3).displayName, 'named');
       if (annotationElement is ConstructorElement) {
@@ -115,8 +111,8 @@
     });
   }
 
-  test_annotation_class_prefixed_staticConstField() async {
-    addNamedSource('/a.dart', r'''
+  test_class_prefixed_staticConstField() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   static const V = 0;
 }
@@ -126,13 +122,13 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<PrefixElement>());
+      expect(name1.staticElement, isPrefixElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<ClassElement>());
+      expect(name2.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
       expect(name3, isNotNull);
-      expect(name3.staticElement, new TypeMatcher<PropertyAccessorElement>());
+      expect(name3.staticElement, isPropertyAccessorElement);
       expect(resolutionMap.staticElementForIdentifier(name3).displayName, 'V');
       if (annotationElement is PropertyAccessorElement) {
         expect(annotationElement, same(name3.staticElement));
@@ -145,8 +141,8 @@
     });
   }
 
-  test_annotation_class_prefixed_unnamedConstructor() async {
-    addNamedSource('/a.dart', r'''
+  test_class_prefixed_unnamedConstructor() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   const A();
 }
@@ -156,10 +152,10 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<PrefixElement>());
+      expect(name1.staticElement, isPrefixElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<ClassElement>());
+      expect(name2.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'A');
       expect(name3, isNull);
       if (annotationElement is ConstructorElement) {
@@ -173,8 +169,8 @@
     });
   }
 
-  test_annotation_class_staticConstField() async {
-    addNamedSource('/a.dart', r'''
+  test_class_staticConstField() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   static const V = 0;
 }
@@ -184,10 +180,10 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<ClassElement>());
+      expect(name1.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<PropertyAccessorElement>());
+      expect(name2.staticElement, isPropertyAccessorElement);
       expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'V');
       expect(name3, isNull);
       if (annotationElement is PropertyAccessorElement) {
@@ -201,8 +197,8 @@
     });
   }
 
-  test_annotation_class_unnamedConstructor() async {
-    addNamedSource('/a.dart', r'''
+  test_class_unnamedConstructor() async {
+    newFile('/test/lib/a.dart', content: r'''
 class A {
   const A();
 }
@@ -212,7 +208,7 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<ClassElement>());
+      expect(name1.staticElement, isClassElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'A');
       expect(name2, isNull);
       expect(name3, isNull);
@@ -227,8 +223,8 @@
     });
   }
 
-  test_annotation_topLevelVariable() async {
-    addNamedSource('/a.dart', r'''
+  test_topLevelVariable() async {
+    newFile('/test/lib/a.dart', content: r'''
 const V = 0;
 ''');
     await _validateAnnotation('', '@V', (SimpleIdentifier name1,
@@ -236,14 +232,13 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<PropertyAccessorElement>());
+      expect(name1.staticElement, isPropertyAccessorElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'V');
       expect(name2, isNull);
       expect(name3, isNull);
       if (annotationElement is PropertyAccessorElement) {
         expect(annotationElement, same(name1.staticElement));
-        expect(annotationElement.enclosingElement,
-            new TypeMatcher<CompilationUnitElement>());
+        expect(annotationElement.enclosingElement, isCompilationUnitElement);
         expect(annotationElement.displayName, 'V');
       } else {
         fail('Expected "annotationElement" is PropertyAccessorElement, '
@@ -252,8 +247,8 @@
     });
   }
 
-  test_annotation_topLevelVariable_prefixed() async {
-    addNamedSource('/a.dart', r'''
+  test_topLevelVariable_prefixed() async {
+    newFile('/test/lib/a.dart', content: r'''
 const V = 0;
 ''');
     await _validateAnnotation('as p', '@p.V', (SimpleIdentifier name1,
@@ -261,16 +256,15 @@
         SimpleIdentifier name3,
         Element annotationElement) {
       expect(name1, isNotNull);
-      expect(name1.staticElement, new TypeMatcher<PrefixElement>());
+      expect(name1.staticElement, isPrefixElement);
       expect(resolutionMap.staticElementForIdentifier(name1).displayName, 'p');
       expect(name2, isNotNull);
-      expect(name2.staticElement, new TypeMatcher<PropertyAccessorElement>());
+      expect(name2.staticElement, isPropertyAccessorElement);
       expect(resolutionMap.staticElementForIdentifier(name2).displayName, 'V');
       expect(name3, isNull);
       if (annotationElement is PropertyAccessorElement) {
         expect(annotationElement, same(name2.staticElement));
-        expect(annotationElement.enclosingElement,
-            new TypeMatcher<CompilationUnitElement>());
+        expect(annotationElement.enclosingElement, isCompilationUnitElement);
         expect(annotationElement.displayName, 'V');
       } else {
         fail('Expected "annotationElement" is PropertyAccessorElement, '
@@ -284,12 +278,14 @@
       String annotationText,
       validator(SimpleIdentifier name1, SimpleIdentifier name2,
           SimpleIdentifier name3, Element annotationElement)) async {
-    CompilationUnit unit = await resolveSource('''
+    addTestFile('''
 import 'a.dart' $annotationPrefix;
 $annotationText
 class C {}
 ''');
-    var clazz = unit.declarations.single as ClassDeclaration;
+    await resolveTestFile();
+
+    var clazz = findNode.classDeclaration('C');
     Annotation annotation = clazz.metadata.single;
     Identifier name = annotation.name;
     Element annotationElement = annotation.element;
@@ -1289,13 +1285,13 @@
     ExpressionStatement statement = statements[0];
     InstanceCreationExpression creation = statement.expression;
 
-    expect(creation.staticElement, _isConstructorElement);
+    expect(creation.staticElement, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
-    expect(creation.constructorName.staticElement, _isConstructorElement);
+    expect(creation.constructorName.staticElement, isConstructorElement);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
   }
@@ -1323,13 +1319,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
 
@@ -1361,13 +1357,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
 
@@ -1397,13 +1393,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name.staticElement, constructor);
   }
@@ -1435,13 +1431,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
   }
@@ -1472,13 +1468,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name.staticElement, constructor);
 
@@ -1517,13 +1513,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
   }
@@ -1552,13 +1548,13 @@
     InstanceCreationExpression creation = statement.expression;
     ConstructorElement constructor = creation.staticElement;
 
-    expect(constructor, _isConstructorElement);
+    expect(constructor, isConstructorElement);
     expect(creation.staticType, isNotNull);
 
     expect(creation.constructorName.staticElement, constructor);
 
     expect(creation.constructorName.type.type, isNotNull);
-    expect(creation.constructorName.type.name.staticElement, _isClassElement);
+    expect(creation.constructorName.type.name.staticElement, isClassElement);
 
     expect(creation.constructorName.name, isNull);
   }
@@ -1577,7 +1573,7 @@
     MethodInvocation invocation = statement.expression;
 
     SimpleIdentifier prefix = invocation.target;
-    expect(prefix.staticElement, new TypeMatcher<PrefixElement>());
+    expect(prefix.staticElement, isPrefixElement);
 
     expect(invocation.methodName.name, 'max');
   }
diff --git a/pkg/analyzer/test/generated/hint_code_test.dart b/pkg/analyzer/test/generated/hint_code_test.dart
index 7f1d918..6695ba9 100644
--- a/pkg/analyzer/test/generated/hint_code_test.dart
+++ b/pkg/analyzer/test/generated/hint_code_test.dart
@@ -2,14 +2,12 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-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/engine.dart';
 import 'package:analyzer/src/generated/parser.dart';
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer/src/task/options.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../src/util/yaml_test.dart';
@@ -3120,1800 +3118,4 @@
     assertErrors(source, [StrongModeCode.DOWN_CAST_COMPOSITE]);
     verify([source]);
   }
-
-  test_strongMode_topLevelInstanceGetter() async {
-    Source source = addSource('''
-class A {
-  int get g => 0;
-}
-var b = new A().g;
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[1];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_call() async {
-    Source source = addSource('''
-class A {
-  int Function() get g => () => 0;
-}
-var a = new A();
-var b = a.g();
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_field() async {
-    Source source = addSource('''
-class A {
-  int g;
-}
-var b = new A().g;
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[1];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_field_call() async {
-    Source source = addSource('''
-class A {
-  int Function() g;
-}
-var a = new A();
-var b = a.g();
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_field_prefixedIdentifier() async {
-    Source source = addSource('''
-class A {
-  int g;
-}
-var a = new A();
-var b = a.g;
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped() async {
-    Source source = addSource('''
-class A {
-  get g => 0;
-}
-var b = new A().g;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_call() async {
-    Source source = addSource('''
-class A {
-  get g => () => 0;
-}
-var a = new A();
-var b = a.g();
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_field() async {
-    Source source = addSource('''
-class A {
-  var g = 0;
-}
-var b = new A().g;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_field_call() async {
-    Source source = addSource('''
-class A {
-  var g = () => 0;
-}
-var a = new A();
-var b = a.g();
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_field_prefixedIdentifier() async {
-    Source source = addSource('''
-class A {
-  var g = 0;
-}
-var a = new A();
-var b = a.g;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_fn() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-int f<T>(x) => 0;
-var a = new A();
-var b = f(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
-    // generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_fn_explicit_type_params() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-int f<T>(x) => 0;
-var a = new A();
-var b = f<int>(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_fn_not_generic() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-int f(x) => 0;
-var a = new A();
-var b = f(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_indexExpression() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-  int operator[](int value) => 0;
-}
-var a = new A();
-var b = a[a.x];
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = (<T>(y) => 0)(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the
-    // closure is generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke_explicit_type_params() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = (<T>(y) => 0)<int>(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_invoke_not_generic() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = ((y) => 0)(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_method() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-  int f<T>(int x) => 0;
-}
-var a = new A();
-var b = a.f(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
-    // generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_method_explicit_type_params() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-  int f<T>(x) => 0;
-}
-var a = new A();
-var b = a.f<int>(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_method_not_generic() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-  int f(x) => 0;
-}
-var a = new A();
-var b = a.f(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B<T> {
-  B(x);
-}
-var a = new A();
-var b = new B(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
-    // generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_explicit_type_params() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B<T> {
-  B(x);
-}
-var a = new A();
-var b = new B<int>(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_explicit_type_params_named() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B<T> {
-  B.named(x);
-}
-var a = new A();
-var b = new B<int>.named(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_explicit_type_params_prefixed() async {
-    addNamedSource('/lib1.dart', '''
-class B<T> {
-  B(x);
-}
-''');
-    Source source = addSource('''
-import 'lib1.dart' as foo;
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = new foo.B<int>(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_named() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B<T> {
-  B.named(x);
-}
-var a = new A();
-var b = new B.named(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
-    // generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_not_generic() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B {
-  B(x);
-}
-var a = new A();
-var b = new B(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_not_generic_named() async {
-    Source source = addSource('''
-class A {
-  var x = 0;
-}
-class B {
-  B.named(x);
-}
-var a = new A();
-var b = new B.named(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_not_generic_prefixed() async {
-    addNamedSource('/lib1.dart', '''
-class B {
-  B(x);
-}
-''');
-    Source source = addSource('''
-import 'lib1.dart' as foo;
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = new foo.B(a.x);
-''');
-    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
-    // it can't possibly affect the type of b.
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_new_prefixed() async {
-    addNamedSource('/lib1.dart', '''
-class B<T> {
-  B(x);
-}
-''');
-    Source source = addSource('''
-import 'lib1.dart' as foo;
-class A {
-  var x = 0;
-}
-var a = new A();
-var b = new foo.B(a.x);
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
-    // generic, so the type of a.x might affect the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_prefixedIdentifier() async {
-    Source source = addSource('''
-class A {
-  get g => 0;
-}
-var a = new A();
-var b = a.g;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_implicitlyTyped_propertyAccessLhs() async {
-    Source source = addSource('''
-class A {
-  var x = new B();
-  int operator[](int value) => 0;
-}
-class B {
-  int y;
-}
-var a = new A();
-var b = (a.x).y;
-''');
-    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the type
-    // of a.x affects the lookup of y, which in turn affects the type of b.
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceGetter_prefixedIdentifier() async {
-    Source source = addSource('''
-class A {
-  int get g => 0;
-}
-var a = new A();
-var b = a.g;
-''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    TopLevelVariableDeclaration b = analysisResult.unit.declarations[2];
-    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod() async {
-    Source source = addSource('''
-class A {
-  f() => 0;
-}
-var x = new A().f();
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_parameter() async {
-    Source source = addSource('''
-class A {
-  int f(v) => 0;
-}
-var x = new A().f(0);
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_parameter_generic() async {
-    Source source = addSource('''
-class A {
-  int f<T>(v) => 0;
-}
-var x = new A().f(0);
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_parameter_generic_explicit() async {
-    Source source = addSource('''
-class A {
-  int f<T>(v) => 0;
-}
-var x = new A().f<int>(0);
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_static() async {
-    Source source = addSource('''
-class A {
-  static f() => 0;
-}
-var x = A.f();
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_tearoff() async {
-    Source source = addSource('''
-class A {
-  f() => 0;
-}
-var x = new A().f;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_tearoff_parameter() async {
-    Source source = addSource('''
-class A {
-  int f(v) => 0;
-}
-var x = new A().f;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
-    verify([source]);
-  }
-
-  test_strongMode_topLevelInstanceMethod_tearoff_static() async {
-    Source source = addSource('''
-class A {
-  static f() => 0;
-}
-var x = A.f;
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_typeCheck_type_is_Null() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is Null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.TYPE_CHECK_IS_NULL]);
-    verify([source]);
-  }
-
-  test_typeCheck_type_not_Null() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is! Null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.TYPE_CHECK_IS_NOT_NULL]);
-    verify([source]);
-  }
-
-  test_undefinedGetter() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    return a.m;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
-  test_undefinedIdentifier_exportHide() async {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart' hide a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNDEFINED_HIDDEN_NAME]);
-    verify([source]);
-  }
-
-  test_undefinedIdentifier_exportShow() async {
-    Source source = addSource(r'''
-library L;
-export 'lib1.dart' show a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNDEFINED_SHOWN_NAME]);
-    verify([source]);
-  }
-
-  test_undefinedIdentifier_importHide() async {
-    Source source = addSource(r'''
-library L;
-import 'lib1.dart' hide a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_HIDDEN_NAME]);
-    verify([source]);
-  }
-
-  test_undefinedIdentifier_importShow() async {
-    Source source = addSource(r'''
-library L;
-import 'lib1.dart' show a;''');
-    addNamedSource("/lib1.dart", "library lib1;");
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_SHOWN_NAME]);
-    verify([source]);
-  }
-
-  test_undefinedOperator_binaryExpression() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a + 1;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_indexBoth() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a[0]++;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-    ]);
-  }
-
-  test_undefinedOperator_indexGetter() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a[0];
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_indexSetter() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a[0] = 1;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_postfixExpression() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a++;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-  }
-
-  test_undefinedOperator_prefixExpression() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    ++a;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-  }
-
-  test_undefinedSetter() async {
-    Source source = addSource(r'''
-class A {}
-f(var a) {
-  if(a is A) {
-    a.m = 0;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
-  }
-
-  test_unnecessaryNoSuchMethod_blockBody() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) {
-    return super.noSuchMethod(y);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
-    verify([source]);
-  }
-
-  test_unnecessaryNoSuchMethod_expressionBody() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) => super.noSuchMethod(y);
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_null_is_Null() async {
-    Source source = addSource("bool b = null is Null;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_null_not_Null() async {
-    Source source = addSource("bool b = null is! Null;");
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_type_is_dynamic() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is dynamic;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_type_is_object() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is Object;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_type_not_dynamic() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is! dynamic;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
-    verify([source]);
-  }
-
-  test_unnecessaryTypeCheck_type_not_object() async {
-    Source source = addSource(r'''
-m(i) {
-  bool b = i is! Object;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_extends() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-class B extends _A {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_fieldDeclaration() async {
-    enableUnusedElement = true;
-    var src = r'''
-class Foo {
-  _Bar x;
-}
-
-class _Bar {
-}
-''';
-    Source source = addSource(src);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_implements() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-class B implements _A {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_instanceCreation() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main() {
-  new _A();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_staticFieldAccess() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  static const F = 42;
-}
-main() {
-  _A.F;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_staticMethodInvocation() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  static m() {}
-}
-main() {
-  _A.m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_isUsed_typeArgument() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main() {
-  var v = new List<_A>();
-  print(v);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_class_notUsed_inClassMember() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  static staticMethod() {
-    new _A();
-  }
-  instanceMethod() {
-    new _A();
-  }
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_class_notUsed_inConstructorName() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {
-  _A() {}
-  _A.named() {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_class_notUsed_isExpression() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main(p) {
-  if (p is _A) {
-  }
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_class_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_class_notUsed_variableDeclaration() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class _A {}
-main() {
-  _A v;
-  print(v);
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_enum_isUsed_fieldReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-enum _MyEnum {A, B, C}
-main() {
-  print(_MyEnum.B);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_enum_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-enum _MyEnum {A, B, C}
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_functionLocal_isUsed_closure() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-main() {
-  print(() {});
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionLocal_isUsed_invocation() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-main() {
-  f() {}
-  f();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionLocal_isUsed_reference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-main() {
-  f() {}
-  print(f);
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionLocal_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-main() {
-  f() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_functionLocal_notUsed_referenceFromItself() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-main() {
-  _f(int p) {
-    _f(p - 1);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTop_isUsed_invocation() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-_f() {}
-main() {
-  _f();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTop_isUsed_reference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-_f() {}
-main() {
-  print(_f);
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTop_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-_f() {}
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTop_notUsed_referenceFromItself() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-_f(int p) {
-  _f(p - 1);
-}
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTypeAlias_isUsed_isExpression() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-typedef _F(a, b);
-main(f) {
-  if (f is _F) {
-    print('F');
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTypeAlias_isUsed_reference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-typedef _F(a, b);
-main(_F f) {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTypeAlias_isUsed_typeArgument() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-typedef _F(a, b);
-main() {
-  var v = new List<_F>();
-  print(v);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTypeAlias_isUsed_variableDeclaration() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-typedef _F(a, b);
-class A {
-  _F f;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_functionTypeAlias_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-typedef _F(a, b);
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_getter_isUsed_invocation_implicitThis() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  get _g => null;
-  useGetter() {
-    var v = _g;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_getter_isUsed_invocation_PrefixedIdentifier() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  get _g => null;
-}
-main(A a) {
-  var v = a._g;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_getter_isUsed_invocation_PropertyAccess() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  get _g => null;
-}
-main() {
-  var v = new A()._g;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_getter_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  get _g => null;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_getter_notUsed_referenceFromItself() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  get _g {
-    return _g;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_hasReference_implicitThis() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-  useMethod() {
-    print(_m);
-  }
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_hasReference_implicitThis_subclass() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-  useMethod() {
-    print(_m);
-  }
-}
-class B extends A {
-  _m() {}
-}
-print(x) {}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_hasReference_PrefixedIdentifier() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-}
-main(A a) {
-  a._m;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_hasReference_PropertyAccess() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-}
-main() {
-  new A()._m;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_implicitThis() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-  useMethod() {
-    _m();
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_implicitThis_subclass() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-  useMethod() {
-    _m();
-  }
-}
-class B extends A {
-  _m() {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_MemberElement() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A<T> {
-  _m(T t) {}
-}
-main(A<int> a) {
-  a._m(0);
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_propagated() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-}
-main() {
-  var a = new A();
-  a._m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_static() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-}
-main() {
-  A a = new A();
-  a._m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_invocation_subclass() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  _m() {}
-}
-class B extends A {
-  _m() {}
-}
-main(A a) {
-  a._m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_notPrivate() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  m() {}
-}
-main() {
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_isUsed_staticInvocation() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  static _m() {}
-}
-main() {
-  A._m();
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_method_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  static _m() {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_method_notUsed_referenceFromItself() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  static _m(int p) {
-    _m(p - 1);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_setter_isUsed_invocation_implicitThis() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  set _s(x) {}
-  useSetter() {
-    _s = 42;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_setter_isUsed_invocation_PrefixedIdentifier() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  set _s(x) {}
-}
-main(A a) {
-  a._s = 42;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_setter_isUsed_invocation_PropertyAccess() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  set _s(x) {}
-}
-main() {
-  new A()._s = 42;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_setter_notUsed_noReference() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  set _s(x) {}
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_setter_notUsed_referenceFromItself() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-class A {
-  set _s(int x) {
-    if (x > 5) {
-      _s = x - 1;
-    }
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedElement_topLevelVariable_isUsed() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-int _a = 1;
-main() {
-  _a;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_topLevelVariable_isUsed_plusPlus() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-int _a = 0;
-main() {
-  var b = _a++;
-  b;
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedElement_topLevelVariable_notUsed() async {
-    enableUnusedElement = true;
-    Source source = addSource(r'''
-int _a = 1;
-main() {
-  _a = 2;
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_ELEMENT]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inCatch_exception() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  try {
-  } on String catch (exception) {
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_CATCH_CLAUSE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inCatch_exception_hasStack() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  try {
-  } catch (exception, stack) {
-    print(stack);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inCatch_exception_noOnClause() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  try {
-  } catch (exception) {
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inCatch_stackTrace() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  try {
-  } catch (exception, stackTrace) {
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_CATCH_STACK]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inCatch_stackTrace_used() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  try {
-  } catch (exception, stackTrace) {
-    print('exception at $stackTrace');
-  }
-}
-print(x) {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inFor_underscore_ignored() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  for (var _ in [1,2,3]) {
-    for (var __ in [4,5,6]) {
-      // do something
-    }
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inFunction() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  var v = 1;
-  v = 2;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_inMethod() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-class A {
-  foo() {
-    var v = 1;
-    v = 2;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isInvoked() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-typedef Foo();
-main() {
-  Foo foo;
-  foo();
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isNullAssigned() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-typedef Foo();
-main() {
-  var v;
-  v ??= doSomething();
-}
-doSomething() => 42;
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isRead_notUsed_compoundAssign() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  var v = 1;
-  v += 2;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isRead_notUsed_postfixExpr() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  var v = 1;
-  v++;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isRead_notUsed_prefixExpr() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  var v = 1;
-  ++v;
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [HintCode.UNUSED_LOCAL_VARIABLE]);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isRead_usedArgument() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-main() {
-  var v = 1;
-  print(++v);
-}
-print(x) {}''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
-
-  test_unusedLocalVariable_isRead_usedInvocationTarget() async {
-    enableUnusedLocalVariable = true;
-    Source source = addSource(r'''
-class A {
-  foo() {}
-}
-main() {
-  var a = new A();
-  a.foo();
-}
-''');
-    await computeAnalysisResult(source);
-    assertErrors(source);
-    verify([source]);
-  }
 }
diff --git a/pkg/analyzer/test/generated/inheritance_manager_test.dart b/pkg/analyzer/test/generated/inheritance_manager_test.dart
index d6def33..8673c9e 100644
--- a/pkg/analyzer/test/generated/inheritance_manager_test.dart
+++ b/pkg/analyzer/test/generated/inheritance_manager_test.dart
@@ -42,6 +42,7 @@
   /**
    * The inheritance manager being tested.
    */
+  @deprecated
   InheritanceManager _inheritanceManager;
 
   /**
@@ -49,6 +50,7 @@
    */
   int _numOfMembersInObject = 0;
 
+  @deprecated
   void setUp() {
     _typeProvider = new TestTypeProvider();
     _inheritanceManager = _createInheritanceManager();
@@ -1106,6 +1108,7 @@
    *
    * @return the inheritance manager that was created
    */
+  @deprecated
   InheritanceManager _createInheritanceManager() {
     AnalysisContext context = AnalysisContextFactory.contextWithCore(
         resourceProvider: resourceProvider);
diff --git a/pkg/analyzer/test/generated/non_error_resolver.dart b/pkg/analyzer/test/generated/non_error_resolver.dart
index 2cf5077..3d06cd2 100644
--- a/pkg/analyzer/test/generated/non_error_resolver.dart
+++ b/pkg/analyzer/test/generated/non_error_resolver.dart
@@ -2910,73 +2910,6 @@
     verify([source]);
   }
 
-  test_invalidOverrideDifferentDefaultValues_named() async {
-    Source source = addSource(r'''
-class A {
-  m({int p : 0}) {}
-}
-class B extends A {
-  m({int p : 0}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_named_function() async {
-    Source source = addSource(r'''
-nothing() => 'nothing';
-class A {
-  thing(String a, {orElse : nothing}) {}
-}
-class B extends A {
-  thing(String a, {orElse : nothing}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_positional() async {
-    Source source = addSource(r'''
-class A {
-  m([int p = 0]) {}
-}
-class B extends A {
-  m([int p = 0]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_positional_changedOrder() async {
-    Source source = addSource(r'''
-class A {
-  m([int a = 0, String b = '0']) {}
-}
-class B extends A {
-  m([int b = 0, String a = '0']) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_positional_function() async {
-    Source source = addSource(r'''
-nothing() => 'nothing';
-class A {
-  thing(String a, [orElse = nothing]) {}
-}
-class B extends A {
-  thing(String a, [orElse = nothing]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_invalidOverrideNamed_unorderedNamedParameter() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/non_hint_code.dart b/pkg/analyzer/test/generated/non_hint_code.dart
index 800b3c1..206e154 100644
--- a/pkg/analyzer/test/generated/non_hint_code.dart
+++ b/pkg/analyzer/test/generated/non_hint_code.dart
@@ -765,21 +765,6 @@
     assertNoErrors(source);
   }
 
-  test_undefinedGetter_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  get b => 0;
-}
-f(var a) {
-  if(a is A) {
-    return a.b;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_GETTER]);
-  }
-
   test_undefinedMethod_assignmentExpression_inSubtype() async {
     Source source = addSource(r'''
 class A {}
@@ -844,175 +829,6 @@
     await computeAnalysisResult(source);
     assertNoErrors(source);
   }
-
-  test_undefinedOperator_binaryExpression_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator +(B b) {}
-}
-f(var a) {
-  if(a is A) {
-    a + 1;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_indexBoth_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator [](int index) {}
-}
-f(var a) {
-  if(a is A) {
-    a[0]++;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-      StaticTypeWarningCode.UNDEFINED_OPERATOR,
-    ]);
-  }
-
-  test_undefinedOperator_indexGetter_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator [](int index) {}
-}
-f(var a) {
-  if(a is A) {
-    a[0];
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_indexSetter_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator []=(i, v) {}
-}
-f(var a) {
-  if(a is A) {
-    a[0] = 1;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
-  }
-
-  test_undefinedOperator_postfixExpression() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator +(B b) {return new B();}
-}
-f(var a) {
-  if(a is A) {
-    a++;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-  }
-
-  test_undefinedOperator_prefixExpression() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  operator +(B b) {return new B();}
-}
-f(var a) {
-  if(a is A) {
-    ++a;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-  }
-
-  test_undefinedSetter_inSubtype() async {
-    Source source = addSource(r'''
-class A {}
-class B extends A {
-  set b(x) {}
-}
-f(var a) {
-  if (a is A) {
-    a.b = 0;
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.UNDEFINED_SETTER]);
-  }
-
-  test_unnecessaryNoSuchMethod_blockBody_notReturnStatement() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) {
-    print(y);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unnecessaryNoSuchMethod_blockBody_notSingleStatement() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) {
-    print(y);
-    return super.noSuchMethod(y);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unnecessaryNoSuchMethod_expressionBody_notNoSuchMethod() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) => super.hashCode;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_unnecessaryNoSuchMethod_expressionBody_notSuper() async {
-    Source source = addSource(r'''
-class A {
-  noSuchMethod(x) => super.noSuchMethod(x);
-}
-class B extends A {
-  mmm();
-  noSuchMethod(y) => 42;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
 }
 
 class PubSuggestionCodeTest extends ResolverTestCase {
diff --git a/pkg/analyzer/test/generated/parser_fasta_test.dart b/pkg/analyzer/test/generated/parser_fasta_test.dart
index 7dbd7f4..4809b48 100644
--- a/pkg/analyzer/test/generated/parser_fasta_test.dart
+++ b/pkg/analyzer/test/generated/parser_fasta_test.dart
@@ -135,7 +135,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionForElement second = list.elements[1];
+    ForElement second = list.elements[1];
     expect(second.awaitKeyword, isNotNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -157,7 +157,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionForElement second = list.elements[1];
+    ForElement second = list.elements[1];
     expect(second.awaitKeyword, isNotNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -169,7 +169,7 @@
     SimpleIdentifier iterable = forLoopParts.iterable;
     expect(iterable.name, 'list');
 
-    CollectionIfElement body = second.body;
+    IfElement body = second.body;
     SimpleIdentifier condition = body.condition;
     expect(condition.name, 'c');
     IntegerLiteral thenElement = body.thenElement;
@@ -183,7 +183,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionForElement second = list.elements[1];
+    ForElement second = list.elements[1];
     expect(second.awaitKeyword, isNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -205,7 +205,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = list.elements[1];
+    IfElement second = list.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     IntegerLiteral thenElement = second.thenElement;
@@ -219,7 +219,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = list.elements[1];
+    IfElement second = list.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     IntegerLiteral thenElement = second.thenElement;
@@ -235,13 +235,13 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = list.elements[1];
+    IfElement second = list.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     IntegerLiteral thenElement = second.thenElement;
     expect(thenElement.value, 2);
 
-    CollectionForElement elseElement = second.elseElement;
+    ForElement elseElement = second.elseElement;
     ForEachPartsWithIdentifier forLoopParts = elseElement.forLoopParts;
     expect(forLoopParts.identifier.name, 'a');
 
@@ -249,17 +249,33 @@
     expect(forValue.value, 5);
   }
 
+  void test_listLiteral_ifElseSpread() {
+    ListLiteral2 list =
+        parseCollectionLiteral('[1, if (true) ...[2] else ...?[5]]');
+    expect(list.elements, hasLength(2));
+    IntegerLiteral first = list.elements[0];
+    expect(first.value, 1);
+
+    IfElement second = list.elements[1];
+    BooleanLiteral condition = second.condition;
+    expect(condition.value, isTrue);
+    SpreadElement thenElement = second.thenElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    SpreadElement elseElement = second.elseElement;
+    expect(elseElement.spreadOperator.lexeme, '...?');
+  }
+
   void test_listLiteral_ifFor() {
     ListLiteral2 list = parseCollectionLiteral('[1, if (true) for (a in b) 2]');
     expect(list.elements, hasLength(2));
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = list.elements[1];
+    IfElement second = list.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
 
-    CollectionForElement thenElement = second.thenElement;
+    ForElement thenElement = second.thenElement;
     ForEachPartsWithIdentifier forLoopParts = thenElement.forLoopParts;
     expect(forLoopParts.identifier.name, 'a');
 
@@ -274,7 +290,7 @@
     IntegerLiteral first = list.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = list.elements[1];
+    IfElement second = list.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     SpreadElement thenElement = second.thenElement;
@@ -282,22 +298,6 @@
     expect(second.elseElement, isNull);
   }
 
-  void test_listLiteral_ifElseSpread() {
-    ListLiteral2 list =
-        parseCollectionLiteral('[1, if (true) ...[2] else ...?[5]]');
-    expect(list.elements, hasLength(2));
-    IntegerLiteral first = list.elements[0];
-    expect(first.value, 1);
-
-    CollectionIfElement second = list.elements[1];
-    BooleanLiteral condition = second.condition;
-    expect(condition.value, isTrue);
-    SpreadElement thenElement = second.thenElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    SpreadElement elseElement = second.elseElement;
-    expect(elseElement.spreadOperator.lexeme, '...?');
-  }
-
   void test_listLiteral_spread() {
     ListLiteral2 list = parseCollectionLiteral('[1, ...[2]]');
     expect(list.elements, hasLength(2));
@@ -330,7 +330,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 7);
 
-    MapForElement second = map.entries[1];
+    ForElement second = map.entries[1];
     expect(second.awaitKeyword, isNotNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -352,7 +352,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 7);
 
-    MapForElement second = map.entries[1];
+    ForElement second = map.entries[1];
     expect(second.awaitKeyword, isNotNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -364,7 +364,7 @@
     SimpleIdentifier iterable = forLoopParts.iterable;
     expect(iterable.name, 'list');
 
-    MapIfElement body = second.body;
+    IfElement body = second.body;
     SimpleIdentifier condition = body.condition;
     expect(condition.name, 'c');
     MapLiteralEntry thenElement = body.thenElement;
@@ -380,7 +380,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 7);
 
-    MapForElement second = map.entries[1];
+    ForElement second = map.entries[1];
     expect(second.awaitKeyword, isNull);
     expect(second.forKeyword.isKeyword, isTrue);
     expect(second.leftParenthesis.lexeme, '(');
@@ -404,7 +404,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 1);
 
-    MapIfElement second = map.entries[1];
+    IfElement second = map.entries[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     MapLiteralEntry thenElement = second.thenElement;
@@ -420,7 +420,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 1);
 
-    MapIfElement second = map.entries[1];
+    IfElement second = map.entries[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     MapLiteralEntry thenElement = second.thenElement;
@@ -439,14 +439,14 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 1);
 
-    MapIfElement second = map.entries[1];
+    IfElement second = map.entries[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     MapLiteralEntry thenElement = second.thenElement;
     IntegerLiteral thenElementValue = thenElement.value;
     expect(thenElementValue.value, 4);
 
-    MapForElement elseElement = second.elseElement;
+    ForElement elseElement = second.elseElement;
     ForEachPartsWithIdentifier forLoopParts = elseElement.forLoopParts;
     expect(forLoopParts.identifier.name, 'c');
 
@@ -455,6 +455,28 @@
     expect(bodyValue.value, 6);
   }
 
+  void test_mapLiteral_ifElseSpread() {
+    MapLiteral2 map =
+        parseCollectionLiteral('{1:7, if (true) ...{2:4} else ...?{5:6}}');
+    expect(map.entries, hasLength(2));
+    MapLiteralEntry first = map.entries[0];
+    IntegerLiteral firstValue = first.value;
+    expect(firstValue.value, 7);
+
+    IfElement second = map.entries[1];
+    BooleanLiteral condition = second.condition;
+    expect(condition.value, isTrue);
+    SpreadElement thenElement = second.thenElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    SpreadElement elseElement = second.elseElement;
+    expect(elseElement.spreadOperator.lexeme, '...?');
+    MapLiteral2 elseElementExpression = elseElement.expression;
+    expect(elseElementExpression.entries, hasLength(1));
+    MapLiteralEntry entry = elseElementExpression.entries[0];
+    IntegerLiteral entryValue = entry.value;
+    expect(entryValue.value, 6);
+  }
+
   void test_mapLiteral_ifFor() {
     MapLiteral2 map =
         parseCollectionLiteral('{1:1, if (true) for (a in b) 2:4}');
@@ -463,11 +485,11 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 1);
 
-    MapIfElement second = map.entries[1];
+    IfElement second = map.entries[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
 
-    MapForElement thenElement = second.thenElement;
+    ForElement thenElement = second.thenElement;
     ForEachPartsWithIdentifier forLoopParts = thenElement.forLoopParts;
     expect(forLoopParts.identifier.name, 'a');
 
@@ -484,7 +506,7 @@
     IntegerLiteral firstValue = first.value;
     expect(firstValue.value, 1);
 
-    MapIfElement second = map.entries[1];
+    IfElement second = map.entries[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     SpreadElement thenElement = second.thenElement;
@@ -492,28 +514,6 @@
     expect(second.elseElement, isNull);
   }
 
-  void test_mapLiteral_ifElseSpread() {
-    MapLiteral2 map =
-        parseCollectionLiteral('{1:7, if (true) ...{2:4} else ...?{5:6}}');
-    expect(map.entries, hasLength(2));
-    MapLiteralEntry first = map.entries[0];
-    IntegerLiteral firstValue = first.value;
-    expect(firstValue.value, 7);
-
-    MapIfElement second = map.entries[1];
-    BooleanLiteral condition = second.condition;
-    expect(condition.value, isTrue);
-    SpreadElement thenElement = second.thenElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    SpreadElement elseElement = second.elseElement;
-    expect(elseElement.spreadOperator.lexeme, '...?');
-    MapLiteral2 elseElementExpression = elseElement.expression;
-    expect(elseElementExpression.entries, hasLength(1));
-    MapLiteralEntry entry = elseElementExpression.entries[0];
-    IntegerLiteral entryValue = entry.value;
-    expect(entryValue.value, 6);
-  }
-
   void test_mapLiteral_spread() {
     MapLiteral2 map = parseCollectionLiteral('{1: 2, ...{3: 4}}');
     expect(map.constKeyword, isNull);
@@ -526,6 +526,30 @@
     expect(spreadExpression.entries, hasLength(1));
   }
 
+  void test_mapLiteral_spread2_typed() {
+    MapLiteral2 map = parseCollectionLiteral('<int, int>{1: 2, ...{3: 4}}');
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.entries, hasLength(2));
+
+    SpreadElement element = map.entries[1];
+    expect(element.spreadOperator.lexeme, '...');
+    MapLiteral2 spreadExpression = element.expression;
+    expect(spreadExpression.entries, hasLength(1));
+  }
+
+  void test_mapLiteral_spread_typed() {
+    MapLiteral2 map = parseCollectionLiteral('<int, int>{...{3: 4}}');
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.entries, hasLength(1));
+
+    SpreadElement element = map.entries[0];
+    expect(element.spreadOperator.lexeme, '...');
+    MapLiteral2 spreadExpression = element.expression;
+    expect(spreadExpression.entries, hasLength(1));
+  }
+
   void test_mapLiteral_spreadQ() {
     MapLiteral2 map = parseCollectionLiteral('{1: 2, ...?{3: 4}}');
     expect(map.constKeyword, isNull);
@@ -538,14 +562,14 @@
     expect(spreadExpression.entries, hasLength(1));
   }
 
-  void test_mapLiteral_spread_typed() {
-    MapLiteral2 map = parseCollectionLiteral('<int, int>{...{3: 4}}');
+  void test_mapLiteral_spreadQ2_typed() {
+    MapLiteral2 map = parseCollectionLiteral('<int, int>{1: 2, ...?{3: 4}}');
     expect(map.constKeyword, isNull);
     expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.entries, hasLength(1));
+    expect(map.entries, hasLength(2));
 
-    SpreadElement element = map.entries[0];
-    expect(element.spreadOperator.lexeme, '...');
+    SpreadElement element = map.entries[1];
+    expect(element.spreadOperator.lexeme, '...?');
     MapLiteral2 spreadExpression = element.expression;
     expect(spreadExpression.entries, hasLength(1));
   }
@@ -562,37 +586,13 @@
     expect(spreadExpression.entries, hasLength(1));
   }
 
-  void test_mapLiteral_spread2_typed() {
-    MapLiteral2 map = parseCollectionLiteral('<int, int>{1: 2, ...{3: 4}}');
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.entries, hasLength(2));
-
-    SpreadElement element = map.entries[1];
-    expect(element.spreadOperator.lexeme, '...');
-    MapLiteral2 spreadExpression = element.expression;
-    expect(spreadExpression.entries, hasLength(1));
-  }
-
-  void test_mapLiteral_spreadQ2_typed() {
-    MapLiteral2 map = parseCollectionLiteral('<int, int>{1: 2, ...?{3: 4}}');
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.entries, hasLength(2));
-
-    SpreadElement element = map.entries[1];
-    expect(element.spreadOperator.lexeme, '...?');
-    MapLiteral2 spreadExpression = element.expression;
-    expect(spreadExpression.entries, hasLength(1));
-  }
-
   void test_setLiteral_if() {
     SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) 2}');
     expect(setLiteral.elements, hasLength(2));
     IntegerLiteral first = setLiteral.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = setLiteral.elements[1];
+    IfElement second = setLiteral.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     IntegerLiteral thenElement = second.thenElement;
@@ -606,7 +606,7 @@
     IntegerLiteral first = setLiteral.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = setLiteral.elements[1];
+    IfElement second = setLiteral.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     IntegerLiteral thenElement = second.thenElement;
@@ -615,20 +615,6 @@
     expect(elseElement.value, 5);
   }
 
-  void test_setLiteral_ifSpread() {
-    SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) ...[2]}');
-    expect(setLiteral.elements, hasLength(2));
-    IntegerLiteral first = setLiteral.elements[0];
-    expect(first.value, 1);
-
-    CollectionIfElement second = setLiteral.elements[1];
-    BooleanLiteral condition = second.condition;
-    expect(condition.value, isTrue);
-    SpreadElement thenElement = second.thenElement;
-    expect(thenElement.spreadOperator.lexeme, '...');
-    expect(second.elseElement, isNull);
-  }
-
   void test_setLiteral_ifElseSpread() {
     SetLiteral2 setLiteral =
         parseCollectionLiteral('{1, if (true) ...{2} else ...?[5]}');
@@ -636,7 +622,7 @@
     IntegerLiteral first = setLiteral.elements[0];
     expect(first.value, 1);
 
-    CollectionIfElement second = setLiteral.elements[1];
+    IfElement second = setLiteral.elements[1];
     BooleanLiteral condition = second.condition;
     expect(condition.value, isTrue);
     SpreadElement thenElement = second.thenElement;
@@ -649,6 +635,20 @@
     expect(elseExpression.elements, hasLength(1));
   }
 
+  void test_setLiteral_ifSpread() {
+    SetLiteral2 setLiteral = parseCollectionLiteral('{1, if (true) ...[2]}');
+    expect(setLiteral.elements, hasLength(2));
+    IntegerLiteral first = setLiteral.elements[0];
+    expect(first.value, 1);
+
+    IfElement second = setLiteral.elements[1];
+    BooleanLiteral condition = second.condition;
+    expect(condition.value, isTrue);
+    SpreadElement thenElement = second.thenElement;
+    expect(thenElement.spreadOperator.lexeme, '...');
+    expect(second.elseElement, isNull);
+  }
+
   void test_setLiteral_spread2() {
     SetLiteral2 set = parseCollectionLiteral('{3, ...[4]}');
     expect(set.constKeyword, isNull);
@@ -864,24 +864,6 @@
 @reflectiveTest
 class ExpressionParserTest_Fasta extends FastaParserTestCase
     with ExpressionParserTestMixin {
-  @override
-  @failingTest
-  void test_parseUnaryExpression_decrement_super() {
-    // TODO(danrubel) Reports a different error and different token stream.
-    // Expected: TokenType:<MINUS>
-    //   Actual: TokenType:<MINUS_MINUS>
-    super.test_parseUnaryExpression_decrement_super();
-  }
-
-  @override
-  @failingTest
-  void test_parseUnaryExpression_decrement_super_withComment() {
-    // TODO(danrubel) Reports a different error and different token stream.
-    // Expected: TokenType:<MINUS>
-    //   Actual: TokenType:<MINUS_MINUS>
-    super.test_parseUnaryExpression_decrement_super_withComment();
-  }
-
   void test_listLiteral_spread() {
     // TODO(danrubel): Remove this once spread_collections is enabled by default
     ListLiteral list = parseExpression('[1, ...[2]]', errors: [
@@ -983,13 +965,13 @@
     expect(map.entries, hasLength(1));
   }
 
-  void test_mapLiteral_spreadQ() {
+  void test_mapLiteral_spread2_typed() {
     // TODO(danrubel): Remove this once spread_collections is enabled by default
-    MapLiteral map = parseExpression('{1: 2, ...?{3: 4}}',
+    MapLiteral map = parseExpression('<int, int>{1: 2, ...{3: 4}}',
         parseSetLiterals: true,
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 4)]);
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 17, 3)]);
     expect(map.constKeyword, isNull);
-    expect(map.typeArguments, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
     expect(map.entries, hasLength(1));
   }
 
@@ -1003,23 +985,13 @@
     expect(map.entries, hasLength(0));
   }
 
-  void test_mapLiteral_spreadQ_typed() {
+  void test_mapLiteral_spreadQ() {
     // TODO(danrubel): Remove this once spread_collections is enabled by default
-    MapLiteral map = parseExpression('<int, int>{...?{3: 4}}',
+    MapLiteral map = parseExpression('{1: 2, ...?{3: 4}}',
         parseSetLiterals: true,
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 11, 4)]);
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 7, 4)]);
     expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
-    expect(map.entries, hasLength(0));
-  }
-
-  void test_mapLiteral_spread2_typed() {
-    // TODO(danrubel): Remove this once spread_collections is enabled by default
-    MapLiteral map = parseExpression('<int, int>{1: 2, ...{3: 4}}',
-        parseSetLiterals: true,
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 17, 3)]);
-    expect(map.constKeyword, isNull);
-    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.typeArguments, isNull);
     expect(map.entries, hasLength(1));
   }
 
@@ -1033,6 +1005,34 @@
     expect(map.entries, hasLength(1));
   }
 
+  void test_mapLiteral_spreadQ_typed() {
+    // TODO(danrubel): Remove this once spread_collections is enabled by default
+    MapLiteral map = parseExpression('<int, int>{...?{3: 4}}',
+        parseSetLiterals: true,
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 11, 4)]);
+    expect(map.constKeyword, isNull);
+    expect(map.typeArguments.arguments, hasLength(2));
+    expect(map.entries, hasLength(0));
+  }
+
+  @override
+  @failingTest
+  void test_parseUnaryExpression_decrement_super() {
+    // TODO(danrubel) Reports a different error and different token stream.
+    // Expected: TokenType:<MINUS>
+    //   Actual: TokenType:<MINUS_MINUS>
+    super.test_parseUnaryExpression_decrement_super();
+  }
+
+  @override
+  @failingTest
+  void test_parseUnaryExpression_decrement_super_withComment() {
+    // TODO(danrubel) Reports a different error and different token stream.
+    // Expected: TokenType:<MINUS>
+    //   Actual: TokenType:<MINUS_MINUS>
+    super.test_parseUnaryExpression_decrement_super_withComment();
+  }
+
   void test_setLiteral() {
     SetLiteral set = parseExpression('{3}', parseSetLiterals: true);
     expect(set.constKeyword, isNull);
@@ -1704,6 +1704,172 @@
     with FormalParameterParserTestMixin {}
 
 /**
+ * Tests of the fasta parser based on [ComplexParserTestMixin].
+ */
+@reflectiveTest
+class NNBDParserTest_Fasta extends FastaParserTestCase {
+  CompilationUnit parseNNBDCompilationUnit(String code,
+      {List<ExpectedError> errors}) {
+    createParser('''
+@pragma('analyzer:non-nullable') library nnbd.parser.test;
+$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); }');
+  }
+
+  void test_assignment_simple() {
+    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
+  }
+
+  void test_binary_expression_statement() {
+    final unit = parseNNBDCompilationUnit('D? foo(X? x) { X ?? x2; }');
+    FunctionDeclaration funct = unit.declarations[0];
+    BlockFunctionBody body = funct.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    BinaryExpression expression = statement.expression;
+    SimpleIdentifier lhs = expression.leftOperand;
+    expect(lhs.name, 'X');
+    expect(expression.operator.lexeme, '??');
+    SimpleIdentifier rhs = expression.rightOperand;
+    expect(rhs.name, 'x2');
+  }
+
+  void test_conditional() {
+    parseNNBDCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
+  }
+
+  void test_conditional_complex() {
+    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
+  }
+
+  void test_conditional_error() {
+    parseNNBDCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
+        errors: [
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 78, 1),
+          expectedError(ParserErrorCode.EXPECTED_TOKEN, 99, 1),
+          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 99, 1),
+        ]);
+  }
+
+  void test_conditional_simple() {
+    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
+  }
+
+  void test_enableNonNullable_false() {
+    parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
+        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 20, 1)]);
+  }
+
+  void test_for() {
+    parseNNBDCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
+  }
+
+  void test_for_conditional() {
+    parseNNBDCompilationUnit(
+        'main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
+  }
+
+  void test_for_nullable() {
+    parseNNBDCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
+  }
+
+  void test_foreach() {
+    parseNNBDCompilationUnit('main() { for(int x in [7]) { } }');
+  }
+
+  void test_foreach_nullable() {
+    parseNNBDCompilationUnit('main() { for(int? x in [7, null]) { } }');
+  }
+
+  void test_gft_nullable() {
+    parseNNBDCompilationUnit('main() { C? Function() x = 7; }');
+  }
+
+  void test_gft_nullable_1() {
+    parseNNBDCompilationUnit('main() { C Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_2() {
+    parseNNBDCompilationUnit('main() { C? Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_3() {
+    parseNNBDCompilationUnit('main() { C? Function()? Function()? x = 7; }');
+  }
+
+  void test_gft_nullable_prefixed() {
+    parseNNBDCompilationUnit('main() { C.a? Function()? x = 7; }');
+  }
+
+  void test_is_nullable() {
+    CompilationUnit unit =
+        parseNNBDCompilationUnit('main() { x is String? ? (x + y) : z; }');
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    ConditionalExpression expression = statement.expression;
+
+    IsExpression condition = expression.condition;
+    expect((condition.type as NamedType).question, isNotNull);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_is_nullable_parenthesis() {
+    CompilationUnit unit =
+        parseNNBDCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
+    FunctionDeclaration function = unit.declarations[0];
+    BlockFunctionBody body = function.functionExpression.body;
+    ExpressionStatement statement = body.block.statements[0];
+    ConditionalExpression expression = statement.expression;
+
+    ParenthesizedExpression condition = expression.condition;
+    IsExpression isExpression = condition.expression;
+    expect((isExpression.type as NamedType).question, isNotNull);
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, isParenthesizedExpression);
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, isSimpleIdentifier);
+  }
+
+  void test_pragma_missing() {
+    createParser("library foo;");
+    _parserProxy.astBuilder.enableNonNullable = true;
+    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
+    expect(unit.hasPragmaAnalyzerNonNullable, false);
+  }
+
+  void test_pragma_non_nullable() {
+    createParser("@pragma('analyzer:non-nullable') library foo;");
+    _parserProxy.astBuilder.enableNonNullable = true;
+    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
+    expect(unit.hasPragmaAnalyzerNonNullable, true);
+  }
+
+  void test_pragma_non_nullable_not_enabled() {
+    createParser("@pragma('analyzer:non-nullable') library foo;");
+    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
+    expect(unit.hasPragmaAnalyzerNonNullable, false);
+  }
+
+  void test_pragma_other() {
+    createParser("@pragma('analyzer:foo') library foo;");
+    _parserProxy.astBuilder.enableNonNullable = true;
+    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
+    expect(unit.hasPragmaAnalyzerNonNullable, false);
+  }
+}
+
+/**
  * Proxy implementation of the analyzer parser, implemented in terms of the
  * Fasta parser.
  *
@@ -2609,169 +2775,3 @@
     expectCommentText(declaration.documentationComment, '/// Doc');
   }
 }
-
-/**
- * Tests of the fasta parser based on [ComplexParserTestMixin].
- */
-@reflectiveTest
-class NNBDParserTest_Fasta extends FastaParserTestCase {
-  CompilationUnit parseNNBDCompilationUnit(String code,
-      {List<ExpectedError> errors}) {
-    createParser('''
-@pragma('analyzer:non-nullable') library nnbd.parser.test;
-$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); }');
-  }
-
-  void test_assignment_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X? x1; X? x2 = x; }');
-  }
-
-  void test_gft_nullable() {
-    parseNNBDCompilationUnit('main() { C? Function() x = 7; }');
-  }
-
-  void test_gft_nullable_1() {
-    parseNNBDCompilationUnit('main() { C Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_2() {
-    parseNNBDCompilationUnit('main() { C? Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_3() {
-    parseNNBDCompilationUnit('main() { C? Function()? Function()? x = 7; }');
-  }
-
-  void test_gft_nullable_prefixed() {
-    parseNNBDCompilationUnit('main() { C.a? Function()? x = 7; }');
-  }
-
-  void test_binary_expression_statement() {
-    final unit = parseNNBDCompilationUnit('D? foo(X? x) { X ?? x2; }');
-    FunctionDeclaration funct = unit.declarations[0];
-    BlockFunctionBody body = funct.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    BinaryExpression expression = statement.expression;
-    SimpleIdentifier lhs = expression.leftOperand;
-    expect(lhs.name, 'X');
-    expect(expression.operator.lexeme, '??');
-    SimpleIdentifier rhs = expression.rightOperand;
-    expect(rhs.name, 'x2');
-  }
-
-  void test_conditional() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? 7 : y; }');
-  }
-
-  void test_conditional_complex() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x + bar(7) : y; }');
-  }
-
-  void test_conditional_error() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? ? x2 = x + bar(7) : y; }',
-        errors: [
-          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 78, 1),
-          expectedError(ParserErrorCode.EXPECTED_TOKEN, 99, 1),
-          expectedError(ParserErrorCode.MISSING_IDENTIFIER, 99, 1),
-        ]);
-  }
-
-  void test_conditional_simple() {
-    parseNNBDCompilationUnit('D? foo(X? x) { X ? x2 = x : y; }');
-  }
-
-  void test_for() {
-    parseNNBDCompilationUnit('main() { for(int x = 0; x < 7; ++x) { } }');
-  }
-
-  void test_for_conditional() {
-    parseNNBDCompilationUnit(
-        'main() { for(x ? y = 7 : y = 8; y < 10; ++y) { } }');
-  }
-
-  void test_for_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x = 0; x < 7; ++x) { } }');
-  }
-
-  void test_foreach() {
-    parseNNBDCompilationUnit('main() { for(int x in [7]) { } }');
-  }
-
-  void test_foreach_nullable() {
-    parseNNBDCompilationUnit('main() { for(int? x in [7, null]) { } }');
-  }
-
-  void test_is_nullable() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { x is String? ? (x + y) : z; }');
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    ConditionalExpression expression = statement.expression;
-
-    IsExpression condition = expression.condition;
-    expect((condition.type as NamedType).question, isNotNull);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_is_nullable_parenthesis() {
-    CompilationUnit unit =
-        parseNNBDCompilationUnit('main() { (x is String?) ? (x + y) : z; }');
-    FunctionDeclaration function = unit.declarations[0];
-    BlockFunctionBody body = function.functionExpression.body;
-    ExpressionStatement statement = body.block.statements[0];
-    ConditionalExpression expression = statement.expression;
-
-    ParenthesizedExpression condition = expression.condition;
-    IsExpression isExpression = condition.expression;
-    expect((isExpression.type as NamedType).question, isNotNull);
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, isParenthesizedExpression);
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, isSimpleIdentifier);
-  }
-
-  void test_pragma_missing() {
-    createParser("library foo;");
-    _parserProxy.astBuilder.enableNonNullable = true;
-    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
-    expect(unit.hasPragmaAnalyzerNonNullable, false);
-  }
-
-  void test_pragma_non_nullable() {
-    createParser("@pragma('analyzer:non-nullable') library foo;");
-    _parserProxy.astBuilder.enableNonNullable = true;
-    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
-    expect(unit.hasPragmaAnalyzerNonNullable, true);
-  }
-
-  void test_pragma_non_nullable_not_enabled() {
-    createParser("@pragma('analyzer:non-nullable') library foo;");
-    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
-    expect(unit.hasPragmaAnalyzerNonNullable, false);
-  }
-
-  void test_pragma_other() {
-    createParser("@pragma('analyzer:foo') library foo;");
-    _parserProxy.astBuilder.enableNonNullable = true;
-    CompilationUnitImpl unit = _parserProxy.parseCompilationUnit2();
-    expect(unit.hasPragmaAnalyzerNonNullable, false);
-  }
-
-  void test_enableNonNullable_false() {
-    parseCompilationUnit('main() { x is String? ? (x + y) : z; }',
-        errors: [expectedError(ParserErrorCode.UNEXPECTED_TOKEN, 20, 1)]);
-  }
-}
diff --git a/pkg/analyzer/test/generated/parser_test.dart b/pkg/analyzer/test/generated/parser_test.dart
index 9d5b456..faf4a1c 100644
--- a/pkg/analyzer/test/generated/parser_test.dart
+++ b/pkg/analyzer/test/generated/parser_test.dart
@@ -1930,46 +1930,6 @@
     expect(expression.condition, isBinaryExpression);
   }
 
-  void test_conditionalExpression_precedence_withAssignment() {
-    ExpressionStatement statement = parseStatement('b ? c = true : g();');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, new TypeMatcher<SimpleIdentifier>());
-    expect(expression.thenExpression, new TypeMatcher<AssignmentExpression>());
-  }
-
-  void test_conditionalExpression_precedence_withAssignment2() {
-    ExpressionStatement statement = parseStatement('b.x ? c = true : g();');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, new TypeMatcher<AssignmentExpression>());
-  }
-
-  void test_conditionalExpression_prefixedValue() {
-    ExpressionStatement statement = parseStatement('a.b ? y : z;');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, new TypeMatcher<SimpleIdentifier>());
-  }
-
-  void test_conditionalExpression_prefixedValue2() {
-    ExpressionStatement statement = parseStatement('a.b ? x.y : z;');
-    ConditionalExpression expression = statement.expression;
-    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
-    expect(expression.thenExpression, new TypeMatcher<PrefixedIdentifier>());
-  }
-
-  void test_conditionalExpression_precedence_prefixedNullableType_is() {
-    ExpressionStatement statement = parseStatement('x is p.A ? (x + y) : z;');
-    ConditionalExpression expression = statement.expression;
-
-    Expression condition = expression.condition;
-    expect(condition, new TypeMatcher<IsExpression>());
-    Expression thenExpression = expression.thenExpression;
-    expect(thenExpression, new TypeMatcher<ParenthesizedExpression>());
-    Expression elseExpression = expression.elseExpression;
-    expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
-  }
-
   void test_conditionalExpression_precedence_nullableType_as() {
     ExpressionStatement statement = parseStatement('x as bool ? (x + y) : z;');
     ConditionalExpression expression = statement.expression;
@@ -2029,6 +1989,46 @@
     expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
   }
 
+  void test_conditionalExpression_precedence_prefixedNullableType_is() {
+    ExpressionStatement statement = parseStatement('x is p.A ? (x + y) : z;');
+    ConditionalExpression expression = statement.expression;
+
+    Expression condition = expression.condition;
+    expect(condition, new TypeMatcher<IsExpression>());
+    Expression thenExpression = expression.thenExpression;
+    expect(thenExpression, new TypeMatcher<ParenthesizedExpression>());
+    Expression elseExpression = expression.elseExpression;
+    expect(elseExpression, new TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_precedence_withAssignment() {
+    ExpressionStatement statement = parseStatement('b ? c = true : g();');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, new TypeMatcher<SimpleIdentifier>());
+    expect(expression.thenExpression, new TypeMatcher<AssignmentExpression>());
+  }
+
+  void test_conditionalExpression_precedence_withAssignment2() {
+    ExpressionStatement statement = parseStatement('b.x ? c = true : g();');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, new TypeMatcher<AssignmentExpression>());
+  }
+
+  void test_conditionalExpression_prefixedValue() {
+    ExpressionStatement statement = parseStatement('a.b ? y : z;');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, new TypeMatcher<SimpleIdentifier>());
+  }
+
+  void test_conditionalExpression_prefixedValue2() {
+    ExpressionStatement statement = parseStatement('a.b ? x.y : z;');
+    ConditionalExpression expression = statement.expression;
+    expect(expression.condition, new TypeMatcher<PrefixedIdentifier>());
+    expect(expression.thenExpression, new TypeMatcher<PrefixedIdentifier>());
+  }
+
   void test_constructor_initializer_withParenthesizedExpression() {
     CompilationUnit unit = parseCompilationUnit(r'''
 class C {
diff --git a/pkg/analyzer/test/generated/resolver_test.dart b/pkg/analyzer/test/generated/resolver_test.dart
index 6c1887b..5d5b657 100644
--- a/pkg/analyzer/test/generated/resolver_test.dart
+++ b/pkg/analyzer/test/generated/resolver_test.dart
@@ -23,13 +23,13 @@
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
 import 'package:analyzer/src/generated/testing/element_factory.dart';
-import 'package:analyzer/src/generated/testing/element_search.dart';
 import 'package:analyzer/src/generated/testing/test_type_provider.dart';
 import 'package:analyzer/src/source/source_resource.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../src/dart/resolution/driver_resolution.dart';
 import 'analysis_context_factory.dart';
 import 'parser_test.dart';
 import 'resolver_test_case.dart';
@@ -45,7 +45,6 @@
     defineReflectiveTests(LibraryScopeTest);
     defineReflectiveTests(PrefixedNamespaceTest);
     defineReflectiveTests(ScopeTest);
-    defineReflectiveTests(TypeOverrideManagerTest);
     defineReflectiveTests(TypeProviderImplTest);
     defineReflectiveTests(TypeResolverVisitorTest);
   });
@@ -164,12 +163,10 @@
   }
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class ErrorResolverTest extends ResolverTestCase {
+class ErrorResolverTest extends DriverResolutionTest {
   test_breakLabelOnSwitchMember() async {
-    Source source = addSource(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     switch (i) {
@@ -179,14 +176,11 @@
         break l;
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
-    verify([source]);
+}''', [ResolverErrorCode.BREAK_LABEL_ON_SWITCH_MEMBER]);
   }
 
   test_continueLabelOnSwitch() async {
-    Source source = addSource(r'''
+    assertErrorsInCode(r'''
 class A {
   void m(int i) {
     l: switch (i) {
@@ -194,43 +188,24 @@
         continue l;
     }
   }
-}''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
-    verify([source]);
+}''', [ResolverErrorCode.CONTINUE_LABEL_ON_SWITCH]);
   }
 
   test_enclosingElement_invalidLocalFunction() async {
-    String code = r'''
+    addTestFile(r'''
 class C {
   C() {
     int get x => 0;
   }
-}''';
-    Source source = addSource(code);
-
-    TestAnalysisResult analysisResult = await computeAnalysisResult(source);
-    assertErrors(source, [
+}''');
+    await resolveTestFile();
+    assertTestErrors([
       ParserErrorCode.MISSING_FUNCTION_PARAMETERS,
       ParserErrorCode.EXPECTED_TOKEN
     ]);
 
-    CompilationUnitElement unit = analysisResult.unit.declaredElement;
-    LibraryElement library = unit.library;
-    expect(library, isNotNull);
-    expect(unit.enclosingElement, same(library));
-
-    var types = unit.types;
-    expect(types, hasLength(1));
-    var type = types[0];
-    expect(type, isNotNull);
-
-    var constructors = type.constructors;
-    expect(constructors, hasLength(1));
-    ConstructorElement constructor = constructors[0];
-    expect(constructor, isNotNull);
-
-    FunctionElement x = findElementsByName(analysisResult.unit, 'x').single;
+    var constructor = findElement.unnamedConstructor('C');
+    var x = findElement.localFunction('x');
     expect(x.enclosingElement, constructor);
   }
 }
@@ -747,68 +722,6 @@
   }
 }
 
-@reflectiveTest
-class TypeOverrideManagerTest extends EngineTestCase {
-  void test_exitScope_noScopes() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    expect(() {
-      manager.exitScope();
-    }, throwsStateError);
-  }
-
-  void test_exitScope_oneScope() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    manager.enterScope();
-    manager.exitScope();
-    expect(() {
-      manager.exitScope();
-    }, throwsStateError);
-  }
-
-  void test_exitScope_twoScopes() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    manager.enterScope();
-    manager.exitScope();
-    manager.enterScope();
-    manager.exitScope();
-    expect(() {
-      manager.exitScope();
-    }, throwsStateError);
-  }
-
-  void test_getType_enclosedOverride() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    LocalVariableElementImpl element =
-        ElementFactory.localVariableElement2("v");
-    InterfaceType type = ElementFactory.classElement2("C").type;
-    manager.enterScope();
-    manager.setType(element, type);
-    manager.enterScope();
-    expect(manager.getType(element), same(type));
-  }
-
-  void test_getType_immediateOverride() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    LocalVariableElementImpl element =
-        ElementFactory.localVariableElement2("v");
-    InterfaceType type = ElementFactory.classElement2("C").type;
-    manager.enterScope();
-    manager.setType(element, type);
-    expect(manager.getType(element), same(type));
-  }
-
-  void test_getType_noOverride() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    manager.enterScope();
-    expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull);
-  }
-
-  void test_getType_noScope() {
-    TypeOverrideManager manager = new TypeOverrideManager();
-    expect(manager.getType(ElementFactory.localVariableElement2("v")), isNull);
-  }
-}
-
 abstract class TypePropagationTest extends ResolverTestCase {
   fail_propagatedReturnType_functionExpression() async {
     // TODO(scheglov) disabled because we don't resolve function expression
diff --git a/pkg/analyzer/test/generated/simple_resolver_test.dart b/pkg/analyzer/test/generated/simple_resolver_test.dart
index 4327b26..a4d99bb 100644
--- a/pkg/analyzer/test/generated/simple_resolver_test.dart
+++ b/pkg/analyzer/test/generated/simple_resolver_test.dart
@@ -3,19 +3,13 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:analyzer/dart/ast/ast.dart';
-import 'package:analyzer/dart/ast/standard_resolution_map.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/exception/exception.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 '../utils.dart';
+import '../src/dart/resolution/driver_resolution.dart';
 import 'resolver_test_case.dart';
-import 'test_support.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -23,111 +17,109 @@
   });
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class SimpleResolverTest extends ResolverTestCase {
+class SimpleResolverTest extends DriverResolutionTest {
   test_argumentResolution_required_matching() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2, 3);
   }
   void g(a, b, c) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2]);
+    await _validateArgumentResolution([0, 1, 2]);
   }
 
   test_argumentResolution_required_tooFew() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2);
   }
   void g(a, b, c) {}
 }''');
-    _validateArgumentResolution(source, [0, 1]);
+    await _validateArgumentResolution([0, 1]);
   }
 
   test_argumentResolution_required_tooMany() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2, 3);
   }
   void g(a, b) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, -1]);
+    await _validateArgumentResolution([0, 1, -1]);
   }
 
   test_argumentResolution_requiredAndNamed_extra() async {
-    Source source = addSource(r'''
+    addTestFile('''
 class A {
   void f() {
     g(1, 2, c: 3, d: 4);
   }
   void g(a, b, {c}) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2, -1]);
+    await _validateArgumentResolution([0, 1, 2, -1]);
   }
 
   test_argumentResolution_requiredAndNamed_matching() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2, c: 3);
   }
   void g(a, b, {c}) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2]);
+    await _validateArgumentResolution([0, 1, 2]);
   }
 
   test_argumentResolution_requiredAndNamed_missing() async {
-    Source source = addSource(r'''
+    addTestFile('''
 class A {
   void f() {
     g(1, 2, d: 3);
   }
   void g(a, b, {c, d}) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 3]);
+    await _validateArgumentResolution([0, 1, 3]);
   }
 
   test_argumentResolution_requiredAndPositional_fewer() async {
-    Source source = addSource(r'''
+    addTestFile('''
 class A {
   void f() {
     g(1, 2, 3);
   }
   void g(a, b, [c, d]) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2]);
+    await _validateArgumentResolution([0, 1, 2]);
   }
 
   test_argumentResolution_requiredAndPositional_matching() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2, 3, 4);
   }
   void g(a, b, [c, d]) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2, 3]);
+    await _validateArgumentResolution([0, 1, 2, 3]);
   }
 
   test_argumentResolution_requiredAndPositional_more() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void f() {
     g(1, 2, 3, 4);
   }
   void g(a, b, [c]) {}
 }''');
-    _validateArgumentResolution(source, [0, 1, 2, -1]);
+    await _validateArgumentResolution([0, 1, 2, -1]);
   }
 
   test_argumentResolution_setter_propagated() async {
-    CompilationUnit unit = await resolveSource(r'''
+    addTestFile(r'''
 main() {
   var a = new A();
   a.sss = 0;
@@ -135,20 +127,17 @@
 class A {
   set sss(x) {}
 }''');
-    // find "a.sss = 0"
-    AssignmentExpression assignment;
-    {
-      var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
-      var statement = statements[1] as ExpressionStatement;
-      assignment = statement.expression as AssignmentExpression;
-    }
-    // get parameter
-    Expression rhs = assignment.rightHandSide;
-    expect(rhs.staticParameterElement, isNotNull);
+    await resolveTestFile();
+
+    var rhs = findNode.assignment(' = 0;').rightHandSide;
+    expect(
+      rhs.staticParameterElement,
+      findElement.parameter('x'),
+    );
   }
 
   test_argumentResolution_setter_propagated_propertyAccess() async {
-    CompilationUnit unit = await resolveSource(r'''
+    addTestFile(r'''
 main() {
   var a = new A();
   a.b.sss = 0;
@@ -159,20 +148,17 @@
 class B {
   set sss(x) {}
 }''');
-    // find "a.b.sss = 0"
-    AssignmentExpression assignment;
-    {
-      var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
-      var statement = statements[1] as ExpressionStatement;
-      assignment = statement.expression as AssignmentExpression;
-    }
-    // get parameter
-    Expression rhs = assignment.rightHandSide;
-    expect(rhs.staticParameterElement, isNotNull);
+    await resolveTestFile();
+
+    var rhs = findNode.assignment(' = 0;').rightHandSide;
+    expect(
+      rhs.staticParameterElement,
+      findElement.parameter('x'),
+    );
   }
 
   test_argumentResolution_setter_static() async {
-    CompilationUnit unit = await resolveSource(r'''
+    addTestFile(r'''
 main() {
   A a = new A();
   a.sss = 0;
@@ -180,26 +166,17 @@
 class A {
   set sss(x) {}
 }''');
-    // find "a.sss = 0"
-    AssignmentExpression assignment;
-    {
-      var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
-      var statement = statements[1] as ExpressionStatement;
-      assignment = statement.expression as AssignmentExpression;
-    }
-    // get parameter
-    Expression rhs = assignment.rightHandSide;
-    ParameterElement parameter = rhs.staticParameterElement;
-    expect(parameter, isNotNull);
-    expect(parameter.displayName, "x");
-    // validate
-    ClassElement classA = unit.declaredElement.types[0];
-    PropertyAccessorElement setter = classA.accessors[0];
-    expect(setter.parameters[0], same(parameter));
+    await resolveTestFile();
+
+    var rhs = findNode.assignment(' = 0;').rightHandSide;
+    expect(
+      rhs.staticParameterElement,
+      findElement.parameter('x'),
+    );
   }
 
   test_argumentResolution_setter_static_propertyAccess() async {
-    CompilationUnit unit = await resolveSource(r'''
+    addTestFile(r'''
 main() {
   A a = new A();
   a.b.sss = 0;
@@ -210,28 +187,19 @@
 class B {
   set sss(x) {}
 }''');
-    // find "a.b.sss = 0"
-    AssignmentExpression assignment;
-    {
-      var statements = AstFinder.getStatementsInTopLevelFunction(unit, 'main');
-      var statement = statements[1] as ExpressionStatement;
-      assignment = statement.expression as AssignmentExpression;
-    }
-    // get parameter
-    Expression rhs = assignment.rightHandSide;
-    ParameterElement parameter = rhs.staticParameterElement;
-    expect(parameter, isNotNull);
-    expect(parameter.displayName, "x");
-    // validate
-    ClassElement classB = unit.declaredElement.types[1];
-    PropertyAccessorElement setter = classB.accessors[0];
-    expect(setter.parameters[0], same(parameter));
+    await resolveTestFile();
+
+    var rhs = findNode.assignment(' = 0;').rightHandSide;
+    expect(
+      rhs.staticParameterElement,
+      findElement.parameter('x'),
+    );
   }
 
   test_breakTarget_labeled() async {
     // Verify that the target of the label is correctly found and is recorded
     // as the unlabeled portion of the statement.
-    String text = r'''
+    addTestFile(r'''
 void f() {
   loop1: while (true) {
     loop2: for (int i = 0; i < 10; i++) {
@@ -240,70 +208,65 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    WhileStatement whileStatement = EngineTestCase.findNode(
-        unit, text, 'while (true)', (n) => n is WhileStatement);
-    ForStatement forStatement =
-        EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
-    BreakStatement break1 = EngineTestCase.findNode(
-        unit, text, 'break loop1', (n) => n is BreakStatement);
-    BreakStatement break2 = EngineTestCase.findNode(
-        unit, text, 'break loop2', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var break1 = findNode.breakStatement('break loop1;');
+    var whileStatement = findNode.whileStatement('while (');
     expect(break1.target, same(whileStatement));
+
+    var break2 = findNode.breakStatement('break loop2;');
+    var forStatement = findNode.forStatement('for (');
     expect(break2.target, same(forStatement));
   }
 
   test_breakTarget_unlabeledBreakFromDo() async {
-    String text = r'''
+    addTestFile('''
 void f() {
   do {
     break;
   } while (true);
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    DoStatement doStatement =
-        EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var doStatement = findNode.doStatement('do {');
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(doStatement));
   }
 
   test_breakTarget_unlabeledBreakFromFor() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   for (int i = 0; i < 10; i++) {
     break;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    ForStatement forStatement =
-        EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var forStatement = findNode.forStatement('for (');
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(forStatement));
   }
 
   test_breakTarget_unlabeledBreakFromForEach() async {
-    String text = r'''
+    addTestFile('''
 void f() {
   for (x in []) {
     break;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    ForEachStatement forStatement = EngineTestCase.findNode(
-        unit, text, 'for', (n) => n is ForEachStatement);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var forStatement = findNode.forEachStatement('for (');
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(forStatement));
   }
 
   test_breakTarget_unlabeledBreakFromSwitch() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     switch (0) {
@@ -312,35 +275,33 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    SwitchStatement switchStatement = EngineTestCase.findNode(
-        unit, text, 'switch', (n) => n is SwitchStatement);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var switchStatement = findNode.switchStatement('switch (');
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(switchStatement));
   }
 
   test_breakTarget_unlabeledBreakFromWhile() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     break;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    WhileStatement whileStatement = EngineTestCase.findNode(
-        unit, text, 'while', (n) => n is WhileStatement);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var whileStatement = findNode.whileStatement('while (');
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, same(whileStatement));
   }
 
   test_breakTarget_unlabeledBreakToOuterFunction() async {
     // Verify that unlabeled break statements can't resolve to loops in an
     // outer function.
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     void g() {
@@ -348,40 +309,34 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    BreakStatement breakStatement = EngineTestCase.findNode(
-        unit, text, 'break', (n) => n is BreakStatement);
+''');
+    await resolveTestFile();
+
+    var breakStatement = findNode.breakStatement('break;');
     expect(breakStatement.target, isNull);
   }
 
   test_class_definesCall() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   int call(int x) { return x; }
 }
 int f(A a) {
   return a(0);
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_class_extends_implements() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A extends B implements C {}
 class B {}
 class C {}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_continueTarget_labeled() async {
     // Verify that the target of the label is correctly found and is recorded
     // as the unlabeled portion of the statement.
-    String text = r'''
+    addTestFile('''
 void f() {
   loop1: while (true) {
     loop2: for (int i = 0; i < 10; i++) {
@@ -390,86 +345,80 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    WhileStatement whileStatement = EngineTestCase.findNode(
-        unit, text, 'while (true)', (n) => n is WhileStatement);
-    ForStatement forStatement =
-        EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
-    ContinueStatement continue1 = EngineTestCase.findNode(
-        unit, text, 'continue loop1', (n) => n is ContinueStatement);
-    ContinueStatement continue2 = EngineTestCase.findNode(
-        unit, text, 'continue loop2', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var continue1 = findNode.continueStatement('continue loop1');
+    var whileStatement = findNode.whileStatement('while (');
     expect(continue1.target, same(whileStatement));
+
+    var continue2 = findNode.continueStatement('continue loop2');
+    var forStatement = findNode.forStatement('for (');
     expect(continue2.target, same(forStatement));
   }
 
   test_continueTarget_unlabeledContinueFromDo() async {
-    String text = r'''
+    addTestFile('''
 void f() {
   do {
     continue;
   } while (true);
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    DoStatement doStatement =
-        EngineTestCase.findNode(unit, text, 'do', (n) => n is DoStatement);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var doStatement = findNode.doStatement('do {');
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(doStatement));
   }
 
   test_continueTarget_unlabeledContinueFromFor() async {
-    String text = r'''
+    addTestFile('''
 void f() {
   for (int i = 0; i < 10; i++) {
     continue;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    ForStatement forStatement =
-        EngineTestCase.findNode(unit, text, 'for', (n) => n is ForStatement);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var forStatement = findNode.forStatement('for (');
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(forStatement));
   }
 
   test_continueTarget_unlabeledContinueFromForEach() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   for (x in []) {
     continue;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    ForEachStatement forStatement = EngineTestCase.findNode(
-        unit, text, 'for', (n) => n is ForEachStatement);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var forStatement = findNode.forEachStatement('for (');
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(forStatement));
   }
 
   test_continueTarget_unlabeledContinueFromWhile() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     continue;
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    WhileStatement whileStatement = EngineTestCase.findNode(
-        unit, text, 'while', (n) => n is WhileStatement);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var whileStatement = findNode.whileStatement('while (');
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(whileStatement));
   }
 
   test_continueTarget_unlabeledContinueSkipsSwitch() async {
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     switch (0) {
@@ -478,19 +427,18 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    WhileStatement whileStatement = EngineTestCase.findNode(
-        unit, text, 'while', (n) => n is WhileStatement);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var whileStatement = findNode.whileStatement('while (');
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, same(whileStatement));
   }
 
   test_continueTarget_unlabeledContinueToOuterFunction() async {
     // Verify that unlabeled continue statements can't resolve to loops in an
     // outer function.
-    String text = r'''
+    addTestFile(r'''
 void f() {
   while (true) {
     void g() {
@@ -498,77 +446,76 @@
     }
   }
 }
-''';
-    CompilationUnit unit = await resolveSource(text);
-    ContinueStatement continueStatement = EngineTestCase.findNode(
-        unit, text, 'continue', (n) => n is ContinueStatement);
+''');
+    await resolveTestFile();
+
+    var continueStatement = findNode.continueStatement('continue;');
     expect(continueStatement.target, isNull);
   }
 
   test_empty() async {
-    Source source = addSource("");
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    addTestFile('');
+    await resolveTestFile();
+    assertNoTestErrors();
   }
 
   test_entryPoint_exported() async {
-    addNamedSource("/two.dart", r'''
-library two;
-main() {}''');
-    Source source = addNamedSource("/one.dart", r'''
-library one;
-export 'two.dart';''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    FunctionElement main = library.entryPoint;
+    newFile('/test/lib/a.dart', content: r'''
+main() {}
+''');
+
+    addTestFile(r'''
+export 'a.dart';
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var library = result.libraryElement;
+    var main = library.entryPoint;
+
     expect(main, isNotNull);
     expect(main.library, isNot(same(library)));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_entryPoint_local() async {
-    Source source = addNamedSource("/one.dart", r'''
-library one;
-main() {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    FunctionElement main = library.entryPoint;
+    addTestFile(r'''
+main() {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var library = result.libraryElement;
+    var main = library.entryPoint;
+
     expect(main, isNotNull);
     expect(main.library, same(library));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_entryPoint_none() async {
-    Source source = addNamedSource("/one.dart", "library one;");
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
+    addTestFile('');
+    await resolveTestFile();
+    assertNoTestErrors();
+
+    var library = result.libraryElement;
     expect(library.entryPoint, isNull);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_enum_externalLibrary() async {
-    addNamedSource("/my_lib.dart", r'''
-library my_lib;
-enum EEE {A, B, C}''');
-    Source source = addSource(r'''
-import 'my_lib.dart';
-main() {
-  EEE e = null;
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    newFile('/test/lib/a.dart', content: r'''
+enum EEE {A, B, C}
+''');
+    addTestFile(r'''
+import 'a.dart';
+
+void f(EEE e) {}
+''');
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_extractedMethodAsConstant() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 abstract class Comparable<T> {
   int compareTo(T other);
   static int compare(Comparable a, Comparable b) => a.compareTo(b);
@@ -576,64 +523,55 @@
 class A {
   void sort([compare = Comparable.compare]) {}
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_fieldFormalParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   int x;
   int y;
   A(this.x) : y = x {}
 }''');
-    CompilationUnit unit =
-        analysisContext2.resolveCompilationUnit2(source, source);
-    ClassDeclaration classA = unit.declarations[0];
-    FieldDeclaration field = classA.members[0];
-    ConstructorDeclaration constructor = classA.members[2];
-    ParameterElement paramElement =
-        constructor.parameters.parameters[0].declaredElement;
-    expect(paramElement, new TypeMatcher<FieldFormalParameterElement>());
-    expect((paramElement as FieldFormalParameterElement).field,
-        field.fields.variables[0].declaredElement);
-    ConstructorFieldInitializer initializer = constructor.initializers[0];
-    SimpleIdentifier identifierX = initializer.expression;
-    expect(identifierX.staticElement, paramElement);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
 
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    var xParameter = findNode.fieldFormalParameter('this.x');
+
+    var xParameterElement =
+        xParameter.declaredElement as FieldFormalParameterElement;
+    expect(xParameterElement.field, findElement.field('x'));
+
+    assertElement(
+      findNode.simple('x {}'),
+      xParameterElement,
+    );
   }
 
   test_forEachLoops_nonConflicting() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   List list = [1,2,3];
   for (int x in list) {}
   for (int x in list) {}
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_forLoops_nonConflicting() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   for (int i = 0; i < 3; i++) {
   }
   for (int i = 0; i < 3; i++) {
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_functionTypeAlias() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 typedef bool P(e);
 class A {
   P p;
@@ -641,13 +579,11 @@
     if (p(e)) {}
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_getter_and_setter_fromMixins_bare_identifier() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   get x => null;
@@ -663,24 +599,21 @@
   }
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     // Verify that both the getter and setter for "x" in C.f() refer to the
     // accessors defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInMethod(analysisResult.unit, 'C', 'f');
-    var statement = statements[0] as ExpressionStatement;
-    AssignmentExpression assignment = statement.expression;
-    SimpleIdentifier leftHandSide = assignment.leftHandSide;
+    var leftHandSide = findNode.simple('x +=');
     expect(
-        resolutionMap
-            .staticElementForIdentifier(leftHandSide)
-            .enclosingElement
-            .name,
-        'M2');
-    expect(leftHandSide.auxiliaryElements.staticElement.enclosingElement.name,
-        'M2');
+      leftHandSide.staticElement,
+      findElement.setter('x', of: 'M2'),
+    );
+    expect(
+      leftHandSide.auxiliaryElements.staticElement,
+      findElement.getter('x', of: 'M2'),
+    );
   }
 
   @failingTest
@@ -688,7 +621,7 @@
     // TODO(paulberry): it appears that auxiliaryElements isn't properly set on
     // a SimpleIdentifier that's inside a property access.  This bug should be
     // fixed.
-    Source source = addSource(r'''
+    addTestFile(r'''
 class B {}
 class M1 {
   get x => null;
@@ -703,30 +636,24 @@
   new C().x += 1;
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    assertNoTestErrors();
+    verifyTestResolved();
+
     // Verify that both the getter and setter for "x" in "new C().x" refer to
     // the accessors defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInTopLevelFunction(analysisResult.unit, 'main');
-    var statement = statements[0] as ExpressionStatement;
-    AssignmentExpression assignment = statement.expression;
-    PropertyAccess propertyAccess = assignment.leftHandSide;
+    var leftHandSide = findNode.simple('x +=');
     expect(
-        resolutionMap
-            .staticElementForIdentifier(propertyAccess.propertyName)
-            .enclosingElement
-            .name,
-        'M2');
+      leftHandSide.staticElement,
+      findElement.setter('x', of: 'M2'),
+    );
     expect(
-        propertyAccess
-            .propertyName.auxiliaryElements.staticElement.enclosingElement.name,
-        'M2');
+      leftHandSide.auxiliaryElements.staticElement,
+      findElement.getter('x', of: 'M2'),
+    );
   }
 
   test_getter_fromMixins_bare_identifier() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   get x => null;
@@ -740,21 +667,20 @@
   }
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     // Verify that the getter for "x" in C.f() refers to the getter defined in
     // M2.
-    var statements =
-        AstFinder.getStatementsInMethod(analysisResult.unit, 'C', 'f');
-    var statement = statements[0] as ReturnStatement;
-    SimpleIdentifier x = statement.expression;
-    expect(resolutionMap.staticElementForIdentifier(x).enclosingElement.name,
-        'M2');
+    expect(
+      findNode.simple('x;').staticElement,
+      findElement.getter('x', of: 'M2'),
+    );
   }
 
   test_getter_fromMixins_property_access() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   get x => null;
@@ -767,26 +693,20 @@
   var y = new C().x;
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     // Verify that the getter for "x" in "new C().x" refers to the getter
     // defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInTopLevelFunction(analysisResult.unit, 'main');
-    var statement = statements[0] as VariableDeclarationStatement;
-    PropertyAccess propertyAccess =
-        statement.variables.variables[0].initializer;
     expect(
-        resolutionMap
-            .staticElementForIdentifier(propertyAccess.propertyName)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('x;').staticElement,
+      findElement.getter('x', of: 'M2'),
+    );
   }
 
   test_getterAndSetterWithDifferentTypes() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   int get f => 0;
   void set f(String s) {}
@@ -794,38 +714,35 @@
 g (A a) {
   a.f = a.f.toString();
 }''');
-    await computeAnalysisResult(source);
-    assertErrors(
-        source, [StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
-    verify([source]);
+    await resolveTestFile();
+    assertTestErrors([StaticWarningCode.MISMATCHED_GETTER_AND_SETTER_TYPES]);
+    verifyTestResolved();
   }
 
   test_hasReferenceToSuper() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {}
 class B {toString() => super.toString();}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(2));
-    expect(classes[0].hasReferenceToSuper, isFalse);
-    expect(classes[1].hasReferenceToSuper, isTrue);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
+    expect(a.hasReferenceToSuper, isFalse);
+
+    var b = findElement.class_('B');
+    expect(b.hasReferenceToSuper, isTrue);
   }
 
   test_import_hide() async {
-    addNamedSource("/lib1.dart", r'''
-library lib1;
+    newFile('/test/lib/lib1.dart', content: r'''
 set foo(value) {}
 class A {}''');
-    addNamedSource("/lib2.dart", r'''
-library lib2;
+
+    newFile('/test/lib/lib2.dart', content: r'''
 set foo(value) {}''');
-    Source source = addNamedSource("/lib3.dart", r'''
+
+    addTestFile(r'''
 import 'lib1.dart' hide foo;
 import 'lib2.dart';
 
@@ -833,26 +750,25 @@
   foo = 0;
 }
 A a;''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_import_prefix() async {
-    addNamedSource("/two.dart", r'''
-library two;
+    newFile('/test/lib/a.dart', content: r'''
 f(int x) {
   return x * x;
 }''');
-    Source source = addNamedSource("/one.dart", r'''
-library one;
-import 'two.dart' as _two;
+
+    addTestFile(r'''
+import 'a.dart' as _a;
 main() {
-  _two.f(0);
+  _a.f(0);
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_import_prefix_doesNotExist() async {
@@ -861,7 +777,7 @@
     // single error generated when the only problem is that an imported file
     // does not exist.
     //
-    Source source = addNamedSource("/a.dart", r'''
+    addTestFile('''
 import 'missing.dart' as p;
 int a = p.q + p.r.s;
 String b = p.t(a) + p.u(v: 0);
@@ -878,9 +794,9 @@
   H(int i) : super(i);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
-    verify([source]);
+    await resolveTestFile();
+    assertTestErrors([CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    verifyTestResolved();
   }
 
   test_import_show_doesNotExist() async {
@@ -889,7 +805,7 @@
     // single error generated when the only problem is that an imported file
     // does not exist.
     //
-    Source source = addNamedSource("/a.dart", r'''
+    addTestFile('''
 import 'missing.dart' show q, r, t, u, T, U, V, W;
 int a = q + r.s;
 String b = t(a) + u(v: 0);
@@ -906,28 +822,28 @@
   H(int i) : super(i);
 }
 ''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
-    verify([source]);
+    await resolveTestFile();
+    assertTestErrors([CompileTimeErrorCode.URI_DOES_NOT_EXIST]);
+    verifyTestResolved();
   }
 
+  @failingTest
   test_import_spaceInUri() async {
-    addNamedSource("/sub folder/lib.dart", r'''
-library lib;
+    // TODO(scheglov) Fix this. The problem is in `package` URI resolver.
+    newFile('/test/lib/sub folder/a.dart', content: r'''
 foo() {}''');
-    Source source = addNamedSource("/app.dart", r'''
-import 'sub folder/lib.dart';
+
+    await assertNoErrorsInCode(r'''
+import 'sub folder/a.dart';
 
 main() {
   foo();
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_indexExpression_typeParameters() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 f() {
   List<int> a;
   a[0];
@@ -936,24 +852,22 @@
   List<List<List<int>>> c;
   c[0][0][0];
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_indexExpression_typeParameters_invalidAssignmentWarning() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 f() {
   List<List<int>> b;
   b[0][0] = 'hi';
 }''');
-    await computeAnalysisResult(source);
-    assertErrors(source, [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
-    verify([source]);
+    await resolveTestFile();
+    assertTestErrors([StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+    verifyTestResolved();
   }
 
   test_indirectOperatorThroughCall() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   B call() { return new B(); }
 }
@@ -969,113 +883,91 @@
 main() {
   g(f()[0]);
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_invoke_dynamicThroughGetter() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 class A {
   List get X => [() => 0];
   m(A a) {
     X.last;
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_isValidMixin_badSuperclass() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A extends B {}
 class B {}
 class C = Object with A;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    ClassElement a = unit.getType('A');
+    await resolveTestFile();
+    assertTestErrors([CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
     expect(a.isValidMixin, isFalse);
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.MIXIN_INHERITS_FROM_NOT_OBJECT]);
-    verify([source]);
   }
 
   test_isValidMixin_constructor() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   A() {}
 }
 class C = Object with A;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    ClassElement a = unit.getType('A');
-    expect(a.isValidMixin, isFalse);
-    await computeAnalysisResult(source);
-    assertErrors(
-      source,
+    await resolveTestFile();
+    assertTestErrors(
       [CompileTimeErrorCode.MIXIN_CLASS_DECLARES_CONSTRUCTOR],
     );
-    verify([source]);
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
+    expect(a.isValidMixin, isFalse);
   }
 
   test_isValidMixin_factoryConstructor() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   factory A() => null;
 }
 class C = Object with A;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    ClassElement a = unit.getType('A');
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
     expect(a.isValidMixin, isTrue);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_isValidMixin_super() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   toString() {
     return super.toString();
   }
 }
 class C = Object with A;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    ClassElement a = unit.getType('A');
+    await resolveTestFile();
+    assertTestErrors([CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
     expect(a.isValidMixin, isFalse);
-    await computeAnalysisResult(source);
-    assertErrors(source, [CompileTimeErrorCode.MIXIN_REFERENCES_SUPER]);
-    verify([source]);
   }
 
   test_isValidMixin_valid() async {
-    Source source = addSource('''
+    await assertNoErrorsInCode('''
 class A {}
 class C = Object with A;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    ClassElement a = unit.getType('A');
+    verifyTestResolved();
+
+    var a = findElement.class_('A');
     expect(a.isValidMixin, isTrue);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_labels_switch() async {
-    Source source = addSource(r'''
+    await assertNoErrorsInCode(r'''
 void doSwitch(int target) {
   switch (target) {
     l0: case 0:
@@ -1086,269 +978,174 @@
       continue l1;
   }
 }''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    verifyTestResolved();
   }
 
   test_localVariable_types_invoked() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 main() {
   var myVar = (int p) => 'foo';
   myVar(42);
 }''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnit unit =
-        analysisContext.resolveCompilationUnit(source, library);
-    expect(unit, isNotNull);
-    List<bool> found = [false];
-    List<CaughtException> thrownException = new List<CaughtException>(1);
-    unit.accept(new _SimpleResolverTest_localVariable_types_invoked(
-        this, found, thrownException));
-    if (thrownException[0] != null) {
-      throw new AnalysisException(
-          "Exception", new CaughtException(thrownException[0], null));
-    }
-    expect(found[0], isTrue);
+    await resolveTestFile();
+
+    var node = findNode.simple('myVar(42)');
+    assertType(node, '(int) → String');
   }
 
   test_metadata_class() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 @A class C<A> {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unitElement = library.definingCompilationUnit;
-    expect(unitElement, isNotNull);
-    List<ClassElement> classes = unitElement.types;
-    expect(classes, hasLength(1));
-    List<ElementAnnotation> annotations = classes[0].metadata;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var annotations = findElement.class_('C').metadata;
     expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
 
-    CompilationUnit unit = resolveCompilationUnit(source, library);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(2));
-
-    TopLevelVariableDeclaration variableDeclaration = declarations[0];
-    ClassDeclaration classDeclaration = declarations[1];
-
-    PropertyInducingElement expectedElement =
-        variableDeclaration.variables.variables[0].name.staticElement;
-
-    Element actualElement = classDeclaration.metadata[0].name.staticElement;
-    expect(actualElement, same(expectedElement.getter));
+    var cDeclaration = findNode.classDeclaration('C<A>');
+    assertElement(
+      cDeclaration.metadata[0].name,
+      findElement.topGet('A'),
+    );
   }
 
   test_metadata_field() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 class C {
   @A int f;
 }''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    FieldElement field = classes[0].fields[0];
-    List<ElementAnnotation> annotations = field.metadata;
-    expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.field('f').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_fieldFormalParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 class C {
   int f;
   C(@A this.f);
 }''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    List<ConstructorElement> constructors = classes[0].constructors;
-    expect(constructors, hasLength(1));
-    List<ParameterElement> parameters = constructors[0].parameters;
-    expect(parameters, hasLength(1));
-    List<ElementAnnotation> annotations = parameters[0].metadata;
-    expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.fieldFormalParameter('f').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_function() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 @A f() {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<FunctionElement> functions = unit.functions;
-    expect(functions, hasLength(1));
-    List<ElementAnnotation> annotations = functions[0].metadata;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var annotations = findElement.topFunction('f').metadata;
     expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
   }
 
   test_metadata_functionTypedParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 f(@A int p(int x)) {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<FunctionElement> functions = unit.functions;
-    expect(functions, hasLength(1));
-    List<ParameterElement> parameters = functions[0].parameters;
-    expect(parameters, hasLength(1));
-    List<ElementAnnotation> annotations1 = parameters[0].metadata;
-    expect(annotations1, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.parameter('p').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_libraryDirective() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 @A library lib;
 const A = null;''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    List<ElementAnnotation> annotations = library.metadata;
-    expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = result.libraryElement.metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_method() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 class C {
   @A void m() {}
 }''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<ClassElement> classes = unit.types;
-    expect(classes, hasLength(1));
-    MethodElement method = classes[0].methods[0];
-    List<ElementAnnotation> annotations = method.metadata;
-    expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.method('m').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_namedParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 f({@A int p : 0}) {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<FunctionElement> functions = unit.functions;
-    expect(functions, hasLength(1));
-    List<ParameterElement> parameters = functions[0].parameters;
-    expect(parameters, hasLength(1));
-    List<ElementAnnotation> annotations1 = parameters[0].metadata;
-    expect(annotations1, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.parameter('p').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_positionalParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 f([@A int p = 0]) {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<FunctionElement> functions = unit.functions;
-    expect(functions, hasLength(1));
-    List<ParameterElement> parameters = functions[0].parameters;
-    expect(parameters, hasLength(1));
-    List<ElementAnnotation> annotations1 = parameters[0].metadata;
-    expect(annotations1, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    var metadata = findElement.parameter('p').metadata;
+    expect(metadata, hasLength(1));
   }
 
   test_metadata_simpleParameter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 f(@A p1, @A int p2) {}''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unit = library.definingCompilationUnit;
-    expect(unit, isNotNull);
-    List<FunctionElement> functions = unit.functions;
-    expect(functions, hasLength(1));
-    List<ParameterElement> parameters = functions[0].parameters;
-    expect(parameters, hasLength(2));
-    List<ElementAnnotation> annotations1 = parameters[0].metadata;
-    expect(annotations1, hasLength(1));
-    List<ElementAnnotation> annotations2 = parameters[1].metadata;
-    expect(annotations2, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
+    expect(findElement.parameter('p1').metadata, hasLength(1));
+    expect(findElement.parameter('p2').metadata, hasLength(1));
   }
 
   test_metadata_typedef() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 const A = null;
 @A typedef F<A>();''');
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    CompilationUnitElement unitElement = library.definingCompilationUnit;
-    expect(unitElement, isNotNull);
-    List<FunctionTypeAliasElement> aliases = unitElement.functionTypeAliases;
-    expect(aliases, hasLength(1));
-    List<ElementAnnotation> annotations = aliases[0].metadata;
-    expect(annotations, hasLength(1));
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    CompilationUnit unit = resolveCompilationUnit(source, library);
-    NodeList<CompilationUnitMember> declarations = unit.declarations;
-    expect(declarations, hasLength(2));
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
 
-    TopLevelVariableDeclaration variableDeclaration = declarations[0];
-    FunctionTypeAlias functionTypeAlias = declarations[1];
+    expect(
+      findElement.genericTypeAlias('F').metadata,
+      hasLength(1),
+    );
 
-    PropertyInducingElement expectedElement =
-        variableDeclaration.variables.variables[0].name.staticElement;
-
-    Element actualElement = functionTypeAlias.metadata[0].name.staticElement;
-    expect(actualElement, same(expectedElement.getter));
+    var actualElement = findNode.annotation('@A').name.staticElement;
+    expect(actualElement, findElement.topGet('A'));
   }
 
   test_method_fromMixin() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class B {
   bar() => 1;
 }
@@ -1360,13 +1157,13 @@
   bar() => super.bar();
   foo() => super.foo();
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_method_fromMixins() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   void f() {}
@@ -1379,24 +1176,18 @@
   new C().f();
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that the "f" in "new C().f()" refers to the "f" defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInTopLevelFunction(analysisResult.unit, 'main');
-    var statement = statements[0] as ExpressionStatement;
-    MethodInvocation expr = statement.expression;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     expect(
-        resolutionMap
-            .staticElementForIdentifier(expr.methodName)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('f();').staticElement,
+      findElement.method('f', of: 'M2'),
+    );
   }
 
   test_method_fromMixins_bare_identifier() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   void f() {}
@@ -1410,25 +1201,18 @@
   }
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that the call to f() in C.g() refers to the method defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInMethod(analysisResult.unit, 'C', 'g');
-    var statement = statements[0] as ExpressionStatement;
-    MethodInvocation invocation = statement.expression;
-    SimpleIdentifier methodName = invocation.methodName;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     expect(
-        resolutionMap
-            .staticElementForIdentifier(methodName)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('f();').staticElement,
+      findElement.method('f', of: 'M2'),
+    );
   }
 
   test_method_fromMixins_invoked_from_outside_class() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   void f() {}
@@ -1441,25 +1225,18 @@
   new C().f();
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that the call to f() in "new C().f()" refers to the method
-    // defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInTopLevelFunction(analysisResult.unit, 'main');
-    var statement = statements[0] as ExpressionStatement;
-    MethodInvocation invocation = statement.expression;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     expect(
-        resolutionMap
-            .staticElementForIdentifier(invocation.methodName)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('f();').staticElement,
+      findElement.method('f', of: 'M2'),
+    );
   }
 
   test_method_fromSuperclassMixin() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void m1() {}
 }
@@ -1470,13 +1247,13 @@
 f(C c) {
   c.m1();
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_methodCascades() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   void m1() {}
   void m2() {}
@@ -1486,13 +1263,13 @@
      ..m2();
   }
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_methodCascades_withSetter() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   String name;
   void m1() {}
@@ -1504,23 +1281,23 @@
      ..m2();
   }
 }''');
-    // failing with error code: INVOCATION_OF_NON_FUNCTION
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_resolveAgainstNull() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 f(var p) {
   return null == p;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_setter_fromMixins_bare_identifier() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   set x(value) {}
@@ -1534,26 +1311,18 @@
   }
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that the setter for "x" in C.f() refers to the setter defined in
-    // M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInMethod(analysisResult.unit, 'C', 'f');
-    var statement = statements[0] as ExpressionStatement;
-    AssignmentExpression assignment = statement.expression;
-    SimpleIdentifier leftHandSide = assignment.leftHandSide;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     expect(
-        resolutionMap
-            .staticElementForIdentifier(leftHandSide)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('x = ').staticElement,
+      findElement.setter('x', of: 'M2'),
+    );
   }
 
   test_setter_fromMixins_property_access() async {
-    Source source = addSource('''
+    addTestFile('''
 class B {}
 class M1 {
   set x(value) {}
@@ -1566,26 +1335,18 @@
   new C().x = 1;
 }
 ''');
-    var analysisResult = await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-    // Verify that the setter for "x" in "new C().x" refers to the setter
-    // defined in M2.
-    List<Statement> statements =
-        AstFinder.getStatementsInTopLevelFunction(analysisResult.unit, 'main');
-    var statement = statements[0] as ExpressionStatement;
-    AssignmentExpression assignment = statement.expression;
-    PropertyAccess propertyAccess = assignment.leftHandSide;
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
+
     expect(
-        resolutionMap
-            .staticElementForIdentifier(propertyAccess.propertyName)
-            .enclosingElement
-            .name,
-        'M2');
+      findNode.simple('x = ').staticElement,
+      findElement.setter('x', of: 'M2'),
+    );
   }
 
   test_setter_inherited() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 class A {
   int get x => 0;
   set x(int p) {}
@@ -1594,49 +1355,41 @@
   int get x => super.x == null ? 0 : super.x;
   int f() => x = 1;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   test_setter_static() async {
-    Source source = addSource(r'''
+    addTestFile(r'''
 set s(x) {
 }
 
 main() {
   s = 123;
 }''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  @failingTest
-  test_staticInvocation() async {
-    Source source = addSource(r'''
-class A {
-  static int get g => (a,b) => 0;
-}
-class B {
-  f() {
-    A.g(1,0);
-  }
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
+    await resolveTestFile();
+    assertNoTestErrors();
+    verifyTestResolved();
   }
 
   /**
-   * Resolve the given source and verify that the arguments in a specific method invocation were
-   * correctly resolved.
+   * Verify that all of the identifiers in the [result] have been resolved.
+   */
+  void verifyTestResolved() {
+    var verifier = new ResolutionVerifier();
+    result.unit.accept(verifier);
+    verifier.assertResolved();
+  }
+
+  /**
+   * Resolve the test file and verify that the arguments in a specific method
+   * invocation were correctly resolved.
    *
-   * The source is expected to be source for a compilation unit, the first declaration is expected
-   * to be a class, the first member of which is expected to be a method with a block body, and the
-   * first statement in the body is expected to be an expression statement whose expression is a
-   * method invocation. It is the arguments to that method invocation that are tested. The method
-   * invocation can contain errors.
+   * The file is expected to define a method named `g`, and has exactly one
+   * [MethodInvocation] in a statement ending with `);`. It is the arguments to
+   * that method invocation that are tested. The method invocation can contain
+   * errors.
    *
    * The arguments were resolved correctly if the number of expressions in the list matches the
    * length of the array of indices and if, for each index in the array of indices, the parameter to
@@ -1644,66 +1397,33 @@
    * parameters at that index. Arguments that should not be resolved to a parameter because of an
    * error can be denoted by including a negative index in the array of indices.
    *
-   * @param source the source to be resolved
    * @param indices the array of indices used to associate arguments with parameters
    * @throws Exception if the source could not be resolved or if the structure of the source is not
    *           valid
    */
-  void _validateArgumentResolution(Source source, List<int> indices) {
-    LibraryElement library = resolve2(source);
-    expect(library, isNotNull);
-    ClassElement classElement = library.definingCompilationUnit.types[0];
-    List<ParameterElement> parameters = classElement.methods[1].parameters;
-    CompilationUnit unit = resolveCompilationUnit(source, library);
-    expect(unit, isNotNull);
-    ClassDeclaration classDeclaration =
-        unit.declarations[0] as ClassDeclaration;
-    MethodDeclaration methodDeclaration =
-        classDeclaration.members[0] as MethodDeclaration;
-    Block block = (methodDeclaration.body as BlockFunctionBody).block;
-    ExpressionStatement statement = block.statements[0] as ExpressionStatement;
-    MethodInvocation invocation = statement.expression as MethodInvocation;
-    NodeList<Expression> arguments = invocation.argumentList.arguments;
-    int argumentCount = arguments.length;
+  Future<void> _validateArgumentResolution(List<int> indices) async {
+    await resolveTestFile();
+
+    var g = findElement.method('g');
+    var parameters = g.parameters;
+
+    var invocation = findNode.methodInvocation(');');
+
+    var arguments = invocation.argumentList.arguments;
+
+    var argumentCount = arguments.length;
     expect(argumentCount, indices.length);
-    for (int i = 0; i < argumentCount; i++) {
-      Expression argument = arguments[i];
-      ParameterElement element = argument.staticParameterElement;
-      int index = indices[i];
+
+    for (var i = 0; i < argumentCount; i++) {
+      var argument = arguments[i];
+      var actualParameter = argument.staticParameterElement;
+
+      var index = indices[i];
       if (index < 0) {
-        expect(element, isNull);
+        expect(actualParameter, isNull);
       } else {
-        expect(element, same(parameters[index]));
-      }
-    }
-  }
-}
-
-class _SimpleResolverTest_localVariable_types_invoked
-    extends RecursiveAstVisitor<void> {
-  final SimpleResolverTest test;
-
-  List<bool> found;
-
-  List<CaughtException> thrownException;
-
-  _SimpleResolverTest_localVariable_types_invoked(
-      this.test, this.found, this.thrownException)
-      : super();
-
-  @override
-  void visitSimpleIdentifier(SimpleIdentifier node) {
-    if (node.name == "myVar" && node.parent is MethodInvocation) {
-      try {
-        found[0] = true;
-        // check static type
-        DartType staticType = node.staticType;
-        expect(staticType is FunctionType, isTrue);
-        FunctionType functionType = staticType;
-        expect(functionType.parameters[0].type, test.typeProvider.intType);
-        expect(functionType.returnType, test.typeProvider.stringType);
-      } on AnalysisException catch (e, stackTrace) {
-        thrownException[0] = new CaughtException(e, stackTrace);
+        var expectedParameter = parameters[index];
+        expect(actualParameter, same(expectedParameter));
       }
     }
   }
diff --git a/pkg/analyzer/test/generated/static_type_analyzer_test.dart b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
index 5deedc3..c6bafc8 100644
--- a/pkg/analyzer/test/generated/static_type_analyzer_test.dart
+++ b/pkg/analyzer/test/generated/static_type_analyzer_test.dart
@@ -1540,7 +1540,6 @@
     _visitor = new ResolverVisitor(
         inheritance, definingLibrary, source, _typeProvider, _listener,
         nameScope: new LibraryScope(definingLibrary));
-    _visitor.overrideManager.enterScope();
     return _visitor.typeAnalyzer;
   }
 
diff --git a/pkg/analyzer/test/generated/static_type_warning_code.dart b/pkg/analyzer/test/generated/static_type_warning_code.dart
index def61b4..01f0538 100644
--- a/pkg/analyzer/test/generated/static_type_warning_code.dart
+++ b/pkg/analyzer/test/generated/static_type_warning_code.dart
@@ -185,13 +185,6 @@
     ]);
   }
 
-  test_defaultSetLiteralNotEnabled() async {
-    await assertErrorsInCode(r'''
-void main() {
-  Set _ = {};
-}''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
-  }
-
   test_expectedOneListTypeArgument() async {
     await assertErrorsInCode(r'''
 main() {
diff --git a/pkg/analyzer/test/generated/static_warning_code_test.dart b/pkg/analyzer/test/generated/static_warning_code_test.dart
index cccdf34..53664c9 100644
--- a/pkg/analyzer/test/generated/static_warning_code_test.dart
+++ b/pkg/analyzer/test/generated/static_warning_code_test.dart
@@ -2173,136 +2173,6 @@
     verify([source]);
   }
 
-  test_invalidOverride_defaultOverridesNonDefault() async {
-    // 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.
-    Source source = addSource(r'''
-class A {
-  foo([x = 1]) {}
-}
-class B extends A {
-  foo([x]) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverride_defaultOverridesNonDefault_named() async {
-    // 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.
-    Source source = addSource(r'''
-class A {
-  foo({x: 1}) {}
-}
-class B extends A {
-  foo({x}) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverride_defaultOverridesNonDefaultNull() async {
-    // If the base class provided an explicit null value for a default
-    // parameter, then it is ok for the derived class to let the default value
-    // be implicit, because the implicit default value of null matches the
-    // explicit default value of null.
-    Source source = addSource(r'''
-class A {
-  foo([x = null]) {}
-}
-class B extends A {
-  foo([x]) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverride_defaultOverridesNonDefaultNull_named() async {
-    // If the base class provided an explicit null value for a default
-    // parameter, then it is ok for the derived class to let the default value
-    // be implicit, because the implicit default value of null matches the
-    // explicit default value of null.
-    Source source = addSource(r'''
-class A {
-  foo({x: null}) {}
-}
-class B extends A {
-  foo({x}) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverride_nonDefaultOverridesDefault() async {
-    // If the base class lets the default parameter be implicit, then it is ok
-    // for the derived class to provide an explicit default value, even if it's
-    // not null.
-    Source source = addSource(r'''
-class A {
-  foo([x]) {}
-}
-class B extends A {
-  foo([x = 1]) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverride_nonDefaultOverridesDefault_named() async {
-    // If the base class lets the default parameter be implicit, then it is ok
-    // for the derived class to provide an explicit default value, even if it's
-    // not null.
-    Source source = addSource(r'''
-class A {
-  foo({x}) {}
-}
-class B extends A {
-  foo({x: 1}) {}
-}
-''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_named() async {
-    Source source = addSource(r'''
-class A {
-  m({int p : 0}) {}
-}
-class B extends A {
-  m({int p : 1}) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
-  test_invalidOverrideDifferentDefaultValues_positional() async {
-    Source source = addSource(r'''
-class A {
-  m([int p = 0]) {}
-}
-class B extends A {
-  m([int p = 1]) {}
-}''');
-    await computeAnalysisResult(source);
-    assertNoErrors(source);
-    verify([source]);
-  }
-
   test_invalidOverrideNamed_fewerNamedParameters() async {
     Source source = addSource(r'''
 class A {
diff --git a/pkg/analyzer/test/generated/strong_mode.dart b/pkg/analyzer/test/generated/strong_mode.dart
index 01050fa..d5d561b 100644
--- a/pkg/analyzer/test/generated/strong_mode.dart
+++ b/pkg/analyzer/test/generated/strong_mode.dart
@@ -13,10 +13,10 @@
 import 'package:analyzer/src/generated/engine.dart';
 import 'package:analyzer/src/generated/source_io.dart';
 import 'package:analyzer/src/task/strong/ast_properties.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:front_end/src/base/errors.dart';
 import 'package:test/test.dart';
 
-import '../src/dart/resolution/find_node.dart';
 import '../utils.dart';
 import 'resolver_test_case.dart';
 
diff --git a/pkg/analyzer/test/src/abstract_single_unit.dart b/pkg/analyzer/test/src/abstract_single_unit.dart
index 164b2f5..d42f775 100644
--- a/pkg/analyzer/test/src/abstract_single_unit.dart
+++ b/pkg/analyzer/test/src/abstract_single_unit.dart
@@ -5,6 +5,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
 import 'package:analyzer/src/generated/source.dart';
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 4797e9d..f5d7695 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_resolution_test.dart
@@ -16,12 +16,12 @@
 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/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../utils.dart';
-import '../resolution/find_element.dart';
-import '../resolution/find_node.dart';
 import 'base.dart';
 
 main() {
@@ -5209,23 +5209,6 @@
     }
   }
 
-  test_mapLiteral_1() async {
-    addTestFile(r'''
-main() {
-  var v = <int>{};
-}
-''');
-    await resolveTestFile();
-    expect(result.errors, isNotEmpty);
-
-    var literal = findNode.mapLiteral('<int>{}');
-    assertType(literal, 'Map<dynamic, dynamic>');
-
-    var intRef = findNode.simple('int>{}');
-    assertElement(intRef, intElement);
-    assertType(intRef, 'int');
-  }
-
   test_mapLiteral_3() async {
     addTestFile(r'''
 main() {
@@ -6732,6 +6715,24 @@
     assertElement(tReference, tElement);
   }
 
+  test_setLiteral() async {
+    addTestFile(r'''
+main() {
+  var v = <int>{};
+  print(v);
+}
+''');
+    await resolveTestFile();
+    expect(result.errors, isEmpty);
+
+    var literal = findNode.setLiteral('<int>{}');
+    assertType(literal, 'Set<int>');
+
+    var intRef = findNode.simple('int>{}');
+    assertElement(intRef, intElement);
+    assertType(intRef, 'int');
+  }
+
   test_stringInterpolation() async {
     String content = r'''
 void main() {
diff --git a/pkg/analyzer/test/src/dart/analysis/driver_test.dart b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
index b1ade98..5cfbae5 100644
--- a/pkg/analyzer/test/src/dart/analysis/driver_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/driver_test.dart
@@ -31,6 +31,7 @@
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
+import '../../../util/element_type_matchers.dart';
 import '../../../utils.dart';
 import 'base.dart';
 
@@ -1116,7 +1117,7 @@
         await createAnalysisDriver().test.getSummaryStore(a);
 
     // There are at least a.dart and dart:core libraries.
-    String aUri = toUri(a).toString();
+    String aUri = toUriStr(a);
     expect(summaryStore.unlinkedMap.keys, contains(aUri));
     expect(summaryStore.linkedMap.keys, contains(aUri));
     expect(summaryStore.unlinkedMap.keys, contains('dart:core'));
@@ -1158,8 +1159,8 @@
     SummaryDataStore summaryStore =
         await createAnalysisDriver().test.getSummaryStore(a);
 
-    String aUri = toUri(a).toString();
-    String bUri = toUri(b).toString();
+    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);
@@ -1867,7 +1868,7 @@
     ClassDeclaration c = result.unit.declarations[1] as ClassDeclaration;
     Annotation a = c.metadata[0];
     expect(a.name.name, 'fff');
-    expect(a.name.staticElement, new TypeMatcher<FunctionElement>());
+    expect(a.name.staticElement, isFunctionElement);
   }
 
   test_getResult_invalidUri() async {
@@ -2076,7 +2077,7 @@
       ResolvedUnitResult result = await driver.getResult(c);
       expect(
         _getImportSource(result.unit, 0).uri,
-        toUri(convertPath('/test/lib/a.dart')),
+        toUri('/test/lib/a.dart'),
       );
       expect(_getTopLevelVarType(result.unit, 'VC'), 'A<double>');
     }
@@ -2427,6 +2428,32 @@
     expect(_getTopLevelVarType(result.unit, 'b'), 'B');
   }
 
+  test_importOfNonLibrary_part_afterLibrary() async {
+    var a = convertPath('/test/lib/a.dart');
+    var b = convertPath('/test/lib/b.dart');
+    var c = convertPath('/test/lib/c.dart');
+
+    newFile(a, content: '''
+library my.lib;
+
+part 'b.dart';
+''');
+    newFile(b, content: '''
+part of my.lib;
+
+class A {}
+''');
+    newFile(c, content: '''
+import 'b.dart';
+''');
+
+    // This ensures that `a.dart` linked library is cached.
+    await driver.getResult(a);
+
+    // Should not fail because of considering `b.dart` part as `a.dart` library.
+    await driver.getResult(c);
+  }
+
   test_instantiateToBounds_invalid() async {
     var a = convertPath('/test/lib/a.dart');
     newFile(a, content: r'''
diff --git a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
index 119f2b3..0a97168 100644
--- a/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/file_state_test.dart
@@ -889,6 +889,29 @@
     _assertFilesWithoutLibraryCycle([fa, fb, fc]);
   }
 
+  test_transitiveSignature_part() {
+    var aPath = convertPath('/test/lib/a.dart');
+    var bPath = convertPath('/test/lib/b.dart');
+
+    newFile(aPath, content: r'''
+part 'b.dart';
+''');
+    newFile(bPath, content: '''
+part of 'a.dart';
+''');
+
+    var aFile = fileSystemState.getFileForPath(aPath);
+    var bFile = fileSystemState.getFileForPath(bPath);
+
+    var aSignature = aFile.transitiveSignature;
+    var bSignature = bFile.transitiveSignature;
+
+    // It is not valid to use a part as a library, and so ask its signature.
+    // But when this happens, we should compute the transitive signature anyway.
+    // And it should not be the signature of the containing library.
+    expect(bSignature, isNot(aSignature));
+  }
+
   void _assertExportedTopLevelDeclarations(String path, List<String> expected) {
     FileState file = fileSystemState.getFileForPath(path);
     Map<String, TopLevelDeclaration> declarations =
diff --git a/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
index f829d24..097d3ed 100644
--- a/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/referenced_names_test.dart
@@ -431,6 +431,14 @@
     expect(names, unorderedEquals(['A', 'B', 'C', 'D', 'E']));
   }
 
+  void test_mixinDeclaration() {
+    Set<String> names = _computeSubtypedNames('''
+import 'lib.dart';
+mixin M on A, B implements C, D {}
+''');
+    expect(names, unorderedEquals(['A', 'B', 'C', 'D']));
+  }
+
   void test_prefixed() {
     Set<String> names = _computeSubtypedNames('''
 import 'lib.dart' as p;
diff --git a/pkg/analyzer/test/src/dart/analysis/search_test.dart b/pkg/analyzer/test/src/dart/analysis/search_test.dart
index 8be9b97..e0f2b7d 100644
--- a/pkg/analyzer/test/src/dart/analysis/search_test.dart
+++ b/pkg/analyzer/test/src/dart/analysis/search_test.dart
@@ -10,6 +10,7 @@
 import 'package:analyzer/dart/ast/standard_resolution_map.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/dart/analysis/search.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/element/member.dart';
 import 'package:analyzer/src/generated/testing/element_search.dart';
@@ -1894,6 +1895,45 @@
     expect(c.id, endsWith('c.dart;C'));
   }
 
+  test_subtypes_mixin_superclassConstraints() async {
+    await _resolveTestUnit('''
+class A {
+  void methodA() {}
+}
+
+class B {
+  void methodB() {}
+}
+
+mixin M on A, B {
+  void methodA() {}
+  void methodM() {}
+}
+''');
+    ClassElement a = _findElement('A');
+    ClassElement b = _findElement('B');
+
+    {
+      var subtypes = await driver.search.subtypes(type: a);
+      expect(subtypes, hasLength(1));
+
+      var m = subtypes.singleWhere((r) => r.name == 'M');
+      expect(m.libraryUri, testUri);
+      expect(m.id, '$testUri;$testUri;M');
+      expect(m.members, ['methodA', 'methodM']);
+    }
+
+    {
+      var subtypes = await driver.search.subtypes(type: b);
+      expect(subtypes, hasLength(1));
+
+      var m = subtypes.singleWhere((r) => r.name == 'M');
+      expect(m.libraryUri, testUri);
+      expect(m.id, '$testUri;$testUri;M');
+      expect(m.members, ['methodA', 'methodM']);
+    }
+  }
+
   test_subtypes_partWithoutLibrary() async {
     await _resolveTestUnit('''
 part of lib;
diff --git a/pkg/analyzer/test/src/dart/ast/constant_evaluator_test.dart b/pkg/analyzer/test/src/dart/ast/constant_evaluator_test.dart
new file mode 100644
index 0000000..ac0dc66
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/ast/constant_evaluator_test.dart
@@ -0,0 +1,355 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/ast/constant_evaluator.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'parse_base.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ConstantEvaluatorTest);
+  });
+}
+
+@reflectiveTest
+class ConstantEvaluatorTest extends ParseBase {
+  void test_binary_bitAnd() {
+    int value = _getConstantValue("74 & 42");
+    expect(value, 74 & 42);
+  }
+
+  void test_binary_bitOr() {
+    int value = _getConstantValue("74 | 42");
+    expect(value, 74 | 42);
+  }
+
+  void test_binary_bitXor() {
+    int value = _getConstantValue("74 ^ 42");
+    expect(value, 74 ^ 42);
+  }
+
+  void test_binary_divide_double() {
+    Object value = _getConstantValue("3.2 / 2.3");
+    expect(value, 3.2 / 2.3);
+  }
+
+  void test_binary_divide_integer() {
+    Object value = _getConstantValue("3 / 2");
+    expect(value, 1.5);
+  }
+
+  void test_binary_equal_boolean() {
+    Object value = _getConstantValue("true == false");
+    expect(value, false);
+  }
+
+  void test_binary_equal_integer() {
+    Object value = _getConstantValue("2 == 3");
+    expect(value, false);
+  }
+
+  void test_binary_equal_invalidLeft() {
+    Object value = _getConstantValue("a == 3");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_equal_invalidRight() {
+    Object value = _getConstantValue("2 == a");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_equal_string() {
+    Object value = _getConstantValue("'a' == 'b'");
+    expect(value, false);
+  }
+
+  void test_binary_greaterThan() {
+    Object value = _getConstantValue("2 > 3");
+    expect(value, false);
+  }
+
+  void test_binary_greaterThanOrEqual() {
+    Object value = _getConstantValue("2 >= 3");
+    expect(value, false);
+  }
+
+  void test_binary_leftShift() {
+    int value = _getConstantValue("16 << 2");
+    expect(value, 64);
+  }
+
+  void test_binary_lessThan() {
+    Object value = _getConstantValue("2 < 3");
+    expect(value, true);
+  }
+
+  void test_binary_lessThanOrEqual() {
+    Object value = _getConstantValue("2 <= 3");
+    expect(value, true);
+  }
+
+  void test_binary_logicalAnd() {
+    Object value = _getConstantValue("true && false");
+    expect(value, false);
+  }
+
+  void test_binary_logicalOr() {
+    Object value = _getConstantValue("true || false");
+    expect(value, true);
+  }
+
+  void test_binary_minus_double() {
+    Object value = _getConstantValue("3.2 - 2.3");
+    expect(value, 3.2 - 2.3);
+  }
+
+  void test_binary_minus_integer() {
+    Object value = _getConstantValue("3 - 2");
+    expect(value, 1);
+  }
+
+  void test_binary_notEqual_boolean() {
+    Object value = _getConstantValue("true != false");
+    expect(value, true);
+  }
+
+  void test_binary_notEqual_integer() {
+    Object value = _getConstantValue("2 != 3");
+    expect(value, true);
+  }
+
+  void test_binary_notEqual_invalidLeft() {
+    Object value = _getConstantValue("a != 3");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_notEqual_invalidRight() {
+    Object value = _getConstantValue("2 != a");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_notEqual_string() {
+    Object value = _getConstantValue("'a' != 'b'");
+    expect(value, true);
+  }
+
+  void test_binary_plus_double() {
+    Object value = _getConstantValue("2.3 + 3.2");
+    expect(value, 2.3 + 3.2);
+  }
+
+  void test_binary_plus_double_string() {
+    Object value = _getConstantValue("'world' + 5.5");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_plus_int_string() {
+    Object value = _getConstantValue("'world' + 5");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_plus_integer() {
+    Object value = _getConstantValue("2 + 3");
+    expect(value, 5);
+  }
+
+  void test_binary_plus_string() {
+    Object value = _getConstantValue("'hello ' + 'world'");
+    expect(value, 'hello world');
+  }
+
+  void test_binary_plus_string_double() {
+    Object value = _getConstantValue("5.5 + 'world'");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_plus_string_int() {
+    Object value = _getConstantValue("5 + 'world'");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_binary_remainder_double() {
+    Object value = _getConstantValue("3.2 % 2.3");
+    expect(value, 3.2 % 2.3);
+  }
+
+  void test_binary_remainder_integer() {
+    Object value = _getConstantValue("8 % 3");
+    expect(value, 2);
+  }
+
+  void test_binary_rightShift() {
+    int value = _getConstantValue("64 >> 2");
+    expect(value, 16);
+  }
+
+  void test_binary_times_double() {
+    Object value = _getConstantValue("2.3 * 3.2");
+    expect(value, 2.3 * 3.2);
+  }
+
+  void test_binary_times_integer() {
+    Object value = _getConstantValue("2 * 3");
+    expect(value, 6);
+  }
+
+  void test_binary_truncatingDivide_double() {
+    int value = _getConstantValue("3.2 ~/ 2.3");
+    expect(value, 1);
+  }
+
+  void test_binary_truncatingDivide_integer() {
+    int value = _getConstantValue("10 ~/ 3");
+    expect(value, 3);
+  }
+
+  @failingTest
+  void test_constructor() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_class() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_function() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_static() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_staticMethod() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_topLevel() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  @failingTest
+  void test_identifier_typeParameter() {
+    Object value = _getConstantValue("?");
+    expect(value, null);
+  }
+
+  void test_literal_boolean_false() {
+    Object value = _getConstantValue("false");
+    expect(value, false);
+  }
+
+  void test_literal_boolean_true() {
+    Object value = _getConstantValue("true");
+    expect(value, true);
+  }
+
+  void test_literal_list() {
+    List value = _getConstantValue("['a', 'b', 'c']");
+    expect(value.length, 3);
+    expect(value[0], "a");
+    expect(value[1], "b");
+    expect(value[2], "c");
+  }
+
+  void test_literal_map() {
+    Map value = _getConstantValue("{'a' : 'm', 'b' : 'n', 'c' : 'o'}");
+    expect(value.length, 3);
+    expect(value["a"], "m");
+    expect(value["b"], "n");
+    expect(value["c"], "o");
+  }
+
+  void test_literal_null() {
+    Object value = _getConstantValue("null");
+    expect(value, null);
+  }
+
+  void test_literal_number_double() {
+    Object value = _getConstantValue("3.45");
+    expect(value, 3.45);
+  }
+
+  void test_literal_number_integer() {
+    Object value = _getConstantValue("42");
+    expect(value, 42);
+  }
+
+  void test_literal_string_adjacent() {
+    Object value = _getConstantValue("'abc' 'def'");
+    expect(value, "abcdef");
+  }
+
+  void test_literal_string_interpolation_invalid() {
+    Object value = _getConstantValue("'a\${f()}c'");
+    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
+  }
+
+  void test_literal_string_interpolation_valid() {
+    Object value = _getConstantValue("'a\${3}c'");
+    expect(value, "a3c");
+  }
+
+  void test_literal_string_simple() {
+    Object value = _getConstantValue("'abc'");
+    expect(value, "abc");
+  }
+
+  void test_parenthesizedExpression() {
+    Object value = _getConstantValue("('a')");
+    expect(value, "a");
+  }
+
+  void test_unary_bitNot() {
+    int value = _getConstantValue("~42");
+    expect(value, ~42);
+  }
+
+  void test_unary_logicalNot() {
+    Object value = _getConstantValue("!true");
+    expect(value, false);
+  }
+
+  void test_unary_negated_double() {
+    Object value = _getConstantValue("-42.3");
+    expect(value, -42.3);
+  }
+
+  void test_unary_negated_integer() {
+    Object value = _getConstantValue("-42");
+    expect(value, -42);
+  }
+
+  Object _getConstantValue(String expressionCode) {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: '''
+void f() {
+  ($expressionCode); // ref
+}
+''');
+
+    var parseResult = parseUnit(path);
+    expect(parseResult.errors, isEmpty);
+
+    var findNode = FindNode(parseResult.content, parseResult.unit);
+    var expression = findNode.parenthesized('); // ref').expression;
+
+    return expression.accept(ConstantEvaluator());
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/ast/element_locator_test.dart b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
new file mode 100644
index 0000000..e7e1ac1
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/ast/element_locator_test.dart
@@ -0,0 +1,368 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analyzer/src/dart/ast/element_locator.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../util/element_type_matchers.dart';
+import '../resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ElementLocatorTest);
+  });
+}
+
+@reflectiveTest
+class ElementLocatorTest extends DriverResolutionTest {
+  @override
+  AnalysisOptionsImpl get analysisOptions {
+    return AnalysisOptionsImpl()..hint = false;
+  }
+
+  test_locate_AssignmentExpression() async {
+    await _resolveTestCode(r'''
+int x = 0;
+void main() {
+  x += 1;
+}
+''');
+    var node = findNode.assignment('+=');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_BinaryExpression() async {
+    await _resolveTestCode('var x = 3 + 4');
+    var node = findNode.binary('+');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_ClassDeclaration() async {
+    await _resolveTestCode('class A {}');
+    var node = findNode.classDeclaration('class');
+    var element = ElementLocator.locate(node);
+    expect(element, isClassElement);
+  }
+
+  test_locate_CompilationUnit() async {
+    await _resolveTestCode('// only comment');
+
+    var unitElement = result.unit.declaredElement;
+    expect(unitElement, isNotNull);
+
+    var element = ElementLocator.locate(result.unit);
+    expect(element, same(unitElement));
+  }
+
+  test_locate_ConstructorDeclaration() async {
+    await _resolveTestCode(r'''
+class A {
+  A.foo();
+}
+''');
+    var node = findNode.constructor('foo();');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_ExportDirective() async {
+    await _resolveTestCode("export 'dart:code';");
+    var node = findNode.export('export');
+    var element = ElementLocator.locate(node);
+    expect(element, isExportElement);
+  }
+
+  test_locate_FunctionDeclaration() async {
+    await _resolveTestCode('int f() => 3;');
+    var node = findNode.functionDeclaration('f');
+    var element = ElementLocator.locate(node);
+    expect(element, isFunctionElement);
+  }
+
+  test_locate_Identifier_annotationClass_namedConstructor() async {
+    await _resolveTestCode(r'''
+class Class {
+  const Class.name();
+}
+void main(@Class.name() parameter) {}
+''');
+    var node = findNode.simple('Class.name() parameter');
+    var element = ElementLocator.locate(node);
+    expect(element, isClassElement);
+  }
+
+  test_locate_Identifier_annotationClass_unnamedConstructor() async {
+    await _resolveTestCode(r'''
+class Class {
+  const Class();
+}
+void main(@Class() parameter) {}
+''');
+    var node = findNode.simple('Class() parameter');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_Identifier_className() async {
+    await _resolveTestCode('class A {}');
+    var node = findNode.simple('A');
+    var element = ElementLocator.locate(node);
+    expect(element, isClassElement);
+  }
+
+  test_locate_Identifier_constructor_named() async {
+    await _resolveTestCode(r'''
+class A {
+  A.bar();
+}
+''');
+    var node = findNode.simple('bar');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_Identifier_constructor_unnamed() async {
+    await _resolveTestCode(r'''
+class A {
+  A();
+}
+''');
+    var node = findNode.constructor('A();');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_Identifier_fieldName() async {
+    await _resolveTestCode('''
+class A {
+  var x;
+}
+''');
+    var node = findNode.simple('x;');
+    var element = ElementLocator.locate(node);
+    expect(element, isFieldElement);
+  }
+
+  test_locate_Identifier_libraryDirective() async {
+    await _resolveTestCode('library foo.bar;');
+    var node = findNode.simple('foo');
+    var element = ElementLocator.locate(node);
+    expect(element, isLibraryElement);
+  }
+
+  test_locate_Identifier_propertyAccess() async {
+    await _resolveTestCode(r'''
+void main() {
+ int x = 'foo'.length;
+}
+''');
+    var node = findNode.simple('length');
+    var element = ElementLocator.locate(node);
+    expect(element, isPropertyAccessorElement);
+  }
+
+  test_locate_ImportDirective() async {
+    await _resolveTestCode("import 'dart:core';");
+    var node = findNode.import('import');
+    var element = ElementLocator.locate(node);
+    expect(element, isImportElement);
+  }
+
+  test_locate_IndexExpression() async {
+    await _resolveTestCode(r'''
+void main() {
+  var x = [1, 2];
+  var y = x[0];
+}
+''');
+    var node = findNode.index('[0]');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_InstanceCreationExpression() async {
+    await _resolveTestCode(r'''
+class A {}
+
+void main() {
+ new A();
+}
+''');
+    var node = findNode.instanceCreation('new A()');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_InstanceCreationExpression_type_prefixedIdentifier() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _resolveTestCode(r'''
+import 'a.dart' as pref;
+
+void main() {
+ new pref.A();
+}
+''');
+    var node = findNode.instanceCreation('A();');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_InstanceCreationExpression_type_simpleIdentifier() async {
+    newFile('/test/lib/a.dart', content: r'''
+''');
+    await _resolveTestCode(r'''
+class A {}
+
+void main() {
+ new A();
+}
+''');
+    var node = findNode.instanceCreation('A();');
+    var element = ElementLocator.locate(node);
+    expect(element, isConstructorElement);
+  }
+
+  test_locate_LibraryDirective() async {
+    await _resolveTestCode('library foo;');
+    var node = findNode.library('library');
+    var element = ElementLocator.locate(node);
+    expect(element, isLibraryElement);
+  }
+
+  test_locate_MethodDeclaration() async {
+    await _resolveTestCode(r'''
+class A {
+  void foo() {}
+}
+''');
+    var node = findNode.methodDeclaration('foo');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_MethodInvocation_method() async {
+    await _resolveTestCode(r'''
+class A {
+  void foo() {}
+}
+
+void main() {
+ new A().foo();
+}
+''');
+    var node = findNode.methodInvocation('foo();');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_MethodInvocation_topLevel() async {
+    await _resolveTestCode(r'''
+foo(x) {}
+
+void main() {
+ foo(0);
+}
+''');
+    var node = findNode.methodInvocation('foo(0)');
+    var element = ElementLocator.locate(node);
+    expect(element, isFunctionElement);
+  }
+
+  test_locate_PartOfDirective() async {
+    var libPath = convertPath('/test/lib/lib.dart');
+    var partPath = convertPath('/test/lib/test.dart');
+
+    newFile(libPath, content: r'''
+library my.lib;
+part 'test.dart';
+''');
+
+    driver.addFile(libPath);
+    driver.addFile(partPath);
+
+    await _resolveTestCode('part of my.lib;');
+    var node = findNode.partOf('part of');
+    var element = ElementLocator.locate(node);
+    expect(element, isLibraryElement);
+  }
+
+  test_locate_PostfixExpression() async {
+    await _resolveTestCode('int addOne(int x) => x++;');
+    var node = findNode.postfix('x++');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_PrefixedIdentifier() async {
+    await _resolveTestCode(r'''
+import 'dart:core' as core;
+core.int value;
+''');
+    var node = findNode.prefixed('core.int');
+    var element = ElementLocator.locate(node);
+    expect(element, isClassElement);
+  }
+
+  test_locate_PrefixExpression() async {
+    await _resolveTestCode('int addOne(int x) => ++x;');
+    var node = findNode.prefix('++x');
+    var element = ElementLocator.locate(node);
+    expect(element, isMethodElement);
+  }
+
+  test_locate_StringLiteral_exportUri() async {
+    newFile("/test/lib/foo.dart", content: '');
+    await _resolveTestCode("export 'foo.dart';");
+    var node = findNode.stringLiteral('foo.dart');
+    var element = ElementLocator.locate(node);
+    expect(element, isLibraryElement);
+  }
+
+  test_locate_StringLiteral_expression() async {
+    await _resolveTestCode("var x = 'abc';");
+    var node = findNode.stringLiteral('abc');
+    var element = ElementLocator.locate(node);
+    expect(element, isNull);
+  }
+
+  test_locate_StringLiteral_importUri() async {
+    newFile("/test/lib/foo.dart", content: '');
+    await _resolveTestCode("import 'foo.dart';");
+    var node = findNode.stringLiteral('foo.dart');
+    var element = ElementLocator.locate(node);
+    expect(element, isLibraryElement);
+  }
+
+  test_locate_StringLiteral_partUri() async {
+    newFile("/test/lib/foo.dart", content: 'part of lib;');
+    await _resolveTestCode('''
+library lib;
+
+part 'foo.dart';
+''');
+    var node = findNode.stringLiteral('foo.dart');
+    var element = ElementLocator.locate(node);
+    expect(element, isCompilationUnitElement);
+  }
+
+  test_locate_VariableDeclaration() async {
+    await _resolveTestCode('var x = 42;');
+    var node = findNode.variableDeclaration('x =');
+    var element = ElementLocator.locate(node);
+    expect(element, isTopLevelVariableElement);
+  }
+
+  Future<void> _resolveTestCode(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/ast/parse_base.dart b/pkg/analyzer/test/src/dart/ast/parse_base.dart
new file mode 100644
index 0000000..a157430
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/ast/parse_base.dart
@@ -0,0 +1,58 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/error/error.dart';
+import 'package:analyzer/error/listener.dart';
+import 'package:analyzer/source/line_info.dart';
+import 'package:analyzer/src/dart/scanner/reader.dart';
+import 'package:analyzer/src/dart/scanner/scanner.dart';
+import 'package:analyzer/src/generated/engine.dart';
+import 'package:analyzer/src/generated/parser.dart';
+import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
+
+class ParseBase with ResourceProviderMixin {
+  /// Override this to change the analysis options for a given set of tests.
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl();
+
+  ParseResult parseUnit(String path) {
+    var file = getFile(path);
+    var source = file.createSource();
+    var content = file.readAsStringSync();
+
+    var analysisOptions = this.analysisOptions;
+    var experimentStatus = analysisOptions.experimentStatus;
+
+    var errorListener = RecordingErrorListener();
+
+    var reader = CharSequenceReader(content);
+    var scanner = Scanner(source, reader, errorListener);
+
+    scanner.enableGtGtGt = experimentStatus.constant_update_2018;
+    var token = scanner.tokenize();
+
+    var useFasta = analysisOptions.useFastaParser;
+    var parser = Parser(source, errorListener, useFasta: useFasta);
+    parser.enableOptionalNewAndConst = true;
+    parser.enableSetLiterals = experimentStatus.set_literals;
+    parser.enableNonNullable = experimentStatus.non_nullable;
+    parser.enableSpreadCollections = experimentStatus.spread_collections;
+    parser.enableControlFlowCollections =
+        experimentStatus.control_flow_collections;
+
+    var unit = parser.parseCompilationUnit(token);
+    unit.lineInfo = LineInfo(scanner.lineStarts);
+
+    return ParseResult(path, content, unit, errorListener.errors);
+  }
+}
+
+class ParseResult {
+  final String path;
+  final String content;
+  final CompilationUnit unit;
+  final List<AnalysisError> errors;
+
+  ParseResult(this.path, this.content, this.unit, this.errors);
+}
diff --git a/pkg/analyzer/test/src/dart/ast/test_all.dart b/pkg/analyzer/test/src/dart/ast/test_all.dart
index 2330fd9..25eb567 100644
--- a/pkg/analyzer/test/src/dart/ast/test_all.dart
+++ b/pkg/analyzer/test/src/dart/ast/test_all.dart
@@ -5,11 +5,15 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'ast_test.dart' as ast;
+import 'constant_evaluator_test.dart' as constant_evaluator;
+import 'element_locator_test.dart' as element_locator;
 import 'utilities_test.dart' as utilities;
 
 main() {
   defineReflectiveSuite(() {
     ast.main();
+    constant_evaluator.main();
+    element_locator.main();
     utilities.main();
   }, name: 'ast');
 }
diff --git a/pkg/analyzer/test/src/dart/ast/utilities_test.dart b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
index 34e5ffe..1a9032b 100644
--- a/pkg/analyzer/test/src/dart/ast/utilities_test.dart
+++ b/pkg/analyzer/test/src/dart/ast/utilities_test.dart
@@ -23,7 +23,6 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ConstantEvaluatorTest);
     defineReflectiveTests(NodeLocatorTest);
     defineReflectiveTests(NodeLocator2Test);
     defineReflectiveTests(ResolutionCopierTest);
@@ -34,323 +33,6 @@
 }
 
 @reflectiveTest
-class ConstantEvaluatorTest extends ParserTestCase {
-  void fail_constructor() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_class() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_function() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_static() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_staticMethod() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_topLevel() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void fail_identifier_typeParameter() {
-    Object value = _getConstantValue("?");
-    expect(value, null);
-  }
-
-  void test_binary_bitAnd() {
-    int value = _getConstantValue("74 & 42");
-    expect(value, 74 & 42);
-  }
-
-  void test_binary_bitOr() {
-    int value = _getConstantValue("74 | 42");
-    expect(value, 74 | 42);
-  }
-
-  void test_binary_bitXor() {
-    int value = _getConstantValue("74 ^ 42");
-    expect(value, 74 ^ 42);
-  }
-
-  void test_binary_divide_double() {
-    Object value = _getConstantValue("3.2 / 2.3");
-    expect(value, 3.2 / 2.3);
-  }
-
-  void test_binary_divide_integer() {
-    Object value = _getConstantValue("3 / 2");
-    expect(value, 1.5);
-  }
-
-  void test_binary_equal_boolean() {
-    Object value = _getConstantValue("true == false");
-    expect(value, false);
-  }
-
-  void test_binary_equal_integer() {
-    Object value = _getConstantValue("2 == 3");
-    expect(value, false);
-  }
-
-  void test_binary_equal_invalidLeft() {
-    Object value = _getConstantValue("a == 3");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_equal_invalidRight() {
-    Object value = _getConstantValue("2 == a");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_equal_string() {
-    Object value = _getConstantValue("'a' == 'b'");
-    expect(value, false);
-  }
-
-  void test_binary_greaterThan() {
-    Object value = _getConstantValue("2 > 3");
-    expect(value, false);
-  }
-
-  void test_binary_greaterThanOrEqual() {
-    Object value = _getConstantValue("2 >= 3");
-    expect(value, false);
-  }
-
-  void test_binary_leftShift() {
-    int value = _getConstantValue("16 << 2");
-    expect(value, 64);
-  }
-
-  void test_binary_lessThan() {
-    Object value = _getConstantValue("2 < 3");
-    expect(value, true);
-  }
-
-  void test_binary_lessThanOrEqual() {
-    Object value = _getConstantValue("2 <= 3");
-    expect(value, true);
-  }
-
-  void test_binary_logicalAnd() {
-    Object value = _getConstantValue("true && false");
-    expect(value, false);
-  }
-
-  void test_binary_logicalOr() {
-    Object value = _getConstantValue("true || false");
-    expect(value, true);
-  }
-
-  void test_binary_minus_double() {
-    Object value = _getConstantValue("3.2 - 2.3");
-    expect(value, 3.2 - 2.3);
-  }
-
-  void test_binary_minus_integer() {
-    Object value = _getConstantValue("3 - 2");
-    expect(value, 1);
-  }
-
-  void test_binary_notEqual_boolean() {
-    Object value = _getConstantValue("true != false");
-    expect(value, true);
-  }
-
-  void test_binary_notEqual_integer() {
-    Object value = _getConstantValue("2 != 3");
-    expect(value, true);
-  }
-
-  void test_binary_notEqual_invalidLeft() {
-    Object value = _getConstantValue("a != 3");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_notEqual_invalidRight() {
-    Object value = _getConstantValue("2 != a");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_notEqual_string() {
-    Object value = _getConstantValue("'a' != 'b'");
-    expect(value, true);
-  }
-
-  void test_binary_plus_double() {
-    Object value = _getConstantValue("2.3 + 3.2");
-    expect(value, 2.3 + 3.2);
-  }
-
-  void test_binary_plus_double_string() {
-    Object value = _getConstantValue("'world' + 5.5");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_plus_int_string() {
-    Object value = _getConstantValue("'world' + 5");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_plus_integer() {
-    Object value = _getConstantValue("2 + 3");
-    expect(value, 5);
-  }
-
-  void test_binary_plus_string() {
-    Object value = _getConstantValue("'hello ' + 'world'");
-    expect(value, 'hello world');
-  }
-
-  void test_binary_plus_string_double() {
-    Object value = _getConstantValue("5.5 + 'world'");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_plus_string_int() {
-    Object value = _getConstantValue("5 + 'world'");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_binary_remainder_double() {
-    Object value = _getConstantValue("3.2 % 2.3");
-    expect(value, 3.2 % 2.3);
-  }
-
-  void test_binary_remainder_integer() {
-    Object value = _getConstantValue("8 % 3");
-    expect(value, 2);
-  }
-
-  void test_binary_rightShift() {
-    int value = _getConstantValue("64 >> 2");
-    expect(value, 16);
-  }
-
-  void test_binary_times_double() {
-    Object value = _getConstantValue("2.3 * 3.2");
-    expect(value, 2.3 * 3.2);
-  }
-
-  void test_binary_times_integer() {
-    Object value = _getConstantValue("2 * 3");
-    expect(value, 6);
-  }
-
-  void test_binary_truncatingDivide_double() {
-    int value = _getConstantValue("3.2 ~/ 2.3");
-    expect(value, 1);
-  }
-
-  void test_binary_truncatingDivide_integer() {
-    int value = _getConstantValue("10 ~/ 3");
-    expect(value, 3);
-  }
-
-  void test_literal_boolean_false() {
-    Object value = _getConstantValue("false");
-    expect(value, false);
-  }
-
-  void test_literal_boolean_true() {
-    Object value = _getConstantValue("true");
-    expect(value, true);
-  }
-
-  void test_literal_list() {
-    List value = _getConstantValue("['a', 'b', 'c']");
-    expect(value.length, 3);
-    expect(value[0], "a");
-    expect(value[1], "b");
-    expect(value[2], "c");
-  }
-
-  void test_literal_map() {
-    Map value = _getConstantValue("{'a' : 'm', 'b' : 'n', 'c' : 'o'}");
-    expect(value.length, 3);
-    expect(value["a"], "m");
-    expect(value["b"], "n");
-    expect(value["c"], "o");
-  }
-
-  void test_literal_null() {
-    Object value = _getConstantValue("null");
-    expect(value, null);
-  }
-
-  void test_literal_number_double() {
-    Object value = _getConstantValue("3.45");
-    expect(value, 3.45);
-  }
-
-  void test_literal_number_integer() {
-    Object value = _getConstantValue("42");
-    expect(value, 42);
-  }
-
-  void test_literal_string_adjacent() {
-    Object value = _getConstantValue("'abc' 'def'");
-    expect(value, "abcdef");
-  }
-
-  void test_literal_string_interpolation_invalid() {
-    Object value = _getConstantValue("'a\${f()}c'");
-    expect(value, ConstantEvaluator.NOT_A_CONSTANT);
-  }
-
-  void test_literal_string_interpolation_valid() {
-    Object value = _getConstantValue("'a\${3}c'");
-    expect(value, "a3c");
-  }
-
-  void test_literal_string_simple() {
-    Object value = _getConstantValue("'abc'");
-    expect(value, "abc");
-  }
-
-  void test_parenthesizedExpression() {
-    Object value = _getConstantValue("('a')");
-    expect(value, "a");
-  }
-
-  void test_unary_bitNot() {
-    int value = _getConstantValue("~42");
-    expect(value, ~42);
-  }
-
-  void test_unary_logicalNot() {
-    Object value = _getConstantValue("!true");
-    expect(value, false);
-  }
-
-  void test_unary_negated_double() {
-    Object value = _getConstantValue("-42.3");
-    expect(value, -42.3);
-  }
-
-  void test_unary_negated_integer() {
-    Object value = _getConstantValue("-42");
-    expect(value, -42);
-  }
-
-  Object _getConstantValue(String source) =>
-      parseExpression(source).accept(new ConstantEvaluator());
-}
-
-@reflectiveTest
 class NodeLocator2Test extends ParserTestCase {
   void test_onlyStartOffset() {
     String code = ' int vv; ';
@@ -543,45 +225,6 @@
     expect(toNode.staticType, same(staticType));
   }
 
-  void test_visitCollectionForElement() {
-    CollectionForElement createNode() => astFactory.collectionForElement(
-        forLoopParts: astFactory.forEachPartsWithIdentifier(
-            identifier: AstTestFactory.identifier3('a'),
-            iterable: AstTestFactory.identifier3('b')),
-        body: AstTestFactory.identifier3('c'));
-
-    DartType typeC = ElementFactory.classElement2("C").type;
-
-    CollectionForElement fromNode = createNode();
-    (fromNode.body as SimpleIdentifier).staticType = typeC;
-
-    CollectionForElement toNode = createNode();
-    ResolutionCopier.copyResolutionData(fromNode, toNode);
-    expect((toNode.body as SimpleIdentifier).staticType, same(typeC));
-  }
-
-  void test_visitCollectionIfElement() {
-    CollectionIfElement createNode() => astFactory.collectionIfElement(
-        condition: AstTestFactory.identifier3('a'),
-        thenElement: AstTestFactory.identifier3('b'),
-        elseElement: AstTestFactory.identifier3('c'));
-
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
-
-    CollectionIfElement fromNode = createNode();
-    (fromNode.condition as SimpleIdentifier).staticType = typeA;
-    (fromNode.thenElement as SimpleIdentifier).staticType = typeB;
-    (fromNode.elseElement as SimpleIdentifier).staticType = typeC;
-
-    CollectionIfElement toNode = createNode();
-    ResolutionCopier.copyResolutionData(fromNode, toNode);
-    expect(toNode.condition.staticType, same(typeA));
-    expect((toNode.thenElement as SimpleIdentifier).staticType, same(typeB));
-    expect((toNode.elseElement as SimpleIdentifier).staticType, same(typeC));
-  }
-
   void test_visitCompilationUnit() {
     CompilationUnit fromNode = AstTestFactory.compilationUnit();
     CompilationUnitElement element = new CompilationUnitElementImpl();
@@ -691,6 +334,23 @@
     expect((toNode.iterable as SimpleIdentifier).staticType, same(typeB));
   }
 
+  void test_visitForElement() {
+    ForElement createNode() => astFactory.forElement(
+        forLoopParts: astFactory.forEachPartsWithIdentifier(
+            identifier: AstTestFactory.identifier3('a'),
+            iterable: AstTestFactory.identifier3('b')),
+        body: AstTestFactory.identifier3('c'));
+
+    DartType typeC = ElementFactory.classElement2("C").type;
+
+    ForElement fromNode = createNode();
+    (fromNode.body as SimpleIdentifier).staticType = typeC;
+
+    ForElement toNode = createNode();
+    ResolutionCopier.copyResolutionData(fromNode, toNode);
+    expect((toNode.body as SimpleIdentifier).staticType, same(typeC));
+  }
+
   void test_visitForPartsWithDeclarations() {
     ForPartsWithDeclarations createNode() =>
         astFactory.forPartsWithDeclarations(
@@ -803,6 +463,28 @@
     expect(toNode.staticElement, same(staticElement));
   }
 
+  void test_visitIfElement() {
+    IfElement createNode() => astFactory.ifElement(
+        condition: AstTestFactory.identifier3('a'),
+        thenElement: AstTestFactory.identifier3('b'),
+        elseElement: AstTestFactory.identifier3('c'));
+
+    DartType typeA = ElementFactory.classElement2("A").type;
+    DartType typeB = ElementFactory.classElement2("B").type;
+    DartType typeC = ElementFactory.classElement2("C").type;
+
+    IfElement fromNode = createNode();
+    (fromNode.condition as SimpleIdentifier).staticType = typeA;
+    (fromNode.thenElement as SimpleIdentifier).staticType = typeB;
+    (fromNode.elseElement as SimpleIdentifier).staticType = typeC;
+
+    IfElement toNode = createNode();
+    ResolutionCopier.copyResolutionData(fromNode, toNode);
+    expect(toNode.condition.staticType, same(typeA));
+    expect((toNode.thenElement as SimpleIdentifier).staticType, same(typeB));
+    expect((toNode.elseElement as SimpleIdentifier).staticType, same(typeC));
+  }
+
   void test_visitImportDirective() {
     ImportDirective fromNode =
         AstTestFactory.importDirective3("dart:uri", null);
@@ -908,55 +590,6 @@
     expect((toNode.elements[0] as SimpleIdentifier).staticType, same(typeB));
   }
 
-  void test_visitMapForElement() {
-    MapForElement createNode() => astFactory.mapForElement(
-        forLoopParts: astFactory.forEachPartsWithIdentifier(
-            identifier: AstTestFactory.identifier3('a'),
-            iterable: AstTestFactory.identifier3('b')),
-        body: AstTestFactory.mapLiteralEntry3('c', 'd'));
-
-    DartType typeC = ElementFactory.classElement2("C").type;
-
-    MapForElement fromNode = createNode();
-    (fromNode.body as MapLiteralEntry).key.staticType = typeC;
-
-    MapForElement toNode = createNode();
-    ResolutionCopier.copyResolutionData(fromNode, toNode);
-    expect((toNode.body as MapLiteralEntry).key.staticType, same(typeC));
-  }
-
-  void test_visitMapIfElement() {
-    MapIfElement createNode() => astFactory.mapIfElement(
-        condition: AstTestFactory.identifier3('a'),
-        thenElement: AstTestFactory.mapLiteralEntry3('b', 'c'),
-        elseElement: AstTestFactory.mapLiteralEntry3('d', 'e'));
-
-    DartType typeA = ElementFactory.classElement2("A").type;
-    DartType typeB = ElementFactory.classElement2("B").type;
-    DartType typeC = ElementFactory.classElement2("C").type;
-    DartType typeD = ElementFactory.classElement2("D").type;
-    DartType typeE = ElementFactory.classElement2("E").type;
-
-    MapIfElement fromNode = createNode();
-    MapLiteralEntry fromThen = fromNode.thenElement as MapLiteralEntry;
-    MapLiteralEntry fromElse = fromNode.elseElement as MapLiteralEntry;
-    (fromNode.condition as SimpleIdentifier).staticType = typeA;
-    (fromThen.key as SimpleStringLiteral).staticType = typeB;
-    (fromThen.value as SimpleStringLiteral).staticType = typeC;
-    (fromElse.key as SimpleStringLiteral).staticType = typeD;
-    (fromElse.value as SimpleStringLiteral).staticType = typeE;
-
-    MapIfElement toNode = createNode();
-    ResolutionCopier.copyResolutionData(fromNode, toNode);
-    MapLiteralEntry toThen = toNode.thenElement as MapLiteralEntry;
-    MapLiteralEntry toElse = toNode.elseElement as MapLiteralEntry;
-    expect(toNode.condition.staticType, same(typeA));
-    expect((toThen.key as SimpleStringLiteral).staticType, same(typeB));
-    expect((toThen.value as SimpleStringLiteral).staticType, same(typeC));
-    expect((toElse.key as SimpleStringLiteral).staticType, same(typeD));
-    expect((toElse.value as SimpleStringLiteral).staticType, same(typeE));
-  }
-
   void test_visitMapLiteral() {
     MapLiteral fromNode = AstTestFactory.mapLiteral2();
     DartType staticType = ElementFactory.classElement2("C").type;
@@ -1732,33 +1365,6 @@
     _assertSource("@deprecated class C = S with M1;", declaration);
   }
 
-  void test_visitCollectionForElement() {
-    _assertSource(
-        'for (e in l) 0',
-        astFactory.collectionForElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.integer(0)));
-  }
-
-  void test_visitCollectionIfElement_else() {
-    _assertSource(
-        'if (b) 1 else 0',
-        astFactory.collectionIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1),
-            elseElement: AstTestFactory.integer(0)));
-  }
-
-  void test_visitCollectionIfElement_then() {
-    _assertSource(
-        'if (b) 1',
-        astFactory.collectionIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1)));
-  }
-
   void test_visitComment() {
     _assertSource(
         "",
@@ -2242,6 +1848,16 @@
             AstTestFactory.block()));
   }
 
+  void test_visitForElement() {
+    _assertSource(
+        'for (e in l) 0',
+        astFactory.forElement(
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3('e'),
+                iterable: AstTestFactory.identifier3('l')),
+            body: AstTestFactory.integer(0)));
+  }
+
   void test_visitFormalParameterList_empty() {
     _assertSource("()", AstTestFactory.formalParameterList());
   }
@@ -2778,6 +2394,23 @@
                 ]))));
   }
 
+  void test_visitIfElement_else() {
+    _assertSource(
+        'if (b) 1 else 0',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1),
+            elseElement: AstTestFactory.integer(0)));
+  }
+
+  void test_visitIfElement_then() {
+    _assertSource(
+        'if (b) 1',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1)));
+  }
+
   void test_visitIfStatement_withElse() {
     _assertSource(
         "if (c) {} else {}",
@@ -3002,12 +2635,12 @@
                 [AstTestFactory.typeName4('int')]),
             elements: [
               AstTestFactory.integer(0),
-              astFactory.collectionForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('e'),
                       iterable: AstTestFactory.identifier3('l')),
                   body: AstTestFactory.integer(0)),
-              astFactory.collectionIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('b'),
                   thenElement: AstTestFactory.integer(1)),
               astFactory.spreadElement(
@@ -3068,33 +2701,6 @@
         ]));
   }
 
-  void test_visitMapForElement() {
-    _assertSource(
-        "for (e in l) 'a' : 'b'",
-        astFactory.mapForElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.mapLiteralEntry3('a', 'b')));
-  }
-
-  void test_visitMapIfElement_else() {
-    _assertSource(
-        "if (b) 'a' : 'b' else 'c' : 'd'",
-        astFactory.mapIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.mapLiteralEntry3('a', 'b'),
-            elseElement: AstTestFactory.mapLiteralEntry3('c', 'd')));
-  }
-
-  void test_visitMapIfElement_then() {
-    _assertSource(
-        "if (b) 'a' : 'b'",
-        astFactory.mapIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.mapLiteralEntry3('a', 'b')));
-  }
-
   void test_visitMapLiteral2_complex() {
     _assertSource(
         "<String, String>{'a' : 'b', for (c in d) 'e' : 'f', if (g) 'h' : 'i', ...{'j' : 'k'}}",
@@ -3105,12 +2711,12 @@
             ]),
             entries: [
               AstTestFactory.mapLiteralEntry3('a', 'b'),
-              astFactory.mapForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('c'),
                       iterable: AstTestFactory.identifier3('d')),
                   body: AstTestFactory.mapLiteralEntry3('e', 'f')),
-              astFactory.mapIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('g'),
                   thenElement: AstTestFactory.mapLiteralEntry3('h', 'i')),
               astFactory.spreadElement(
@@ -3545,12 +3151,12 @@
                 [AstTestFactory.typeName4('int')]),
             elements: [
               AstTestFactory.integer(0),
-              astFactory.collectionForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('e'),
                       iterable: AstTestFactory.identifier3('l')),
                   body: AstTestFactory.integer(0)),
-              astFactory.collectionIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('b'),
                   thenElement: AstTestFactory.integer(1)),
               astFactory.spreadElement(
@@ -4439,33 +4045,6 @@
     _assertSource("@deprecated class C = S with M1;", declaration);
   }
 
-  void test_visitCollectionForElement() {
-    _assertSource(
-        'for (e in l) 0',
-        astFactory.collectionForElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.integer(0)));
-  }
-
-  void test_visitCollectionIfElement_else() {
-    _assertSource(
-        'if (b) 1 else 0',
-        astFactory.collectionIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1),
-            elseElement: AstTestFactory.integer(0)));
-  }
-
-  void test_visitCollectionIfElement_then() {
-    _assertSource(
-        'if (b) 1',
-        astFactory.collectionIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.integer(1)));
-  }
-
   void test_visitComment() {
     _assertSource(
         "",
@@ -4949,6 +4528,16 @@
             AstTestFactory.block()));
   }
 
+  void test_visitForElement() {
+    _assertSource(
+        'for (e in l) 0',
+        astFactory.forElement(
+            forLoopParts: astFactory.forEachPartsWithIdentifier(
+                identifier: AstTestFactory.identifier3('e'),
+                iterable: AstTestFactory.identifier3('l')),
+            body: AstTestFactory.integer(0)));
+  }
+
   void test_visitFormalParameterList_empty() {
     _assertSource("()", AstTestFactory.formalParameterList());
   }
@@ -5485,6 +5074,23 @@
                 ]))));
   }
 
+  void test_visitIfElement_else() {
+    _assertSource(
+        'if (b) 1 else 0',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1),
+            elseElement: AstTestFactory.integer(0)));
+  }
+
+  void test_visitIfElement_then() {
+    _assertSource(
+        'if (b) 1',
+        astFactory.ifElement(
+            condition: AstTestFactory.identifier3('b'),
+            thenElement: AstTestFactory.integer(1)));
+  }
+
   void test_visitIfStatement_withElse() {
     _assertSource(
         "if (c) {} else {}",
@@ -5709,12 +5315,12 @@
                 [AstTestFactory.typeName4('int')]),
             elements: [
               AstTestFactory.integer(0),
-              astFactory.collectionForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('e'),
                       iterable: AstTestFactory.identifier3('l')),
                   body: AstTestFactory.integer(0)),
-              astFactory.collectionIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('b'),
                   thenElement: AstTestFactory.integer(1)),
               astFactory.spreadElement(
@@ -5775,33 +5381,6 @@
         ]));
   }
 
-  void test_visitMapForElement() {
-    _assertSource(
-        "for (e in l) 'a' : 'b'",
-        astFactory.mapForElement(
-            forLoopParts: astFactory.forEachPartsWithIdentifier(
-                identifier: AstTestFactory.identifier3('e'),
-                iterable: AstTestFactory.identifier3('l')),
-            body: AstTestFactory.mapLiteralEntry3('a', 'b')));
-  }
-
-  void test_visitMapIfElement_else() {
-    _assertSource(
-        "if (b) 'a' : 'b' else 'c' : 'd'",
-        astFactory.mapIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.mapLiteralEntry3('a', 'b'),
-            elseElement: AstTestFactory.mapLiteralEntry3('c', 'd')));
-  }
-
-  void test_visitMapIfElement_then() {
-    _assertSource(
-        "if (b) 'a' : 'b'",
-        astFactory.mapIfElement(
-            condition: AstTestFactory.identifier3('b'),
-            thenElement: AstTestFactory.mapLiteralEntry3('a', 'b')));
-  }
-
   void test_visitMapLiteral2_complex() {
     _assertSource(
         "<String, String>{'a' : 'b', for (c in d) 'e' : 'f', if (g) 'h' : 'i', ...{'j' : 'k'}}",
@@ -5812,12 +5391,12 @@
             ]),
             entries: [
               AstTestFactory.mapLiteralEntry3('a', 'b'),
-              astFactory.mapForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('c'),
                       iterable: AstTestFactory.identifier3('d')),
                   body: AstTestFactory.mapLiteralEntry3('e', 'f')),
-              astFactory.mapIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('g'),
                   thenElement: AstTestFactory.mapLiteralEntry3('h', 'i')),
               astFactory.spreadElement(
@@ -6243,12 +5822,12 @@
                 [AstTestFactory.typeName4('int')]),
             elements: [
               AstTestFactory.integer(0),
-              astFactory.collectionForElement(
+              astFactory.forElement(
                   forLoopParts: astFactory.forEachPartsWithIdentifier(
                       identifier: AstTestFactory.identifier3('e'),
                       iterable: AstTestFactory.identifier3('l')),
                   body: AstTestFactory.integer(0)),
-              astFactory.collectionIfElement(
+              astFactory.ifElement(
                   condition: AstTestFactory.identifier3('b'),
                   thenElement: AstTestFactory.integer(1)),
               astFactory.spreadElement(
diff --git a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
index ca9e41b..fe9fbf9 100644
--- a/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
+++ b/pkg/analyzer/test/src/dart/constant/evaluation_test.dart
@@ -4,827 +4,193 @@
 
 import 'package:analyzer/dart/analysis/declared_variables.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/error/error.dart';
 import 'package:analyzer/error/listener.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:analyzer/src/error/codes.dart';
 import 'package:analyzer/src/generated/constant.dart';
 import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/resolver.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/generated/source_io.dart';
-import 'package:analyzer/src/generated/testing/ast_test_factory.dart';
-import 'package:analyzer/src/generated/testing/test_type_provider.dart';
-import 'package:path/path.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
-import '../../../generated/resolver_test_case.dart';
 import '../../../generated/test_support.dart';
+import '../resolution/driver_resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(ConstantVisitorTest);
-    defineReflectiveTests(ConstantVisitorTest_Driver);
     defineReflectiveTests(ConstantVisitorWithConstantUpdate2018Test);
     defineReflectiveTests(
         ConstantVisitorWithFlowControlAndSpreadCollectionsTest);
   });
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
 class ConstantVisitorTest extends ConstantVisitorTestSupport {
-  test_visitAsExpression_instanceOfSameClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a as A;
-class A {
-  const A();
-}
-''');
-    DartObjectImpl resultA = _evaluateConstant(compilationUnit, 'a',
-        experiments: [EnableString.constant_update_2018]);
-    DartObjectImpl resultB = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(resultB, resultA);
-  }
-
-  test_visitAsExpression_instanceOfSubclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const B();
-const b = a as A;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl resultA = _evaluateConstant(compilationUnit, 'a',
-        experiments: [EnableString.constant_update_2018]);
-    DartObjectImpl resultB = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(resultB, resultA);
-  }
-
-  test_visitAsExpression_instanceOfSuperclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a as B;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION],
-        experiments: [EnableString.constant_update_2018]);
-    expect(result, isNull);
-  }
-
-  test_visitAsExpression_instanceOfUnrelatedClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a as B;
-class A {
-  const A();
-}
-class B {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION],
-        experiments: [EnableString.constant_update_2018]);
-    expect(result, isNull);
-  }
-
-  test_visitAsExpression_null() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a as A;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.nullType);
-  }
-
-  test_visitBinaryExpression_and_bool_known_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false & true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_and_bool_known_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const b = bool.fromEnvironment('y');
-const c = false & b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_and_bool_unknown_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const c = a & true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_and_bool_unknown_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const b = bool.fromEnvironment('y');
-const c = a & b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_and_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 & 5;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-  }
-
-  test_visitBinaryExpression_and_mixed() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 & false;
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
-  test_visitBinaryExpression_or_bool_known_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false | true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_or_bool_known_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const b = bool.fromEnvironment('y');
-const c = false | b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_or_bool_unknown_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const c = a | true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_or_bool_unknown_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const b = bool.fromEnvironment('y');
-const c = a | b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_or_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 | 5;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-  }
-
-  test_visitBinaryExpression_or_mixed() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 | false;
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
   test_visitBinaryExpression_questionQuestion_eager_notNull_notNull() async {
-    Expression left = AstTestFactory.string2('a');
-    Expression right = AstTestFactory.string2('b');
-    Expression expression = AstTestFactory.binaryExpression(
-        left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isFalse);
+    await _resolveTestCode('''
+const c = 'a' ?? 'b';
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.stringType);
     expect(result.toStringValue(), 'a');
-    errorListener.assertNoErrors();
   }
 
   test_visitBinaryExpression_questionQuestion_eager_null_notNull() async {
-    Expression left = AstTestFactory.nullLiteral();
-    Expression right = AstTestFactory.string2('b');
-    Expression expression = AstTestFactory.binaryExpression(
-        left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isFalse);
+    await _resolveTestCode('''
+const c = null ?? 'b';
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.stringType);
     expect(result.toStringValue(), 'b');
-    errorListener.assertNoErrors();
   }
 
   test_visitBinaryExpression_questionQuestion_eager_null_null() async {
-    Expression left = AstTestFactory.nullLiteral();
-    Expression right = AstTestFactory.nullLiteral();
-    Expression expression = AstTestFactory.binaryExpression(
-        left, TokenType.QUESTION_QUESTION, right);
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
-    expect(result, isNotNull);
-    expect(result.isNull, isTrue);
-    errorListener.assertNoErrors();
-  }
-
-  test_visitBinaryExpression_questionQuestion_lazy_notNull_invalid() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 'a' ?? new C();
-class C {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.stringType);
-    expect(result.toStringValue(), 'a');
-  }
-
-  test_visitBinaryExpression_questionQuestion_lazy_notNull_notNull() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 'a' ?? 'b';
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.stringType);
-    expect(result.toStringValue(), 'a');
-  }
-
-  test_visitBinaryExpression_questionQuestion_lazy_null_invalid() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = null ?? new C();
-class C {}
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
-  test_visitBinaryExpression_questionQuestion_lazy_null_notNull() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = null ?? 'b';
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.stringType);
-    expect(result.toStringValue(), 'b');
-  }
-
-  test_visitBinaryExpression_questionQuestion_lazy_null_null() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = null ?? null;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.isNull, isTrue);
   }
 
-  test_visitBinaryExpression_xor_bool_known_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false ^ true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_xor_bool_known_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const b = bool.fromEnvironment('y');
-const c = false ^ b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_xor_bool_unknown_known() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const c = a ^ true;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_xor_bool_unknown_unknown() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = bool.fromEnvironment('x');
-const b = bool.fromEnvironment('y');
-const c = a ^ b;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-  }
-
-  test_visitBinaryExpression_xor_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 ^ 5;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-  }
-
-  test_visitBinaryExpression_xor_mixed() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 ^ false;
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
   test_visitConditionalExpression_eager_false_int_int() async {
-    Expression thenExpression = AstTestFactory.integer(1);
-    Expression elseExpression = AstTestFactory.integer(0);
-    ConditionalExpression expression = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(false), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(0, _evaluate(expression, errorReporter));
-    errorListener.assertNoErrors();
+    await _resolveTestCode('''
+const c = false ? 1 : 0;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 0);
   }
 
   test_visitConditionalExpression_eager_invalid_int_int() async {
-    Expression thenExpression = AstTestFactory.integer(1);
-    Expression elseExpression = AstTestFactory.integer(0);
-    NullLiteral conditionExpression = AstTestFactory.nullLiteral();
-    ConditionalExpression expression = AstTestFactory.conditionalExpression(
-        conditionExpression, thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
+    await _resolveTestCode('''
+const c = null ? 1 : 0;
+''');
+    DartObjectImpl result = _evaluateConstant(
+      'c',
+      errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL],
+    );
     expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
   }
 
   test_visitConditionalExpression_eager_true_int_int() async {
-    Expression thenExpression = AstTestFactory.integer(1);
-    Expression elseExpression = AstTestFactory.integer(0);
-    ConditionalExpression expression = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    _assertValue(1, _evaluate(expression, errorReporter));
-    errorListener.assertNoErrors();
+    await _resolveTestCode('''
+const c = true ? 1 : 0;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 1);
   }
 
   test_visitConditionalExpression_eager_true_int_invalid() async {
-    Expression thenExpression = AstTestFactory.integer(1);
-    Expression elseExpression = AstTestFactory.identifier3("x");
-    ConditionalExpression expression = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
+    await _resolveTestCode('''
+const c = true ? 1 : x;
+''');
+    DartObjectImpl result = _evaluateConstant(
+      'c',
+      errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
+    );
     expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
   }
 
   test_visitConditionalExpression_eager_true_invalid_int() async {
-    Expression thenExpression = AstTestFactory.identifier3("x");
-    Expression elseExpression = AstTestFactory.integer(0);
-    ConditionalExpression expression = AstTestFactory.conditionalExpression(
-        AstTestFactory.booleanLiteral(true), thenExpression, elseExpression);
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter =
-        new ErrorReporter(errorListener, _dummySource());
-    DartObjectImpl result = _evaluate(expression, errorReporter);
+    await _resolveTestCode('''
+const c = true ? x : 0;
+''');
+    DartObjectImpl result = _evaluateConstant(
+      'c',
+      errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
+    );
     expect(result, isNull);
-    errorListener
-        .assertErrorsWithCodes([CompileTimeErrorCode.INVALID_CONSTANT]);
-  }
-
-  test_visitConditionalExpression_lazy_false_int_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false ? 1 : 0;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-    expect(result.toIntValue(), 0);
-  }
-
-  test_visitConditionalExpression_lazy_false_int_invalid() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false ? 1 : new C();
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
-  test_visitConditionalExpression_lazy_false_invalid_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = false ? new C() : 0;
-class C {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-    expect(result.toIntValue(), 0);
-  }
-
-  test_visitConditionalExpression_lazy_invalid_int_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = 3 ? 1 : 0;
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL],
-        experiments: [EnableString.constant_update_2018]);
-  }
-
-  test_visitConditionalExpression_lazy_true_int_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = true ? 1 : 0;
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-    expect(result.toIntValue(), 1);
-  }
-
-  test_visitConditionalExpression_lazy_true_int_invalid() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = true ? 1 : new C();
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.intType);
-    expect(result.toIntValue(), 1);
-  }
-
-  test_visitConditionalExpression_lazy_true_invalid_int() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const c = true ? new C() : 0;
-class C {}
-''');
-    _evaluateConstant(compilationUnit, 'c',
-        errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT],
-        experiments: [EnableString.constant_update_2018]);
   }
 
   test_visitIntegerLiteral() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const double d = 3;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'd');
+    DartObjectImpl result = _evaluateConstant('d');
     expect(result.type, typeProvider.doubleType);
     expect(result.toDoubleValue(), 3.0);
   }
 
-  test_visitIsExpression_is_instanceOfSameClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is A;
-class A {
-  const A();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_is_instanceOfSubclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const B();
-const b = a is A;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_is_instanceOfSuperclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is B;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), false);
-  }
-
-  test_visitIsExpression_is_instanceOfUnrelatedClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is B;
-class A {
-  const A();
-}
-class B {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), false);
-  }
-
-  test_visitIsExpression_is_null() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a is A;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), false);
-  }
-
-  test_visitIsExpression_is_null_dynamic() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a is dynamic;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_is_null_null() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a is Null;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_is_null_object() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a is Object;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_isNot_instanceOfSameClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is! A;
-class A {
-  const A();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), false);
-  }
-
-  test_visitIsExpression_isNot_instanceOfSubclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const B();
-const b = a is! A;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), false);
-  }
-
-  test_visitIsExpression_isNot_instanceOfSuperclass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is! B;
-class A {
-  const A();
-}
-class B extends A {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_isNot_instanceOfUnrelatedClass() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = const A();
-const b = a is! B;
-class A {
-  const A();
-}
-class B {
-  const B();
-}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
-  test_visitIsExpression_isNot_null() async {
-    CompilationUnit compilationUnit = await resolveSource('''
-const a = null;
-const b = a is! A;
-class A {}
-''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'b',
-        experiments: [EnableString.constant_update_2018]);
-    expect(result.type, typeProvider.boolType);
-    expect(result.toBoolValue(), true);
-  }
-
   test_visitSimpleIdentifier_className() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const a = C;
 class C {}
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a');
+    DartObjectImpl result = _evaluateConstant('a');
     expect(result.type, typeProvider.typeType);
     expect(result.toTypeValue().name, 'C');
   }
 
   test_visitSimpleIdentifier_dynamic() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const a = dynamic;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'a');
+    DartObjectImpl result = _evaluateConstant('a');
     expect(result.type, typeProvider.typeType);
     expect(result.toTypeValue(), typeProvider.dynamicType);
   }
 
   test_visitSimpleIdentifier_inEnvironment() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
+    await _resolveTestCode(r'''
 const a = b;
 const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["b"] = six;
-    _assertValue(
-        6,
-        _evaluateConstant(compilationUnit, "a",
-            lexicalEnvironment: environment));
+    var environment = <String, DartObjectImpl>{
+      'b': DartObjectImpl(typeProvider.intType, IntState(6)),
+    };
+    var result = _evaluateConstant('a', lexicalEnvironment: environment);
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 6);
   }
 
   test_visitSimpleIdentifier_notInEnvironment() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
+    await _resolveTestCode(r'''
 const a = b;
 const b = 3;''');
-    Map<String, DartObjectImpl> environment = new Map<String, DartObjectImpl>();
-    DartObjectImpl six =
-        new DartObjectImpl(typeProvider.intType, new IntState(6));
-    environment["c"] = six;
-    _assertValue(
-        3,
-        _evaluateConstant(compilationUnit, "a",
-            lexicalEnvironment: environment));
+    var environment = <String, DartObjectImpl>{
+      'c': DartObjectImpl(typeProvider.intType, IntState(6)),
+    };
+    var result = _evaluateConstant('a', lexicalEnvironment: environment);
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 3);
   }
 
   test_visitSimpleIdentifier_withoutEnvironment() async {
-    CompilationUnit compilationUnit = await resolveSource(r'''
+    await _resolveTestCode(r'''
 const a = b;
 const b = 3;''');
-    _assertValue(3, _evaluateConstant(compilationUnit, "a"));
-  }
-
-  void _assertValue(int expectedValue, DartObjectImpl result) {
-    expect(result, isNotNull);
-    expect(result.type.name, "int");
-    expect(result.toIntValue(), expectedValue);
-  }
-
-  NonExistingSource _dummySource() {
-    String path = '/test.dart';
-    return new NonExistingSource(path, toUri(path), UriKind.FILE_URI);
-  }
-
-  DartObjectImpl _evaluate(Expression expression, ErrorReporter errorReporter) {
-    TestTypeProvider typeProvider = new TestTypeProvider();
-    return expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
-            typeSystem: new Dart2TypeSystem(typeProvider)),
-        errorReporter));
+    var result = _evaluateConstant('a');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 3);
   }
 }
 
-@reflectiveTest
-class ConstantVisitorTest_Driver extends ConstantVisitorTest {
-  bool get enableNewAnalysisDriver => true;
-}
+class ConstantVisitorTestSupport extends DriverResolutionTest {
+  DartObjectImpl _evaluateConstant(
+    String name, {
+    List<ErrorCode> errorCodes,
+    Map<String, DartObjectImpl> lexicalEnvironment,
+  }) {
+    var options = driver.analysisOptions as AnalysisOptionsImpl;
+    var expression = findNode.topVariableDeclarationByName(name).initializer;
 
-class ConstantVisitorTestSupport extends ResolverTestCase {
-  @override
-  List<String> get enabledExperiments => [];
+    var source = this.result.unit.declaredElement.source;
+    var errorListener = GatheringErrorListener();
+    var errorReporter = ErrorReporter(errorListener, source);
 
-  DartObjectImpl _evaluateConstant(CompilationUnit compilationUnit, String name,
-      {List<ErrorCode> errorCodes,
-      List<String> experiments,
-      Map<String, DartObjectImpl> lexicalEnvironment}) {
-    Source source =
-        resolutionMap.elementDeclaredByCompilationUnit(compilationUnit).source;
-    Expression expression =
-        findTopLevelConstantExpression(compilationUnit, name);
-
-    AnalysisOptionsImpl options = new AnalysisOptionsImpl();
-    options.enabledExperiments = experiments ?? enabledExperiments;
-
-    GatheringErrorListener errorListener = new GatheringErrorListener();
-    ErrorReporter errorReporter = new ErrorReporter(errorListener, source);
-
-    DartObjectImpl result = expression.accept(new ConstantVisitor(
-        new ConstantEvaluationEngine(typeProvider, new DeclaredVariables(),
-            experimentStatus: options.experimentStatus, typeSystem: typeSystem),
+    DartObjectImpl result = expression.accept(
+      ConstantVisitor(
+        ConstantEvaluationEngine(
+          typeProvider,
+          new DeclaredVariables(),
+          experimentStatus: options.experimentStatus,
+          typeSystem: this.result.typeSystem,
+        ),
         errorReporter,
-        lexicalEnvironment: lexicalEnvironment));
+        lexicalEnvironment: lexicalEnvironment,
+      ),
+    );
     if (errorCodes == null) {
       errorListener.assertNoErrors();
     } else {
@@ -832,104 +198,616 @@
     }
     return result;
   }
+
+  Future<CompilationUnit> _resolveTestCode(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+    return result.unit;
+  }
 }
 
 @reflectiveTest
 class ConstantVisitorWithConstantUpdate2018Test
     extends ConstantVisitorTestSupport {
   @override
-  List<String> get enabledExperiments => [EnableString.constant_update_2018];
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [EnableString.constant_update_2018];
 
-  bool get enableNewAnalysisDriver => true;
+  test_visitAsExpression_instanceOfSameClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a as A;
+class A {
+  const A();
+}
+''');
+    DartObjectImpl resultA = _evaluateConstant('a');
+    DartObjectImpl resultB = _evaluateConstant('b');
+    expect(resultB, resultA);
+  }
+
+  test_visitAsExpression_instanceOfSubclass() async {
+    await _resolveTestCode('''
+const a = const B();
+const b = a as A;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl resultA = _evaluateConstant('a');
+    DartObjectImpl resultB = _evaluateConstant('b');
+    expect(resultB, resultA);
+  }
+
+  test_visitAsExpression_instanceOfSuperclass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a as B;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+    expect(result, isNull);
+  }
+
+  test_visitAsExpression_instanceOfUnrelatedClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a as B;
+class A {
+  const A();
+}
+class B {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
+    expect(result, isNull);
+  }
+
+  test_visitAsExpression_null() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a as A;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.nullType);
+  }
+
+  test_visitBinaryExpression_and_bool_known_known() async {
+    await _resolveTestCode('''
+const c = false & true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_and_bool_known_unknown() async {
+    await _resolveTestCode('''
+const b = bool.fromEnvironment('y');
+const c = false & b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_and_bool_unknown_known() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const c = a & true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_and_bool_unknown_unknown() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const b = bool.fromEnvironment('y');
+const c = a & b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_and_int() async {
+    await _resolveTestCode('''
+const c = 3 & 5;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+  }
+
+  test_visitBinaryExpression_and_mixed() async {
+    await _resolveTestCode('''
+const c = 3 & false;
+''');
+    _evaluateConstant('c',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
+  }
 
   test_visitBinaryExpression_gtGtGt_negative_fewerBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFFFFFFFF >>> 8;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0xFFFFFF);
   }
 
   test_visitBinaryExpression_gtGtGt_negative_moreBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFFFFFFFF >>> 33;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0);
   }
 
   test_visitBinaryExpression_gtGtGt_negative_negativeBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFFFFFFFF >>> -2;
 ''');
-    _evaluateConstant(compilationUnit, 'c',
+    _evaluateConstant('c',
         errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
   }
 
   test_visitBinaryExpression_gtGtGt_negative_zeroBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFFFFFFFF >>> 0;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0xFFFFFFFF);
   }
 
   test_visitBinaryExpression_gtGtGt_positive_fewerBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFF >>> 3;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0x1F);
   }
 
   test_visitBinaryExpression_gtGtGt_positive_moreBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFF >>> 9;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0);
   }
 
   test_visitBinaryExpression_gtGtGt_positive_negativeBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFF >>> -2;
 ''');
-    _evaluateConstant(compilationUnit, 'c',
+    _evaluateConstant('c',
         errorCodes: [CompileTimeErrorCode.CONST_EVAL_THROWS_EXCEPTION]);
   }
 
   test_visitBinaryExpression_gtGtGt_positive_zeroBits() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = 0xFF >>> 0;
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(result.type, typeProvider.intType);
     expect(result.toIntValue(), 0xFF);
   }
+
+  test_visitBinaryExpression_or_bool_known_known() async {
+    await _resolveTestCode('''
+const c = false | true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_or_bool_known_unknown() async {
+    await _resolveTestCode('''
+const b = bool.fromEnvironment('y');
+const c = false | b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_or_bool_unknown_known() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const c = a | true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_or_bool_unknown_unknown() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const b = bool.fromEnvironment('y');
+const c = a | b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_or_int() async {
+    await _resolveTestCode('''
+const c = 3 | 5;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+  }
+
+  test_visitBinaryExpression_or_mixed() async {
+    await _resolveTestCode('''
+const c = 3 | false;
+''');
+    _evaluateConstant('c',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
+  }
+
+  test_visitBinaryExpression_questionQuestion_lazy_notNull_invalid() async {
+    await _resolveTestCode('''
+const c = 'a' ?? new C();
+class C {}
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.stringType);
+    expect(result.toStringValue(), 'a');
+  }
+
+  test_visitBinaryExpression_questionQuestion_lazy_notNull_notNull() async {
+    await _resolveTestCode('''
+const c = 'a' ?? 'b';
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.stringType);
+    expect(result.toStringValue(), 'a');
+  }
+
+  test_visitBinaryExpression_questionQuestion_lazy_null_invalid() async {
+    await _resolveTestCode('''
+const c = null ?? new C();
+class C {}
+''');
+    _evaluateConstant('c', errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  test_visitBinaryExpression_questionQuestion_lazy_null_notNull() async {
+    await _resolveTestCode('''
+const c = null ?? 'b';
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.stringType);
+    expect(result.toStringValue(), 'b');
+  }
+
+  test_visitBinaryExpression_questionQuestion_lazy_null_null() async {
+    await _resolveTestCode('''
+const c = null ?? null;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.isNull, isTrue);
+  }
+
+  test_visitBinaryExpression_xor_bool_known_known() async {
+    await _resolveTestCode('''
+const c = false ^ true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_xor_bool_known_unknown() async {
+    await _resolveTestCode('''
+const b = bool.fromEnvironment('y');
+const c = false ^ b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_xor_bool_unknown_known() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const c = a ^ true;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_xor_bool_unknown_unknown() async {
+    await _resolveTestCode('''
+const a = bool.fromEnvironment('x');
+const b = bool.fromEnvironment('y');
+const c = a ^ b;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.boolType);
+  }
+
+  test_visitBinaryExpression_xor_int() async {
+    await _resolveTestCode('''
+const c = 3 ^ 5;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+  }
+
+  test_visitBinaryExpression_xor_mixed() async {
+    await _resolveTestCode('''
+const c = 3 ^ false;
+''');
+    _evaluateConstant('c',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL_INT]);
+  }
+
+  test_visitConditionalExpression_lazy_false_int_int() async {
+    await _resolveTestCode('''
+const c = false ? 1 : 0;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 0);
+  }
+
+  test_visitConditionalExpression_lazy_false_int_invalid() async {
+    await _resolveTestCode('''
+const c = false ? 1 : new C();
+''');
+    _evaluateConstant('c', errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  test_visitConditionalExpression_lazy_false_invalid_int() async {
+    await _resolveTestCode('''
+const c = false ? new C() : 0;
+class C {}
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 0);
+  }
+
+  test_visitConditionalExpression_lazy_invalid_int_int() async {
+    await _resolveTestCode('''
+const c = 3 ? 1 : 0;
+''');
+    _evaluateConstant('c',
+        errorCodes: [CompileTimeErrorCode.CONST_EVAL_TYPE_BOOL]);
+  }
+
+  test_visitConditionalExpression_lazy_true_int_int() async {
+    await _resolveTestCode('''
+const c = true ? 1 : 0;
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 1);
+  }
+
+  test_visitConditionalExpression_lazy_true_int_invalid() async {
+    await _resolveTestCode('''
+const c = true ? 1 : new C();
+''');
+    DartObjectImpl result = _evaluateConstant('c');
+    expect(result.type, typeProvider.intType);
+    expect(result.toIntValue(), 1);
+  }
+
+  test_visitConditionalExpression_lazy_true_invalid_int() async {
+    await _resolveTestCode('''
+const c = true ? new C() : 0;
+class C {}
+''');
+    _evaluateConstant('c', errorCodes: [CompileTimeErrorCode.INVALID_CONSTANT]);
+  }
+
+  test_visitIsExpression_is_instanceOfSameClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is A;
+class A {
+  const A();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_is_instanceOfSubclass() async {
+    await _resolveTestCode('''
+const a = const B();
+const b = a is A;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_is_instanceOfSuperclass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is B;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), false);
+  }
+
+  test_visitIsExpression_is_instanceOfUnrelatedClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is B;
+class A {
+  const A();
+}
+class B {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), false);
+  }
+
+  test_visitIsExpression_is_null() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a is A;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), false);
+  }
+
+  test_visitIsExpression_is_null_dynamic() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a is dynamic;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_is_null_null() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a is Null;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_is_null_object() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a is Object;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_isNot_instanceOfSameClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is! A;
+class A {
+  const A();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), false);
+  }
+
+  test_visitIsExpression_isNot_instanceOfSubclass() async {
+    await _resolveTestCode('''
+const a = const B();
+const b = a is! A;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), false);
+  }
+
+  test_visitIsExpression_isNot_instanceOfSuperclass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is! B;
+class A {
+  const A();
+}
+class B extends A {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_isNot_instanceOfUnrelatedClass() async {
+    await _resolveTestCode('''
+const a = const A();
+const b = a is! B;
+class A {
+  const A();
+}
+class B {
+  const B();
+}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
+
+  test_visitIsExpression_isNot_null() async {
+    await _resolveTestCode('''
+const a = null;
+const b = a is! A;
+class A {}
+''');
+    DartObjectImpl result = _evaluateConstant('b');
+    expect(result.type, typeProvider.boolType);
+    expect(result.toBoolValue(), true);
+  }
 }
 
 @reflectiveTest
 class ConstantVisitorWithFlowControlAndSpreadCollectionsTest
     extends ConstantVisitorTestSupport {
   @override
-  List<String> get enabledExperiments => [
-        EnableString.control_flow_collections,
-        EnableString.set_literals,
-        EnableString.spread_collections
-      ];
-
-  bool get enableNewAnalysisDriver => true;
+  AnalysisOptionsImpl get analysisOptions => AnalysisOptionsImpl()
+    ..enabledExperiments = [
+      EnableString.control_flow_collections,
+      EnableString.set_literals,
+      EnableString.spread_collections
+    ];
 
   test_listLiteral_nested() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, if (1 > 0) if (2 > 1) 2, 3];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     // The expected type ought to be `List<int>`, but type inference isn't yet
     // implemented.
     expect(
@@ -938,50 +816,50 @@
   }
 
   test_listLiteral_withIf_false_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, if (1 < 0) 2 else 3, 4];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.listType.instantiate([typeProvider.intType]));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 3, 4]);
   }
 
   test_listLiteral_withIf_false_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, if (1 < 0) 2, 3];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.listType.instantiate([typeProvider.intType]));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 3]);
   }
 
   test_listLiteral_withIf_true_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, if (1 > 0) 2 else 3, 4];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.listType.instantiate([typeProvider.intType]));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 4]);
   }
 
   test_listLiteral_withIf_true_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, if (1 > 0) 2, 3];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.listType.instantiate([typeProvider.intType]));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
   test_listLiteral_withSpread() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = [1, ...[2, 3], 4];
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.listType.instantiate([typeProvider.intType]));
     expect(result.toListValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
@@ -990,10 +868,10 @@
   @failingTest
   test_mapLiteral_nested() async {
     // Fails because we're not yet parsing nested elements.
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) if (2 > 1) {'b' : 2}, 'c' : 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1005,10 +883,10 @@
   }
 
   test_mapLiteral_withIf_false_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, if (1 < 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1020,10 +898,10 @@
   }
 
   test_mapLiteral_withIf_false_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, if (1 < 0) 'b' : 2, 'c' : 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1035,10 +913,10 @@
   }
 
   test_mapLiteral_withIf_true_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) 'b' : 2 else 'c' : 3, 'd' : 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1050,10 +928,10 @@
   }
 
   test_mapLiteral_withIf_true_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, if (1 > 0) 'b' : 2, 'c' : 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1065,10 +943,10 @@
   }
 
   test_mapLiteral_withSpread() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {'a' : 1, ...{'b' : 2, 'c' : 3}, 'd' : 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type,
         typeProvider.mapType
@@ -1081,60 +959,60 @@
   }
 
   test_setLiteral_nested() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, if (1 > 0) if (2 > 1) 2, 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
   test_setLiteral_withIf_false_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, if (1 < 0) 2 else 3, 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3, 4]);
   }
 
   test_setLiteral_withIf_false_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, if (1 < 0) 2, 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 3]);
   }
 
   test_setLiteral_withIf_true_withElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, if (1 > 0) 2 else 3, 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 4]);
   }
 
   test_setLiteral_withIf_true_withoutElse() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, if (1 > 0) 2, 3};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3]);
   }
 
   test_setLiteral_withSpread() async {
-    CompilationUnit compilationUnit = await resolveSource('''
+    await _resolveTestCode('''
 const c = {1, ...{2, 3}, 4};
 ''');
-    DartObjectImpl result = _evaluateConstant(compilationUnit, 'c');
+    DartObjectImpl result = _evaluateConstant('c');
     expect(
         result.type, typeProvider.setType.instantiate([typeProvider.intType]));
     expect(result.toSetValue().map((e) => e.toIntValue()), [1, 2, 3, 4]);
diff --git a/pkg/analyzer/test/src/dart/element/element_test.dart b/pkg/analyzer/test/src/dart/element/element_test.dart
index 0ef1e17..565ee2d 100644
--- a/pkg/analyzer/test/src/dart/element/element_test.dart
+++ b/pkg/analyzer/test/src/dart/element/element_test.dart
@@ -45,102 +45,8 @@
   });
 }
 
-/// TODO(paulberry): migrate this test away from the task model.
-/// See dartbug.com/35734.
 @reflectiveTest
-class ClassElementImplTest extends EngineTestCase {
-  @deprecated
-  void test_computeNode_ClassDeclaration() {
-    AnalysisContextHelper contextHelper = new AnalysisContextHelper();
-    AnalysisContext context = contextHelper.context;
-    Source source = contextHelper.addSource("/test.dart", r'''
-class A {}
-@deprecated class B {}
-enum C {C1, C2, C3}
-@deprecated enum D {D1, D2, D3}''');
-    // prepare CompilationUnitElement
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    CompilationUnitElement unitElement = libraryElement.definingCompilationUnit;
-    // A
-    {
-      ClassElement elementA = unitElement.getType("A");
-      expect(elementA.hasDeprecated, isFalse);
-      expect(elementA.isEnum, isFalse);
-      ClassDeclaration nodeA = elementA.computeNode();
-      expect(nodeA, isNotNull);
-      expect(nodeA.name.name, "A");
-      expect(nodeA.declaredElement, same(elementA));
-    }
-    // B
-    {
-      ClassElement elementB = unitElement.getType("B");
-      expect(elementB.hasDeprecated, isTrue);
-      expect(elementB.isEnum, isFalse);
-      ClassDeclaration nodeB = elementB.computeNode();
-      expect(nodeB, isNotNull);
-      expect(nodeB.name.name, "B");
-      expect(nodeB.declaredElement, same(elementB));
-    }
-    // C
-    {
-      ClassElement elementC = unitElement.getEnum("C");
-      expect(elementC.hasDeprecated, isFalse);
-      expect(elementC.isEnum, isTrue);
-      EnumDeclaration nodeC = elementC.computeNode();
-      expect(nodeC, isNotNull);
-      expect(nodeC.name.name, "C");
-      expect(nodeC.declaredElement, same(elementC));
-    }
-    // D
-    {
-      ClassElement elementD = unitElement.getEnum("D");
-      expect(elementD.hasDeprecated, isTrue);
-      expect(elementD.isEnum, isTrue);
-      EnumDeclaration nodeC = elementD.computeNode();
-      expect(nodeC, isNotNull);
-      expect(nodeC.name.name, "D");
-      expect(nodeC.declaredElement, same(elementD));
-    }
-  }
-
-  @deprecated
-  void test_computeNode_ClassTypeAlias() {
-    AnalysisContextHelper contextHelper = new AnalysisContextHelper();
-    AnalysisContext context = contextHelper.context;
-    Source source = contextHelper.addSource("/test.dart", r'''
-abstract class A<K, V> = Object with MapMixin<K, V>;
-''');
-    // prepare CompilationUnitElement
-    LibraryElement libraryElement = context.computeLibraryElement(source);
-    CompilationUnitElement unitElement = libraryElement.definingCompilationUnit;
-    // A
-    {
-      ClassElement elementA = unitElement.getType("A");
-      ClassTypeAlias nodeA = elementA.computeNode();
-      expect(nodeA, isNotNull);
-      expect(nodeA.name.name, "A");
-      expect(nodeA.declaredElement, same(elementA));
-    }
-  }
-
-  void test_constructors_mixinApplicationWithHandle() {
-    AnalysisContext context = createAnalysisContext();
-    context.sourceFactory = new SourceFactory([]);
-
-    ElementLocation location = new ElementLocationImpl.con2('');
-    ClassElementImpl classA = ElementFactory.classElement2("A");
-    classA.mixinApplication = true;
-    TestElementResynthesizer resynthesizer =
-        new TestElementResynthesizer(context, {location: classA});
-    ClassElementHandle classAHandle =
-        new ClassElementHandle(resynthesizer, location);
-    ClassElementImpl classB = new ClassElementImpl('B', 0)
-      ..supertype = new InterfaceTypeImpl(classAHandle);
-    classB.mixinApplication = true;
-
-    expect(classB.constructors, hasLength(1));
-  }
-
+class ClassElementImplTest {
   void test_getAllSupertypes_interface() {
     ClassElement classA = ElementFactory.classElement2("A");
     ClassElement classB = ElementFactory.classElement("B", classA.type);
@@ -321,8 +227,7 @@
     // class A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -336,8 +241,7 @@
     // class A {
     //   m();
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElementImpl method = ElementFactory.methodElement(methodName, null);
@@ -355,8 +259,7 @@
     // class B extends A {
     //   m();
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -379,8 +282,7 @@
     // class B extends A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -401,8 +303,7 @@
     // class B extends A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.abstract = true;
     String methodName = "m";
@@ -424,8 +325,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -441,8 +341,7 @@
   void test_lookUpConcreteMethod_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -453,8 +352,7 @@
     // class A {
     //   get g {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String getterName = "g";
     PropertyAccessorElement getter =
@@ -471,8 +369,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String getterName = "g";
     PropertyAccessorElement getter =
@@ -487,8 +384,7 @@
   void test_lookUpGetter_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -500,8 +396,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     classA.supertype = classB.type;
@@ -514,8 +409,7 @@
     // class A {
     //   get g {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String getterName = "g";
     PropertyAccessorElement getter =
@@ -532,8 +426,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String getterName = "g";
     PropertyAccessorElement inheritedGetter =
@@ -549,8 +442,7 @@
   void test_lookUpInheritedConcreteGetter_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -562,8 +454,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     classA.supertype = classB.type;
@@ -576,8 +467,7 @@
     // class A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -594,8 +484,7 @@
     // class B extends A {
     //   m();
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -618,8 +507,7 @@
     // class B extends A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -641,8 +529,7 @@
     // class B extends A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     classA.abstract = true;
     String methodName = "m";
@@ -669,8 +556,7 @@
     // class C extends B {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -696,8 +582,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -713,8 +598,7 @@
   void test_lookUpInheritedConcreteMethod_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -725,8 +609,7 @@
     // class A {
     //   set g(x) {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String setterName = "s";
     PropertyAccessorElement setter =
@@ -743,8 +626,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String setterName = "s";
     PropertyAccessorElement setter =
@@ -760,8 +642,7 @@
   void test_lookUpInheritedConcreteSetter_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -773,8 +654,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     classA.supertype = classB.type;
@@ -787,8 +667,7 @@
     // class A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -805,8 +684,7 @@
     // class B extends A {
     //   m() {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -827,8 +705,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement inheritedMethod =
@@ -844,8 +721,7 @@
   void test_lookUpInheritedMethod_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -853,8 +729,7 @@
   }
 
   void test_lookUpMethod_declared() {
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -865,8 +740,7 @@
   }
 
   void test_lookUpMethod_inherited() {
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String methodName = "m";
     MethodElement method = ElementFactory.methodElement(methodName, null);
@@ -878,8 +752,7 @@
   }
 
   void test_lookUpMethod_undeclared() {
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -887,8 +760,7 @@
   }
 
   void test_lookUpMethod_undeclared_recursive() {
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     classA.supertype = classB.type;
@@ -901,8 +773,7 @@
     // class A {
     //   set g(x) {}
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String setterName = "s";
     PropertyAccessorElement setter =
@@ -919,8 +790,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     String setterName = "s";
     PropertyAccessorElement setter =
@@ -935,8 +805,7 @@
   void test_lookUpSetter_undeclared() {
     // class A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     (library.definingCompilationUnit as CompilationUnitElementImpl).types =
         <ClassElement>[classA];
@@ -948,8 +817,7 @@
     // }
     // class B extends A {
     // }
-    LibraryElementImpl library =
-        ElementFactory.library(createAnalysisContext(), "lib");
+    LibraryElementImpl library = _newLibrary();
     ClassElementImpl classA = ElementFactory.classElement2("A");
     ClassElementImpl classB = ElementFactory.classElement("B", classA.type);
     classA.supertype = classB.type;
@@ -957,6 +825,8 @@
         <ClassElement>[classA, classB];
     expect(classA.lookUpSetter("s", library), isNull);
   }
+
+  LibraryElementImpl _newLibrary() => ElementFactory.library(null, 'lib');
 }
 
 @reflectiveTest
diff --git a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
index 07fb0e8..2755ffb 100644
--- a/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.dart
+++ b/pkg/analyzer/test/src/dart/element/inheritance_manager2_test.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/element/element.dart';
+import 'package:analyzer/dart/element/type.dart';
 import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
+import 'package:meta/meta.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
@@ -43,9 +44,10 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getInherited('X', 'foo'),
-      same(findElement.method('foo', of: 'B')),
+    _assertGetInherited(
+      className: 'X',
+      name: 'foo',
+      expected: 'B.foo: () → void',
     );
   }
 
@@ -65,9 +67,10 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getInherited('X', 'foo'),
-      same(findElement.method('foo', of: 'J')),
+    _assertGetInherited(
+      className: 'X',
+      name: 'foo',
+      expected: 'J.foo: () → void',
     );
   }
 
@@ -87,9 +90,10 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getInherited('X', 'foo'),
-      same(findElement.method('foo', of: 'M')),
+    _assertGetInherited(
+      className: 'X',
+      name: 'foo',
+      expected: 'M.foo: () → void',
     );
   }
 
@@ -109,12 +113,593 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getInherited('X', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetInherited(
+      className: 'X',
+      name: 'foo',
+      expected: 'A.foo: () → void',
     );
   }
 
+  test_getInheritedConcreteMap_accessor_extends() async {
+    addTestFile('''
+class A {
+  int get foo => 0;
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', r'''
+A.foo: () → int
+''');
+  }
+
+  test_getInheritedConcreteMap_accessor_implements() async {
+    addTestFile('''
+class A {
+  int get foo => 0;
+}
+
+abstract class B implements A {}
+''');
+    await resolveTestFile();
+    _assertInheritedConcreteMap('B', '');
+  }
+
+  test_getInheritedConcreteMap_accessor_with() async {
+    addTestFile('''
+mixin A {
+  int get foo => 0;
+}
+
+class B extends Object with A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', r'''
+A.foo: () → int
+''');
+  }
+
+  test_getInheritedConcreteMap_implicitExtends() async {
+    addTestFile('''
+class A {}
+''');
+    await resolveTestFile();
+    _assertInheritedConcreteMap('A', '');
+  }
+
+  test_getInheritedConcreteMap_method_extends() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedConcreteMap_method_extends_abstract() async {
+    addTestFile('''
+abstract class A {
+  void foo();
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', '');
+  }
+
+  test_getInheritedConcreteMap_method_extends_invalidForImplements() async {
+    addTestFile('''
+abstract class I {
+  void foo(int x, {int y});
+  void bar(String s);
+}
+
+class A {
+  void foo(int x) {}
+}
+
+class C extends A implements I {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('C', r'''
+A.foo: (int) → void
+''');
+  }
+
+  test_getInheritedConcreteMap_method_implements() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+abstract class B implements A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', '');
+  }
+
+  test_getInheritedConcreteMap_method_with() async {
+    addTestFile('''
+mixin A {
+  void foo() {}
+}
+
+class B extends Object with A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('B', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedConcreteMap_method_with2() async {
+    addTestFile('''
+mixin A {
+  void foo() {}
+}
+
+mixin B {
+  void bar() {}
+}
+
+class C extends Object with A, B {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedConcreteMap('C', r'''
+A.foo: () → void
+B.bar: () → void
+''');
+  }
+
+  test_getInheritedMap_accessor_extends() async {
+    addTestFile('''
+class A {
+  int get foo => 0;
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+''');
+  }
+
+  test_getInheritedMap_accessor_implements() async {
+    addTestFile('''
+class A {
+  int get foo => 0;
+}
+
+abstract class B implements A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+''');
+  }
+
+  test_getInheritedMap_accessor_with() async {
+    addTestFile('''
+mixin A {
+  int get foo => 0;
+}
+
+class B extends Object with A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+''');
+  }
+
+  test_getInheritedMap_closestSuper() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+class B extends A {
+  void foo() {}
+}
+
+class X extends B {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('X', r'''
+B.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_field_extends() async {
+    addTestFile('''
+class A {
+  int foo;
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+A.foo=: (int) → void
+''');
+  }
+
+  test_getInheritedMap_field_implements() async {
+    addTestFile('''
+class A {
+  int foo;
+}
+
+abstract class B implements A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+A.foo=: (int) → void
+''');
+  }
+
+  test_getInheritedMap_field_with() async {
+    addTestFile('''
+mixin A {
+  int foo;
+}
+
+class B extends Object with A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → int
+A.foo=: (int) → void
+''');
+  }
+
+  test_getInheritedMap_implicitExtendsObject() async {
+    addTestFile('''
+class A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', '');
+  }
+
+  test_getInheritedMap_method_extends() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+class B extends A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_method_implements() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+abstract class B implements A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_method_with() async {
+    addTestFile('''
+mixin A {
+  void foo() {}
+}
+
+class B extends Object with A {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('B', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_preferImplemented() async {
+    addTestFile('''
+class A {
+  void foo() {}
+}
+
+class I {
+  void foo() {}
+}
+
+class X extends A implements I {
+  void foo() {}
+}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('X', r'''
+A.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_union_conflict() async {
+    addTestFile('''
+abstract class I {
+  int foo();
+  void bar();
+}
+
+abstract class J {
+  double foo();
+  void bar();
+}
+
+abstract class A implements I, J {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+J.bar: () → void
+''');
+  }
+
+  test_getInheritedMap_union_differentNames() async {
+    addTestFile('''
+abstract class I {
+  int foo();
+}
+
+abstract class J {
+  double bar();
+}
+
+abstract class A implements I, J {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+I.foo: () → int
+J.bar: () → double
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_2_getters() async {
+    addTestFile('''
+abstract class I {
+  int get foo;
+}
+
+abstract class J {
+  int get foo;
+}
+
+abstract class A implements I, J {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+J.foo: () → int
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_2_methods() async {
+    addTestFile('''
+abstract class I {
+  void foo();
+}
+
+abstract class J {
+  void foo();
+}
+
+abstract class A implements I, J {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+J.foo: () → void
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_2_setters() async {
+    addTestFile('''
+abstract class I {
+  void set foo(num _);
+}
+
+abstract class J {
+  void set foo(int _);
+}
+
+abstract class A implements I, J {}
+abstract class B implements J, I {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+I.foo=: (num) → void
+''');
+
+    _assertInheritedMap('B', r'''
+I.foo=: (num) → void
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_3_getters() async {
+    addTestFile('''
+class A {}
+class B extends A {}
+class C extends B {}
+
+abstract class I1 {
+  A get foo;
+}
+
+abstract class I2 {
+  B get foo;
+}
+
+abstract class I3 {
+  C get foo;
+}
+
+abstract class D implements I1, I2, I3 {}
+abstract class E implements I3, I2, I1 {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('D', r'''
+I3.foo: () → C
+''');
+
+    _assertInheritedMap('E', r'''
+I3.foo: () → C
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_3_methods() async {
+    addTestFile('''
+class A {}
+class B extends A {}
+class C extends B {}
+
+abstract class I1 {
+  void foo(A _);
+}
+
+abstract class I2 {
+  void foo(B _);
+}
+
+abstract class I3 {
+  void foo(C _);
+}
+
+abstract class D implements I1, I2, I3 {}
+abstract class E implements I3, I2, I1 {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('D', r'''
+I1.foo: (A) → void
+''');
+  }
+
+  test_getInheritedMap_union_multipleSubtypes_3_setters() async {
+    addTestFile('''
+class A {}
+class B extends A {}
+class C extends B {}
+
+abstract class I1 {
+  set foo(A _);
+}
+
+abstract class I2 {
+  set foo(B _);
+}
+
+abstract class I3 {
+  set foo(C _);
+}
+
+abstract class D implements I1, I2, I3 {}
+abstract class E implements I3, I2, I1 {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('D', r'''
+I1.foo=: (A) → void
+''');
+
+    _assertInheritedMap('E', r'''
+I1.foo=: (A) → void
+''');
+  }
+
+  test_getInheritedMap_union_oneSubtype_2_methods() async {
+    addTestFile('''
+abstract class I1 {
+  int foo();
+}
+
+abstract class I2 {
+  int foo([int _]);
+}
+
+abstract class A implements I1, I2 {}
+abstract class B implements I2, I1 {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+I2.foo: ([int]) → int
+''');
+
+    _assertInheritedMap('B', r'''
+I2.foo: ([int]) → int
+''');
+  }
+
+  test_getInheritedMap_union_oneSubtype_3_methods() async {
+    addTestFile('''
+abstract class I1 {
+  int foo();
+}
+
+abstract class I2 {
+  int foo([int _]);
+}
+
+abstract class I3 {
+  int foo([int _, int __]);
+}
+
+abstract class A implements I1, I2, I3 {}
+abstract class B implements I3, I2, I1 {}
+''');
+    await resolveTestFile();
+
+    _assertInheritedMap('A', r'''
+I3.foo: ([int, int]) → int
+''');
+
+    _assertInheritedMap('B', r'''
+I3.foo: ([int, int]) → int
+''');
+  }
+
   test_getMember() async {
     addTestFile('''
 abstract class I1 {
@@ -129,11 +714,11 @@
 ''');
     await resolveTestFile();
 
-    var memberType = manager.getMember(
-      findElement.class_('C').type,
-      new Name(null, 'f'),
+    _assertGetMember(
+      className: 'C',
+      name: 'f',
+      expected: 'I2.f: (Object) → void',
     );
-    assertElementTypeString(memberType, '(Object) → void');
   }
 
   test_getMember_concrete() async {
@@ -144,9 +729,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('A', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'A',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -158,7 +745,11 @@
 ''');
     await resolveTestFile();
 
-    expect(_getConcrete('A', 'foo'), isNull);
+    _assertGetMember(
+      className: 'A',
+      name: 'foo',
+      concrete: true,
+    );
   }
 
   test_getMember_concrete_fromMixedClass() async {
@@ -171,9 +762,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('X', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -189,9 +782,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('X', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -207,9 +802,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('X', 'toString'),
-      same(findElement.method('toString', of: 'A')),
+    _assertGetMember(
+      className: 'X',
+      name: 'toString',
+      concrete: true,
+      expected: 'A.toString: () → String',
     );
   }
 
@@ -223,9 +820,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('X', 'foo'),
-      same(findElement.method('foo', of: 'M')),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      concrete: true,
+      expected: 'M.foo: () → void',
     );
   }
 
@@ -241,14 +840,18 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('B', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
 
-    expect(
-      _getConcrete('C', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'C',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -258,7 +861,11 @@
 ''');
     await resolveTestFile();
 
-    expect(_getConcrete('A', 'foo'), isNull);
+    _assertGetMember(
+      className: 'A',
+      name: 'foo',
+      concrete: true,
+    );
   }
 
   test_getMember_concrete_noSuchMethod() async {
@@ -275,14 +882,18 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('B', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
 
-    expect(
-      _getConcrete('C', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'C',
+      name: 'foo',
+      concrete: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -300,7 +911,11 @@
 
     // noSuchMethod forwarders are not mixed-in.
     // https://github.com/dart-lang/sdk/issues/33553#issuecomment-424638320
-    expect(_getConcrete('B', 'foo'), isNull);
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      concrete: true,
+    );
   }
 
   test_getMember_concrete_noSuchMethod_moreSpecificSignature() async {
@@ -314,14 +929,16 @@
 }
 
 class C extends B {
-  void foo([a]);
+  void foo([int a]);
 }
 ''');
     await resolveTestFile();
 
-    expect(
-      _getConcrete('C', 'foo'),
-      same(findElement.method('foo', of: 'C')),
+    _assertGetMember(
+      className: 'C',
+      name: 'foo',
+      concrete: true,
+      expected: 'C.foo: ([int]) → void',
     );
   }
 
@@ -347,11 +964,11 @@
 ''');
     await resolveTestFile();
 
-    var member = manager.getMember(
-      findElement.class_('X').type,
-      new Name(null, 'foo'),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      expected: 'M2.foo: () → void',
     );
-    expect(member.element, findElement.method('foo', of: 'M2'));
   }
 
   test_getMember_preferLatest_superclass() async {
@@ -372,11 +989,11 @@
 ''');
     await resolveTestFile();
 
-    var member = manager.getMember(
-      findElement.class_('X').type,
-      new Name(null, 'foo'),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      expected: 'B.foo: () → void',
     );
-    expect(member.element, findElement.method('foo', of: 'B'));
   }
 
   test_getMember_preferLatest_this() async {
@@ -395,11 +1012,11 @@
 ''');
     await resolveTestFile();
 
-    var member = manager.getMember(
-      findElement.class_('X').type,
-      new Name(null, 'foo'),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      expected: 'X.foo: () → void',
     );
-    expect(member.element, findElement.method('foo', of: 'X'));
   }
 
   test_getMember_super_abstract() async {
@@ -414,7 +1031,11 @@
 ''');
     await resolveTestFile();
 
-    expect(_getSuper('B', 'foo'), isNull);
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      forSuper: true,
+    );
   }
 
   test_getMember_super_forMixin_interface() async {
@@ -427,9 +1048,10 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getSuperForElement(findElement.mixin('M'), 'foo'),
-      isNull,
+    _assertGetMember(
+      className: 'M',
+      name: 'foo',
+      forSuper: true,
     );
   }
 
@@ -443,9 +1065,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getSuperForElement(findElement.mixin('M'), 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'M',
+      name: 'foo',
+      forSuper: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -461,9 +1085,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getSuper('X', 'foo'),
-      same(findElement.method('foo', of: 'M')),
+    _assertGetMember(
+      className: 'X',
+      name: 'foo',
+      forSuper: true,
+      expected: 'M.foo: () → void',
     );
   }
 
@@ -479,9 +1105,11 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getSuper('B', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      forSuper: true,
+      expected: 'A.foo: () → void',
     );
   }
 
@@ -493,7 +1121,11 @@
 ''');
     await resolveTestFile();
 
-    expect(_getSuper('B', 'foo'), isNull);
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      forSuper: true,
+    );
   }
 
   test_getMember_super_noSuchMember() async {
@@ -509,33 +1141,90 @@
 ''');
     await resolveTestFile();
 
-    expect(
-      _getSuper('B', 'foo'),
-      same(findElement.method('foo', of: 'A')),
+    _assertGetMember(
+      className: 'B',
+      name: 'foo',
+      forSuper: true,
+      expected: 'A.foo: () → void',
     );
   }
 
-  ExecutableElement _getConcrete(String className, String name) {
+  void _assertGetInherited({
+    @required String className,
+    @required String name,
+    String expected,
+  }) {
+    var interfaceType = findElement.classOrMixin(className).type;
+
+    var memberType = manager.getInherited(
+      interfaceType,
+      new Name(null, name),
+    );
+
+    _assertMemberType(memberType, expected);
+  }
+
+  void _assertGetMember({
+    @required String className,
+    @required String name,
+    String expected,
+    bool concrete = false,
+    bool forSuper = false,
+  }) {
+    var interfaceType = findElement.classOrMixin(className).type;
+
+    var memberType = manager.getMember(
+      interfaceType,
+      new Name(null, name),
+      concrete: concrete,
+      forSuper: forSuper,
+    );
+
+    _assertMemberType(memberType, expected);
+  }
+
+  void _assertInheritedConcreteMap(String className, String expected) {
     var type = findElement.class_(className).type;
-    return manager
-        .getMember(type, new Name(null, name), concrete: true)
-        ?.element;
+    var map = manager.getInheritedConcreteMap(type);
+    _assertNameToFunctionTypeMap(map, expected);
   }
 
-  ExecutableElement _getInherited(String className, String name) {
+  void _assertInheritedMap(String className, String expected) {
     var type = findElement.class_(className).type;
-    return manager.getInherited(type, new Name(null, name)).element;
+    var map = manager.getInheritedMap(type);
+    _assertNameToFunctionTypeMap(map, expected);
   }
 
-  ExecutableElement _getSuper(String className, String name) {
-    var element = findElement.class_(className);
-    return _getSuperForElement(element, name);
+  void _assertMemberType(FunctionType type, String expected) {
+    if (expected != null) {
+      var element = type.element;
+      var enclosingElement = element.enclosingElement;
+      var actual = '${enclosingElement.name}.${element.name}: $type';
+      expect(actual, expected);
+    } else {
+      expect(type, isNull);
+    }
   }
 
-  ExecutableElement _getSuperForElement(ClassElement element, String name) {
-    var type = element.type;
-    return manager
-        .getMember(type, new Name(null, name), forSuper: true)
-        ?.element;
+  void _assertNameToFunctionTypeMap(
+      Map<Name, FunctionType> map, String expected) {
+    var lines = <String>[];
+    for (var name in map.keys) {
+      var type = map[name];
+      var element = type.element;
+
+      var enclosingElement = element.enclosingElement;
+      if (enclosingElement.name == 'Object') continue;
+
+      lines.add('${enclosingElement.name}.${element.name}: $type');
+    }
+
+    lines.sort();
+    var actual = lines.isNotEmpty ? lines.join('\n') + '\n' : '';
+
+    if (actual != expected) {
+      print(actual);
+    }
+    expect(actual, expected);
   }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
index 081ef0e..50902ca 100644
--- a/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/driver_resolution.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/file_system/file_system.dart';
 import 'package:analyzer/src/dart/analysis/byte_store.dart';
 import 'package:analyzer/src/dart/analysis/driver.dart';
@@ -41,14 +42,8 @@
   }
 
   @override
-  Future<TestAnalysisResult> resolveFile(String path) async {
-    var result = await driver.getResult(path);
-    return new TestAnalysisResult(
-      path,
-      result.content,
-      result.unit,
-      result.errors,
-    );
+  Future<ResolvedUnitResult> resolveFile(String path) async {
+    return await driver.getResult(path);
   }
 
   void setUp() {
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 d0e73a6..4c7daeb 100644
--- a/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/flow_analysis_test.dart
@@ -17,6 +17,7 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(NullableFlowTest);
     defineReflectiveTests(DefiniteAssignmentFlowTest);
     defineReflectiveTests(ReachableFlowTest);
     defineReflectiveTests(TypePromotionFlowTest);
@@ -1080,7 +1081,6 @@
     assertReadBeforeWritten();
   }
 
-  @failingTest
   test_tryCatchFinally_useInFinally() async {
     await trackCode(r'''
 f() {
@@ -1308,8 +1308,8 @@
 
     var unit = result.unit;
 
-    var loopAssignedVariables = LoopAssignedVariables();
-    unit.accept(_LoopAssignedVariablesVisitor(loopAssignedVariables));
+    var loopAssignedVariables = AssignedVariables();
+    unit.accept(_AssignedVariablesVisitor(loopAssignedVariables));
 
     var typeSystem = unit.declaredElement.context.typeSystem;
     unit.accept(_AstVisitor(
@@ -1319,6 +1319,323 @@
       readBeforeWritten,
       [],
       [],
+      [],
+      [],
+    ));
+  }
+}
+
+@reflectiveTest
+class NullableFlowTest extends DriverResolutionTest {
+  final List<AstNode> nullableNodes = [];
+  final List<AstNode> nonNullableNodes = [];
+
+  void assertNonNullable([
+    String search1,
+    String search2,
+    String search3,
+    String search4,
+    String search5,
+  ]) {
+    var expected = [search1, search2, search3, search4, search5]
+        .where((i) => i != null)
+        .map((search) => findNode.simple(search))
+        .toList();
+    expect(nonNullableNodes, unorderedEquals(expected));
+  }
+
+  void assertNullable([
+    String search1,
+    String search2,
+    String search3,
+    String search4,
+    String search5,
+  ]) {
+    var expected = [search1, search2, search3, search4, search5]
+        .where((i) => i != null)
+        .map((search) => findNode.simple(search))
+        .toList();
+    expect(nullableNodes, unorderedEquals(expected));
+  }
+
+  test_assign_toNonNull() async {
+    await trackCode(r'''
+void f(int x) {
+  if (x != null) return;
+  x; // 1
+  x = 0;
+  x; // 2
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable('x; // 2');
+  }
+
+  test_assign_toNull() async {
+    await trackCode(r'''
+void f(int x) {
+  if (x == null) return;
+  x; // 1
+  x = null;
+  x; // 2
+}
+''');
+    assertNullable('x; // 2');
+    assertNonNullable('x; // 1');
+  }
+
+  test_assign_toUnknown_fromNotNull() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a == null) return;
+  a; // 1
+  a = b;
+  a; // 2
+}
+''');
+    assertNullable();
+    assertNonNullable('a; // 1');
+  }
+
+  test_assign_toUnknown_fromNull() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a != null) return;
+  a; // 1
+  a = b;
+  a; // 2
+}
+''');
+    assertNullable('a; // 1');
+    assertNonNullable();
+  }
+
+  test_binaryExpression_logicalAnd() async {
+    await trackCode(r'''
+void f(int x) {
+  x == null && x.isEven;
+}
+''');
+    assertNullable('x.isEven');
+    assertNonNullable();
+  }
+
+  test_binaryExpression_logicalOr() async {
+    await trackCode(r'''
+void f(int x) {
+  x == null || x.isEven;
+}
+''');
+    assertNullable();
+    assertNonNullable('x.isEven');
+  }
+
+  test_if_joinThenElse_ifNull() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a == null) {
+    a; // 1
+    if (b == null) return;
+    b; // 2
+  } else {
+    a; // 3
+    if (b == null) return;
+    b; // 4
+  }
+  a; // 5
+  b; // 6
+}
+''');
+    assertNullable('a; // 1');
+    assertNonNullable('b; // 2', 'a; // 3', 'b; // 4', 'b; // 6');
+  }
+
+  test_if_notNull_thenExit() async {
+    await trackCode(r'''
+void f(int x) {
+  if (x != null) return;
+  x; // 1
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable();
+  }
+
+  test_if_null_thenExit() async {
+    await trackCode(r'''
+void f(int x) {
+  if (x == null) return;
+  x; // 1
+}
+''');
+    assertNullable();
+    assertNonNullable('x; // 1');
+  }
+
+  test_if_then_else() async {
+    await trackCode(r'''
+void f(int x) {
+  if (x == null) {
+    x; // 1
+  } else {
+    x; // 2
+  }
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable('x; // 2');
+  }
+
+  test_potentiallyMutatedInClosure() async {
+    await trackCode(r'''
+f(int a, int b) {
+  localFunction() {
+    a = b;
+  }
+
+  if (a == null) {
+    a; // 1
+    localFunction();
+    a; // 2
+  }
+}
+''');
+    assertNullable();
+    assertNonNullable();
+  }
+
+  test_tryFinally_eqNullExit_body() async {
+    await trackCode(r'''
+void f(int x) {
+  try {
+    if (x == null) return;
+    x; // 1
+  } finally {
+    x; // 2
+  }
+  x; // 3
+}
+''');
+    assertNullable();
+    assertNonNullable('x; // 1', 'x; // 3');
+  }
+
+  test_tryFinally_eqNullExit_finally() async {
+    await trackCode(r'''
+void f(int x) {
+  try {
+    x; // 1
+  } finally {
+    if (x == null) return;
+    x; // 2
+  }
+  x; // 3
+}
+''');
+    assertNullable();
+    assertNonNullable('x; // 2', 'x; // 3');
+  }
+
+  test_tryFinally_outerEqNotNullExit_assignUnknown_body() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a != null) return;
+  try {
+    a; // 1
+    a = b;
+    a; // 2
+  } finally {
+    a; // 3
+  }
+  a; // 4
+}
+''');
+    assertNullable('a; // 1');
+    assertNonNullable();
+  }
+
+  test_tryFinally_outerEqNullExit_assignUnknown_body() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a == null) return;
+  try {
+    a; // 1
+    a = b;
+    a; // 2
+  } finally {
+    a; // 3
+  }
+  a; // 4
+}
+''');
+    assertNullable();
+    assertNonNullable('a; // 1');
+  }
+
+  test_tryFinally_outerEqNullExit_assignUnknown_finally() async {
+    await trackCode(r'''
+void f(int a, int b) {
+  if (a == null) return;
+  try {
+    a; // 1
+  } finally {
+    a; // 2
+    a = b;
+    a; // 3
+  }
+  a; // 4
+}
+''');
+    assertNullable();
+    assertNonNullable('a; // 1', 'a; // 2');
+  }
+
+  test_while_eqNull() async {
+    await trackCode(r'''
+void f(int x) {
+  while (x == null) {
+    x; // 1
+  }
+  x; // 2
+}
+''');
+    assertNullable('x; // 1');
+    assertNonNullable('x; // 2');
+  }
+
+  test_while_notEqNull() async {
+    await trackCode(r'''
+void f(int x) {
+  while (x != null) {
+    x; // 1
+  }
+  x; // 2
+}
+''');
+    assertNullable('x; // 2');
+    assertNonNullable('x; // 1');
+  }
+
+  /// Resolve the given [code] and track nullability in the unit.
+  Future<void> trackCode(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+
+    var unit = result.unit;
+
+    var loopAssignedVariables = AssignedVariables();
+    unit.accept(_AssignedVariablesVisitor(loopAssignedVariables));
+
+    var typeSystem = unit.declaredElement.context.typeSystem;
+    unit.accept(_AstVisitor(
+      typeSystem,
+      loopAssignedVariables,
+      {},
+      [],
+      nullableNodes,
+      nonNullableNodes,
+      [],
+      [],
     ));
   }
 }
@@ -1753,8 +2070,8 @@
 
     var unit = result.unit;
 
-    var loopAssignedVariables = LoopAssignedVariables();
-    unit.accept(_LoopAssignedVariablesVisitor(loopAssignedVariables));
+    var loopAssignedVariables = AssignedVariables();
+    unit.accept(_AssignedVariablesVisitor(loopAssignedVariables));
 
     var typeSystem = unit.declaredElement.context.typeSystem;
     unit.accept(_AstVisitor(
@@ -1762,6 +2079,8 @@
       loopAssignedVariables,
       {},
       [],
+      [],
+      [],
       unreachableNodes,
       functionBodiesThatDontComplete,
     ));
@@ -2584,8 +2903,8 @@
 
     var unit = result.unit;
 
-    var loopAssignedVariables = LoopAssignedVariables();
-    unit.accept(_LoopAssignedVariablesVisitor(loopAssignedVariables));
+    var loopAssignedVariables = AssignedVariables();
+    unit.accept(_AssignedVariablesVisitor(loopAssignedVariables));
 
     var typeSystem = unit.declaredElement.context.typeSystem;
     unit.accept(_AstVisitor(
@@ -2595,31 +2914,124 @@
       [],
       [],
       [],
+      [],
+      [],
     ));
   }
 }
 
+class _AssignedVariablesVisitor extends RecursiveAstVisitor<void> {
+  final AssignedVariables assignedVariables;
+
+  _AssignedVariablesVisitor(this.assignedVariables);
+
+  @override
+  void visitAssignmentExpression(AssignmentExpression node) {
+    var left = node.leftHandSide;
+
+    super.visitAssignmentExpression(node);
+
+    if (left is SimpleIdentifier) {
+      var element = left.staticElement;
+      if (element is VariableElement) {
+        assignedVariables.write(element);
+      }
+    }
+  }
+
+  @override
+  void visitDoStatement(DoStatement node) {
+    assignedVariables.beginLoop();
+    super.visitDoStatement(node);
+    assignedVariables.endLoop(node);
+  }
+
+  @override
+  void visitForEachStatement(ForEachStatement node) {
+    var iterable = node.iterable;
+    var body = node.body;
+
+    iterable.accept(this);
+
+    assignedVariables.beginLoop();
+    body.accept(this);
+    assignedVariables.endLoop(node);
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    node.initialization?.accept(this);
+    node.variables?.accept(this);
+
+    assignedVariables.beginLoop();
+    node.condition?.accept(this);
+    node.body.accept(this);
+    node.updaters?.accept(this);
+    assignedVariables.endLoop(node);
+  }
+
+  @override
+  void visitSwitchStatement(SwitchStatement node) {
+    var expression = node.expression;
+    var members = node.members;
+
+    expression.accept(this);
+
+    assignedVariables.beginLoop();
+    members.accept(this);
+    assignedVariables.endLoop(node);
+  }
+
+  @override
+  void visitTryStatement(TryStatement node) {
+    assignedVariables.beginLoop();
+    node.body.accept(this);
+    assignedVariables.endLoop(node.body);
+
+    node.catchClauses.accept(this);
+
+    var finallyBlock = node.finallyBlock;
+    if (finallyBlock != null) {
+      assignedVariables.beginLoop();
+      finallyBlock.accept(this);
+      assignedVariables.endLoop(finallyBlock);
+    }
+  }
+
+  @override
+  void visitWhileStatement(WhileStatement node) {
+    assignedVariables.beginLoop();
+    super.visitWhileStatement(node);
+    assignedVariables.endLoop(node);
+  }
+}
+
 /// [AstVisitor] that drives the [flow] in the way we expect the resolver
 /// will do in production.
 class _AstVisitor extends GeneralizingAstVisitor<void> {
   static final trueLiteral = astFactory.booleanLiteral(null, true);
 
-  final TypeSystem typeSystem;
-  final LoopAssignedVariables loopAssignedVariables;
+  final TypeOperations<DartType> typeOperations;
+  final AssignedVariables assignedVariables;
   final Map<AstNode, DartType> promotedTypes;
   final List<LocalVariableElement> readBeforeWritten;
+  final List<AstNode> nullableNodes;
+  final List<AstNode> nonNullableNodes;
   final List<AstNode> unreachableNodes;
   final List<FunctionBody> functionBodiesThatDontComplete;
 
-  FlowAnalysis flow;
+  FlowAnalysis<DartType> flow;
 
   _AstVisitor(
-      this.typeSystem,
-      this.loopAssignedVariables,
+      TypeSystem typeSystem,
+      this.assignedVariables,
       this.promotedTypes,
       this.readBeforeWritten,
+      this.nullableNodes,
+      this.nonNullableNodes,
       this.unreachableNodes,
-      this.functionBodiesThatDontComplete);
+      this.functionBodiesThatDontComplete)
+      : typeOperations = _TypeSystemTypeOperations(typeSystem);
 
   @override
   void visitAssignmentExpression(AssignmentExpression node) {
@@ -2640,7 +3052,11 @@
         flow.read(localElement);
       }
       right.accept(this);
-      flow.write(localElement);
+      flow.write(
+        localElement,
+        isNull: _isNull(right),
+        isNonNull: _isNonNull(right),
+      );
     } else {
       left.accept(this);
       right.accept(this);
@@ -2670,6 +3086,28 @@
       right.accept(this);
 
       flow.logicalOr_end(node);
+    } else if (operator == TokenType.BANG_EQ) {
+      left.accept(this);
+      right.accept(this);
+      if (right is NullLiteral) {
+        if (left is SimpleIdentifier) {
+          var element = left.staticElement;
+          if (element is VariableElement) {
+            flow.conditionNotEqNull(node, element);
+          }
+        }
+      }
+    } else if (operator == TokenType.EQ_EQ) {
+      left.accept(this);
+      right.accept(this);
+      if (right is NullLiteral) {
+        if (left is SimpleIdentifier) {
+          var element = left.staticElement;
+          if (element is VariableElement) {
+            flow.conditionEqNull(node, element);
+          }
+        }
+      }
     } else if (operator == TokenType.QUESTION_QUESTION) {
       left.accept(this);
 
@@ -2686,7 +3124,20 @@
   @override
   void visitBlockFunctionBody(BlockFunctionBody node) {
     var isFlowOwner = flow == null;
-    flow ??= FlowAnalysis(typeSystem, node);
+
+    if (isFlowOwner) {
+      flow = FlowAnalysis<DartType>(typeOperations, node);
+
+      var function = node.parent;
+      if (function is FunctionExpression) {
+        var parameters = function.parameters;
+        if (parameters != null) {
+          for (var parameter in parameters?.parameters) {
+            flow.add(parameter.declaredElement, assigned: true);
+          }
+        }
+      }
+    }
 
     super.visitBlockFunctionBody(node);
 
@@ -2754,7 +3205,7 @@
     var body = node.body;
     var condition = node.condition;
 
-    flow.doStatement_bodyBegin(node, loopAssignedVariables[node]);
+    flow.doStatement_bodyBegin(node, assignedVariables[node]);
     body.accept(this);
 
     flow.doStatement_conditionBegin();
@@ -2771,7 +3222,7 @@
     var body = node.body;
 
     iterable.accept(this);
-    flow.forEachStatement_bodyBegin(loopAssignedVariables[node]);
+    flow.forEachStatement_bodyBegin(assignedVariables[node]);
 
     body.accept(this);
 
@@ -2787,7 +3238,7 @@
     node.initialization?.accept(this);
     node.variables?.accept(this);
 
-    flow.forStatement_conditionBegin(loopAssignedVariables[node]);
+    flow.forStatement_conditionBegin(assignedVariables[node]);
     if (condition != null) {
       condition.accept(this);
     } else {
@@ -2809,7 +3260,7 @@
     if (parts is ForEachParts) {
       parts.iterable?.accept(this);
 
-      flow.forEachStatement_bodyBegin(loopAssignedVariables[node]);
+      flow.forEachStatement_bodyBegin(assignedVariables[node]);
 
       node.body.accept(this);
 
@@ -2832,7 +3283,7 @@
     initialization?.accept(this);
     variables?.accept(this);
 
-    flow.forStatement_conditionBegin(loopAssignedVariables[node]);
+    flow.forStatement_conditionBegin(assignedVariables[node]);
     if (condition != null) {
       condition.accept(this);
     } else {
@@ -2920,11 +3371,19 @@
     var element = node.staticElement;
     var isLocalVariable = element is LocalVariableElement;
     if (isLocalVariable || element is ParameterElement) {
-      if (node.inGetterContext()) {
+      if (node.inGetterContext() && !node.inDeclarationContext()) {
         if (isLocalVariable) {
           flow.read(element);
         }
 
+        if (flow.isNullable(element)) {
+          nullableNodes?.add(node);
+        }
+
+        if (flow.isNonNullable(element)) {
+          nonNullableNodes?.add(node);
+        }
+
         var promotedType = flow?.promotedType(element);
         if (promotedType != null) {
           promotedTypes[node] = promotedType;
@@ -2948,7 +3407,7 @@
     node.expression.accept(this);
     flow.switchStatement_expressionEnd(node);
 
-    var assignedInCases = loopAssignedVariables[node];
+    var assignedInCases = assignedVariables[node];
 
     var members = node.members;
     var membersLength = members.length;
@@ -2957,9 +3416,7 @@
       var member = members[i];
 
       flow.switchStatement_beginCase(
-        member.labels.isNotEmpty
-            ? assignedInCases
-            : LoopAssignedVariables.emptySet,
+        member.labels.isNotEmpty ? assignedInCases : AssignedVariables.emptySet,
       );
       member.accept(this);
 
@@ -2985,23 +3442,31 @@
 
     var body = node.body;
     var catchClauses = node.catchClauses;
+    var finallyBlock = node.finallyBlock;
 
-    flow.tryStatement_bodyBegin();
+    if (finallyBlock != null) {
+      flow.tryFinallyStatement_bodyBegin();
+    }
+
+    flow.tryCatchStatement_bodyBegin();
     body.accept(this);
-    flow.tryStatement_bodyEnd(loopAssignedVariables[node.body]);
+    flow.tryCatchStatement_bodyEnd(assignedVariables[body]);
 
     var catchLength = catchClauses.length;
     for (var i = 0; i < catchLength; ++i) {
       var catchClause = catchClauses[i];
-      flow.tryStatement_catchBegin();
+      flow.tryCatchStatement_catchBegin();
       catchClause.accept(this);
-      flow.tryStatement_catchEnd();
+      flow.tryCatchStatement_catchEnd();
     }
 
-    flow.tryStatement_finallyBegin();
-    node.finallyBlock?.accept(this);
+    flow.tryCatchStatement_end();
 
-    flow.tryStatement_end();
+    if (finallyBlock != null) {
+      flow.tryFinallyStatement_finallyBegin(assignedVariables[body]);
+      finallyBlock.accept(this);
+      flow.tryFinallyStatement_end(assignedVariables[finallyBlock]);
+    }
   }
 
   @override
@@ -3023,7 +3488,7 @@
     var condition = node.condition;
     var body = node.body;
 
-    flow.whileStatement_conditionBegin(loopAssignedVariables[node]);
+    flow.whileStatement_conditionBegin(assignedVariables[node]);
     condition.accept(this);
 
     flow.whileStatement_bodyBegin(node);
@@ -3084,117 +3549,33 @@
     return node is BooleanLiteral && !node.value;
   }
 
+  static bool _isNonNull(Expression node) {
+    if (node is NullLiteral) return false;
+
+    return node is Literal;
+  }
+
+  static bool _isNull(Expression node) {
+    return node is NullLiteral;
+  }
+
   static bool _isTrueLiteral(AstNode node) {
     return node is BooleanLiteral && node.value;
   }
 }
 
-class _LoopAssignedVariablesVisitor extends RecursiveAstVisitor<void> {
-  final LoopAssignedVariables loopAssignedVariables;
+class _TypeSystemTypeOperations implements TypeOperations<DartType> {
+  final TypeSystem typeSystem;
 
-  _LoopAssignedVariablesVisitor(this.loopAssignedVariables);
+  _TypeSystemTypeOperations(this.typeSystem);
 
   @override
-  void visitAssignmentExpression(AssignmentExpression node) {
-    var left = node.leftHandSide;
-
-    super.visitAssignmentExpression(node);
-
-    if (left is SimpleIdentifier) {
-      var element = left.staticElement;
-      if (element is VariableElement) {
-        loopAssignedVariables.write(element);
-      }
-    }
+  DartType elementType(VariableElement element) {
+    return element.type;
   }
 
   @override
-  void visitDoStatement(DoStatement node) {
-    loopAssignedVariables.beginLoop();
-    super.visitDoStatement(node);
-    loopAssignedVariables.endLoop(node);
-  }
-
-  @override
-  void visitForEachStatement(ForEachStatement node) {
-    var iterable = node.iterable;
-    var body = node.body;
-
-    iterable.accept(this);
-
-    loopAssignedVariables.beginLoop();
-    body.accept(this);
-    loopAssignedVariables.endLoop(node);
-  }
-
-  @override
-  void visitForStatement(ForStatement node) {
-    node.initialization?.accept(this);
-    node.variables?.accept(this);
-
-    loopAssignedVariables.beginLoop();
-    node.condition?.accept(this);
-    node.body.accept(this);
-    node.updaters?.accept(this);
-    loopAssignedVariables.endLoop(node);
-  }
-
-  @override
-  void visitForStatement2(ForStatement2 node) {
-    ForLoopParts parts = node.forLoopParts;
-    Expression initialization;
-    VariableDeclarationList variables;
-    Expression iterable;
-    Expression condition;
-    NodeList<Expression> updaters;
-    if (parts is ForPartsWithDeclarations) {
-      variables = parts.variables;
-      condition = parts.condition;
-      updaters = parts.updaters;
-    } else if (parts is ForPartsWithExpression) {
-      initialization = parts.initialization;
-      condition = parts.condition;
-      updaters = parts.updaters;
-    } else if (parts is ForEachParts) {
-      iterable = parts.iterable;
-    }
-    initialization?.accept(this);
-    variables?.accept(this);
-    iterable?.accept(this);
-
-    loopAssignedVariables.beginLoop();
-    condition?.accept(this);
-    node.body.accept(this);
-    updaters?.accept(this);
-    loopAssignedVariables.endLoop(node);
-  }
-
-  @override
-  void visitSwitchStatement(SwitchStatement node) {
-    var expression = node.expression;
-    var members = node.members;
-
-    expression.accept(this);
-
-    loopAssignedVariables.beginLoop();
-    members.accept(this);
-    loopAssignedVariables.endLoop(node);
-  }
-
-  @override
-  void visitTryStatement(TryStatement node) {
-    loopAssignedVariables.beginLoop();
-    node.body.accept(this);
-    loopAssignedVariables.endLoop(node.body);
-
-    node.catchClauses.accept(this);
-    node.finallyBlock?.accept(this);
-  }
-
-  @override
-  void visitWhileStatement(WhileStatement node) {
-    loopAssignedVariables.beginLoop();
-    super.visitWhileStatement(node);
-    loopAssignedVariables.endLoop(node);
+  bool isSubtypeOf(DartType leftType, DartType rightType) {
+    return typeSystem.isSubtypeOf(leftType, rightType);
   }
 }
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 f25fe19..2af994d 100644
--- a/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
+++ b/pkg/analyzer/test/src/dart/resolution/method_invocation_test.dart
@@ -5,7 +5,6 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/error/codes.dart';
-import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import 'driver_resolution.dart';
@@ -468,7 +467,7 @@
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
 
-    var import = _importFinder('package:test/a.dart');
+    var import = findElement.importFind('package:test/a.dart');
 
     var invocation = findNode.methodInvocation('foo();');
     assertMethodInvocation(
@@ -492,7 +491,7 @@
       CompileTimeErrorCode.PREFIX_IDENTIFIER_NOT_FOLLOWED_BY_DOT,
     ]);
 
-    var import = _importFinder('dart:math');
+    var import = findElement.importFind('dart:math');
 
     var invocation = findNode.methodInvocation('loadLibrary()');
     assertMethodInvocation(
@@ -1076,7 +1075,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    var import = _importFinder('dart:math');
+    var import = findElement.importFind('dart:math');
 
     var invocation = findNode.methodInvocation('loadLibrary()');
     assertMethodInvocation(
@@ -1123,7 +1122,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    var import = _importFinder('package:test/a.dart');
+    var import = findElement.importFind('package:test/a.dart');
 
     var invocation = findNode.methodInvocation('foo(1, 2)');
     assertMethodInvocation(
@@ -1149,7 +1148,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    var import = _importFinder('package:test/a.dart');
+    var import = findElement.importFind('package:test/a.dart');
 
     var invocation = findNode.methodInvocation('foo(1, 2)');
     assertMethodInvocation(
@@ -1328,7 +1327,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    var import = _importFinder('package:test/a.dart');
+    var import = findElement.importFind('package:test/a.dart');
 
     var invocation = findNode.methodInvocation('foo(0)');
     assertMethodInvocation(
@@ -1360,7 +1359,7 @@
     await resolveTestFile();
     assertNoTestErrors();
 
-    var import = _importFinder('package:test/a.dart');
+    var import = findElement.importFind('package:test/a.dart');
 
     var invocation = findNode.methodInvocation('foo(0)');
     assertMethodInvocation(
@@ -1751,50 +1750,4 @@
 //      expectedType: 'dynamic',
 //    );
   }
-
-  _ImportElementFinder _importFinder(String targetUri) {
-    var import = findElement.import(targetUri);
-    return _ImportElementFinder(import);
-  }
-}
-
-class _ImportElementFinder {
-  final ImportElement import;
-
-  _ImportElementFinder(this.import);
-
-  CompilationUnitElement get definingUnit {
-    return importedLibrary.definingCompilationUnit;
-  }
-
-  LibraryElement get importedLibrary => import.importedLibrary;
-
-  PrefixElement get prefix => import.prefix;
-
-  ClassElement class_(String name) {
-    for (var class_ in definingUnit.types) {
-      if (class_.name == name) {
-        return class_;
-      }
-    }
-    fail('Not found class: $name');
-  }
-
-  FunctionElement topFunction(String name) {
-    for (var function in definingUnit.functions) {
-      if (function.name == name) {
-        return function;
-      }
-    }
-    fail('Not found top-level function: $name');
-  }
-
-  PropertyAccessorElement topGetter(String name) {
-    for (var accessor in definingUnit.accessors) {
-      if (accessor.name == name && accessor.isGetter) {
-        return accessor;
-      }
-    }
-    fail('Not found top-level getter: $name');
-  }
 }
diff --git a/pkg/analyzer/test/src/dart/resolution/resolution.dart b/pkg/analyzer/test/src/dart/resolution/resolution.dart
index efd7d8e..be8eb31 100644
--- a/pkg/analyzer/test/src/dart/resolution/resolution.dart
+++ b/pkg/analyzer/test/src/dart/resolution/resolution.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/dart/element/type.dart';
@@ -14,12 +15,12 @@
 import 'package:analyzer/src/dart/element/type.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/resolver.dart' show TypeProvider;
+import 'package:analyzer/src/test_utilities/find_element.dart';
+import 'package:analyzer/src/test_utilities/find_node.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:test/test.dart';
 
 import '../../../generated/test_support.dart';
-import 'find_element.dart';
-import 'find_node.dart';
 
 final isBottomType = new TypeMatcher<BottomTypeImpl>();
 
@@ -31,7 +32,7 @@
 
 /// Base for resolution tests.
 mixin ResolutionTest implements ResourceProviderMixin {
-  TestAnalysisResult result;
+  ResolvedUnitResult result;
   FindNode findNode;
   FindElement findElement;
 
@@ -143,6 +144,10 @@
     expect(element.enclosingElement, expectedEnclosing);
   }
 
+  bool get enableUnusedLocalVariable => false;
+
+  bool get enableUnusedElement => false;
+
   /**
    * Assert that the number of error codes in reported [errors] matches the
    * number of [expected] error codes. The order of errors is ignored.
@@ -152,11 +157,15 @@
     var errorListener = new GatheringErrorListener();
     for (AnalysisError error in result.errors) {
       ErrorCode errorCode = error.errorCode;
-      if (errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
-          errorCode == HintCode.UNUSED_CATCH_STACK ||
-          errorCode == HintCode.UNUSED_ELEMENT ||
-          errorCode == HintCode.UNUSED_FIELD ||
-          errorCode == HintCode.UNUSED_LOCAL_VARIABLE) {
+      if (!enableUnusedElement &&
+          (errorCode == HintCode.UNUSED_ELEMENT ||
+              errorCode == HintCode.UNUSED_FIELD)) {
+        continue;
+      }
+      if (!enableUnusedLocalVariable &&
+          (errorCode == HintCode.UNUSED_CATCH_CLAUSE ||
+              errorCode == HintCode.UNUSED_CATCH_STACK ||
+              errorCode == HintCode.UNUSED_LOCAL_VARIABLE)) {
         continue;
       }
       errorListener.onError(error);
@@ -164,6 +173,12 @@
     errorListener.assertErrorsWithCodes(expected);
   }
 
+  Future<void> assertErrorsInCode(String code, List<ErrorCode> errors) async {
+    addTestFile(code);
+    await resolveTestFile();
+    assertTestErrors(errors);
+  }
+
   void assertHasTestErrors() {
     expect(result.errors, isNotEmpty);
   }
@@ -295,6 +310,12 @@
     assertTypeNull(ref);
   }
 
+  Future<void> assertNoErrorsInCode(String code) async {
+    addTestFile(code);
+    await resolveTestFile();
+    assertNoTestErrors();
+  }
+
   void assertNoTestErrors() {
     assertTestErrors(const <ErrorCode>[]);
   }
@@ -397,7 +418,7 @@
     }
   }
 
-  Future<TestAnalysisResult> resolveFile(String path);
+  Future<ResolvedUnitResult> resolveFile(String path);
 
   Future<void> resolveTestFile() async {
     var path = convertPath('/test/lib/test.dart');
@@ -419,12 +440,3 @@
     return invokeType.substring(arrowIndex + 1).trim();
   }
 }
-
-class TestAnalysisResult {
-  final String path;
-  final String content;
-  final CompilationUnit unit;
-  final List<AnalysisError> errors;
-
-  TestAnalysisResult(this.path, this.content, this.unit, this.errors);
-}
diff --git a/pkg/analyzer/test/src/dart/resolution/task_resolution.dart b/pkg/analyzer/test/src/dart/resolution/task_resolution.dart
deleted file mode 100644
index 7c84ed2..0000000
--- a/pkg/analyzer/test/src/dart/resolution/task_resolution.dart
+++ /dev/null
@@ -1,56 +0,0 @@
-// Copyright (c) 2018, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'dart:async';
-
-import 'package:analyzer/file_system/file_system.dart';
-import 'package:analyzer/src/generated/engine.dart';
-import 'package:analyzer/src/generated/sdk.dart';
-import 'package:analyzer/src/generated/source.dart';
-import 'package:analyzer/src/source/package_map_resolver.dart';
-import 'package:analyzer/src/test_utilities/mock_sdk.dart';
-import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
-
-import '../../../generated/analysis_context_factory.dart';
-import 'resolution.dart';
-
-/// Task model based implementation of [ResolutionTest].
-class TaskResolutionTest with ResourceProviderMixin, ResolutionTest {
-  DartSdk sdk;
-
-  SourceFactory sourceFactory;
-  InternalAnalysisContext analysisContext;
-
-  @override
-  Future<TestAnalysisResult> resolveFile(String path) async {
-    var file = resourceProvider.getFile(path);
-    var content = file.readAsStringSync();
-    var source = file.createSource(Uri.parse('package:test/test.dart'));
-
-    analysisContext.computeKindOf(source);
-    List<Source> libraries = analysisContext.getLibrariesContaining(source);
-    Source library = libraries.first;
-
-    var unit = analysisContext.resolveCompilationUnit2(source, library);
-    var errors = analysisContext.computeErrors(source);
-
-    return new TestAnalysisResult(path, content, unit, errors);
-  }
-
-  void setUp() {
-    sdk = new MockSdk(resourceProvider: resourceProvider);
-
-    Map<String, List<Folder>> packageMap = <String, List<Folder>>{
-      'test': [getFolder('/test/lib')],
-      'aaa': [getFolder('/aaa/lib')],
-      'bbb': [getFolder('/bbb/lib')],
-    };
-
-    analysisContext = AnalysisContextFactory.contextWithCore(
-      contributedResolver:
-          new PackageMapUriResolver(resourceProvider, packageMap),
-      resourceProvider: resourceProvider,
-    );
-  }
-}
diff --git a/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
new file mode 100644
index 0000000..6a313d0
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolver/exit_detector_test.dart
@@ -0,0 +1,1118 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/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';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../ast/parse_base.dart';
+import '../resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ExitDetectorParsedStatementTest);
+    defineReflectiveTests(ExitDetectorResolvedStatementTest);
+    defineReflectiveTests(ExitDetectorForCodeAsUiTest);
+  });
+}
+
+/// Tests for the [ExitDetector] that require that the control flow and spread
+/// 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]');
+  }
+
+  test_for_implicitTrue() async {
+    _assertTrue('[for (;;) 0]');
+  }
+
+  test_for_initialization() async {
+    _assertTrue('[for (i = throw 0;;) 0]');
+  }
+
+  test_for_true() async {
+    _assertTrue('[for (; true; ) 0]');
+  }
+
+  test_for_true_if_return() async {
+    _assertTrue('[for (; true; ) if (true) throw 42]');
+  }
+
+  test_for_true_noBreak() async {
+    _assertTrue('[for (; true; ) 0]');
+  }
+
+  test_for_updaters() async {
+    _assertTrue('[for (;; i++, throw 0) 1]');
+  }
+
+  test_for_variableDeclaration() async {
+    _assertTrue('[for (int i = throw 0;;) 1]');
+  }
+
+  test_forEach() async {
+    _assertFalse('[for (element in list) 0]');
+  }
+
+  test_forEach_throw() async {
+    _assertTrue('[for (element in throw 42) 0]');
+  }
+
+  test_if_false_else_throw() async {
+    _assertTrue('[if (false) 0 else throw 42]');
+  }
+
+  test_if_false_noThrow() async {
+    _assertFalse('[if (false) 0]');
+  }
+
+  test_if_false_throw() async {
+    _assertFalse('[if (false) throw 42]');
+  }
+
+  test_if_noThrow() async {
+    _assertFalse('[if (c) i++]');
+  }
+
+  test_if_throw() async {
+    _assertFalse('[if (c) throw 42]');
+  }
+
+  test_if_true_noThrow() async {
+    _assertFalse('[if (true) 0]');
+  }
+
+  test_if_true_throw() async {
+    _assertTrue('[if (true) throw 42]');
+  }
+
+  test_ifElse_bothThrow() async {
+    _assertTrue("[if (c) throw 0 else throw 1]");
+  }
+
+  test_ifElse_elseThrow() async {
+    _assertFalse('[if (c) 0 else throw 42]');
+  }
+
+  test_ifElse_noThrow() async {
+    _assertFalse('[if (c) 0 else 1]');
+  }
+
+  test_ifElse_thenThrow() async {
+    _assertFalse('[if (c) throw 42 else 0]');
+  }
+
+  void _assertFalse(String expressionCode) {
+    _assertHasReturn(expressionCode, false);
+  }
+
+  void _assertHasReturn(String expressionCode, bool expected) {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: '''
+void f() { // ref
+  $expressionCode;
+}
+''');
+
+    var parseResult = parseUnit(path);
+    expect(parseResult.errors, isEmpty);
+
+    var findNode = FindNode(parseResult.content, parseResult.unit);
+
+    var block = findNode.block('{ // ref');
+    var statement = block.statements.single as ExpressionStatement;
+    var expression = statement.expression;
+
+    var actual = ExitDetector.exits(expression);
+    expect(actual, expected);
+  }
+
+  void _assertTrue(String expressionCode) {
+    _assertHasReturn(expressionCode, true);
+  }
+}
+
+/// Tests for the [ExitDetector] that do not require that the AST be resolved.
+///
+/// See [ExitDetectorResolvedStatementTest] for tests that require the AST to be resolved.
+@reflectiveTest
+class ExitDetectorParsedStatementTest extends ParseBase {
+  test_asExpression() async {
+    _assertFalse('a as Object;');
+  }
+
+  test_asExpression_throw() async {
+    _assertTrue('throw 42 as Object;');
+  }
+
+  test_assertStatement() async {
+    _assertFalse("assert(a);");
+  }
+
+  test_assertStatement_throw() async {
+    _assertFalse('assert((throw 0));');
+  }
+
+  test_assignmentExpression() async {
+    _assertFalse('v = 1;');
+  }
+
+  @failingTest
+  test_assignmentExpression_compound_lazy() async {
+    _assertFalse('v ||= false;');
+  }
+
+  test_assignmentExpression_lhs_throw() async {
+    _assertTrue('a[throw 42] = 0;');
+  }
+
+  test_assignmentExpression_rhs_throw() async {
+    _assertTrue('v = throw 42;');
+  }
+
+  test_await_false() async {
+    _assertFalse('await x;');
+  }
+
+  test_await_throw_true() async {
+    _assertTrue('bool b = await (throw 42 || true);');
+  }
+
+  test_binaryExpression_and() async {
+    _assertFalse('a && b;');
+  }
+
+  test_binaryExpression_and_lhs() async {
+    _assertTrue('throw 42 && b;');
+  }
+
+  test_binaryExpression_and_rhs() async {
+    _assertFalse('a && (throw 42);');
+  }
+
+  test_binaryExpression_and_rhs2() async {
+    _assertFalse('false && (throw 42);');
+  }
+
+  test_binaryExpression_and_rhs3() async {
+    _assertTrue('true && (throw 42);');
+  }
+
+  test_binaryExpression_ifNull() async {
+    _assertFalse('a ?? b;');
+  }
+
+  test_binaryExpression_ifNull_lhs() async {
+    _assertTrue('throw 42 ?? b;');
+  }
+
+  test_binaryExpression_ifNull_rhs() async {
+    _assertFalse('a ?? (throw 42);');
+  }
+
+  test_binaryExpression_ifNull_rhs2() async {
+    _assertFalse('null ?? (throw 42);');
+  }
+
+  test_binaryExpression_or() async {
+    _assertFalse('a || b;');
+  }
+
+  test_binaryExpression_or_lhs() async {
+    _assertTrue('throw 42 || b;');
+  }
+
+  test_binaryExpression_or_rhs() async {
+    _assertFalse('a || (throw 42);');
+  }
+
+  test_binaryExpression_or_rhs2() async {
+    _assertFalse('true || (throw 42);');
+  }
+
+  test_binaryExpression_or_rhs3() async {
+    _assertTrue('false || (throw 42);');
+  }
+
+  test_block_empty() async {
+    _assertFalse('{}');
+  }
+
+  test_block_noReturn() async {
+    _assertFalse('{ int i = 0; }');
+  }
+
+  test_block_return() async {
+    _assertTrue('{ return 0; }');
+  }
+
+  test_block_returnNotLast() async {
+    _assertTrue('{ return 0; throw 42; }');
+  }
+
+  test_block_throwNotLast() async {
+    _assertTrue('{ throw 0; x = null; }');
+  }
+
+  test_cascadeExpression_argument() async {
+    _assertTrue('a..b(throw 42);');
+  }
+
+  test_cascadeExpression_index() async {
+    _assertTrue('a..[throw 42];');
+  }
+
+  test_cascadeExpression_target() async {
+    _assertTrue('throw a..b();');
+  }
+
+  test_conditional_ifElse_bothThrows() async {
+    _assertTrue('c ? throw 42 : throw 42;');
+  }
+
+  test_conditional_ifElse_elseThrows() async {
+    _assertFalse('c ? i : throw 42;');
+  }
+
+  test_conditional_ifElse_noThrow() async {
+    _assertFalse('c ? i : j;');
+  }
+
+  test_conditional_ifElse_thenThrow() async {
+    _assertFalse('c ? throw 42 : j;');
+  }
+
+  test_conditionalAccess() async {
+    _assertFalse('a?.b;');
+  }
+
+  test_conditionalAccess_lhs() async {
+    _assertTrue('(throw 42)?.b;');
+  }
+
+  test_conditionalAccessAssign() async {
+    _assertFalse('a?.b = c;');
+  }
+
+  test_conditionalAccessAssign_lhs() async {
+    _assertTrue('(throw 42)?.b = c;');
+  }
+
+  test_conditionalAccessAssign_rhs() async {
+    _assertFalse('a?.b = throw 42;');
+  }
+
+  test_conditionalAccessAssign_rhs2() async {
+    _assertFalse("null?.b = throw 42;");
+  }
+
+  test_conditionalAccessIfNullAssign() async {
+    _assertFalse('a?.b ??= c;');
+  }
+
+  test_conditionalAccessIfNullAssign_lhs() async {
+    _assertTrue('(throw 42)?.b ??= c;');
+  }
+
+  test_conditionalAccessIfNullAssign_rhs() async {
+    _assertFalse('a?.b ??= throw 42;');
+  }
+
+  test_conditionalAccessIfNullAssign_rhs2() async {
+    _assertFalse('null?.b ??= throw 42;');
+  }
+
+  test_conditionalCall() async {
+    _assertFalse('a?.b(c);');
+  }
+
+  test_conditionalCall_lhs() async {
+    _assertTrue('(throw 42)?.b(c);');
+  }
+
+  test_conditionalCall_rhs() async {
+    _assertFalse('a?.b(throw 42);');
+  }
+
+  test_conditionalCall_rhs2() async {
+    _assertFalse('null?.b(throw 42);');
+  }
+
+  test_doStatement_break_and_throw() async {
+    _assertFalse('''
+{
+  do {
+    if (1 == 1) break;
+    throw 42;
+  } while (0 == 1);
+}
+''');
+  }
+
+  test_doStatement_continue_and_throw() async {
+    _assertFalse('''
+{
+  do {
+    if (1 == 1) continue;
+    throw 42;
+  } while (0 == 1);
+}
+''');
+  }
+
+  test_doStatement_continueDoInSwitch_and_throw() async {
+    _assertFalse('''
+{
+  D: do {
+    switch (1) {
+      L: case 0: continue D;
+      M: case 1: break;
+    }
+    throw 42;
+  } while (0 == 1);
+}''');
+  }
+
+  test_doStatement_continueInSwitch_and_throw() async {
+    _assertFalse('''
+{
+  do {
+    switch (1) {
+      L: case 0: continue;
+      M: case 1: break;
+    }
+    throw 42;
+  } while (0 == 1);
+}''');
+  }
+
+  test_doStatement_return() async {
+    _assertTrue('{ do { return null; } while (1 == 2); }');
+  }
+
+  test_doStatement_throwCondition() async {
+    _assertTrue('{ do {} while (throw 42); }');
+  }
+
+  test_doStatement_true_break() async {
+    _assertFalse('{ do { break; } while (true); }');
+  }
+
+  test_doStatement_true_continue() async {
+    _assertTrue('{ do { continue; } while (true); }');
+  }
+
+  test_doStatement_true_continueWithLabel() async {
+    _assertTrue('{ x: do { continue x; } while (true); }');
+  }
+
+  test_doStatement_true_if_return() async {
+    _assertTrue('{ do { if (true) {return null;} } while (true); }');
+  }
+
+  test_doStatement_true_noBreak() async {
+    _assertTrue('{ do {} while (true); }');
+  }
+
+  test_doStatement_true_return() async {
+    _assertTrue('{ do { return null; } while (true);  }');
+  }
+
+  test_emptyStatement() async {
+    _assertFalse(';');
+  }
+
+  test_forEachStatement() async {
+    _assertFalse('for (element in list) {}');
+  }
+
+  test_forEachStatement_throw() async {
+    _assertTrue('for (element in throw 42) {}');
+  }
+
+  test_forStatement_condition() async {
+    _assertTrue('for (; throw 0;) {}');
+  }
+
+  test_forStatement_implicitTrue() async {
+    _assertTrue('for (;;) {}');
+  }
+
+  test_forStatement_implicitTrue_break() async {
+    _assertFalse('for (;;) { break; }');
+  }
+
+  test_forStatement_implicitTrue_if_break() async {
+    _assertFalse('''
+{
+  for (;;) {
+    if (1==2) {
+      var a = 1;
+    } else {
+      break;
+    }
+  }
+}
+''');
+  }
+
+  test_forStatement_initialization() async {
+    _assertTrue('for (i = throw 0;;) {}');
+  }
+
+  test_forStatement_true() async {
+    _assertTrue('for (; true; ) {}');
+  }
+
+  test_forStatement_true_break() async {
+    _assertFalse('{ for (; true; ) { break; } }');
+  }
+
+  test_forStatement_true_continue() async {
+    _assertTrue('{ for (; true; ) { continue; } }');
+  }
+
+  test_forStatement_true_if_return() async {
+    _assertTrue('{ for (; true; ) { if (true) {return null;} } }');
+  }
+
+  test_forStatement_true_noBreak() async {
+    _assertTrue('{ for (; true; ) {} }');
+  }
+
+  test_forStatement_updaters() async {
+    _assertTrue('for (;; i++, throw 0) {}');
+  }
+
+  test_forStatement_variableDeclaration() async {
+    _assertTrue('for (int i = throw 0;;) {}');
+  }
+
+  test_functionExpression() async {
+    _assertFalse('(){};');
+  }
+
+  test_functionExpression_bodyThrows() async {
+    _assertFalse('(int i) => throw 42;');
+  }
+
+  test_functionExpressionInvocation() async {
+    _assertFalse('f(g);');
+  }
+
+  test_functionExpressionInvocation_argumentThrows() async {
+    _assertTrue('f(throw 42);');
+  }
+
+  test_functionExpressionInvocation_targetThrows() async {
+    _assertTrue("(throw 42)(g);");
+  }
+
+  test_identifier_prefixedIdentifier() async {
+    _assertFalse('a.b;');
+  }
+
+  test_identifier_simpleIdentifier() async {
+    _assertFalse('a;');
+  }
+
+  test_if_false_else_return() async {
+    _assertTrue('if (false) {} else { return 0; }');
+  }
+
+  test_if_false_noReturn() async {
+    _assertFalse('if (false) {}');
+  }
+
+  test_if_false_return() async {
+    _assertFalse('if (false) { return 0; }');
+  }
+
+  test_if_noReturn() async {
+    _assertFalse('if (c) i++;');
+  }
+
+  test_if_return() async {
+    _assertFalse('if (c) return 0;');
+  }
+
+  test_if_true_noReturn() async {
+    _assertFalse('if (true) {}');
+  }
+
+  test_if_true_return() async {
+    _assertTrue('if (true) { return 0; }');
+  }
+
+  test_ifElse_bothReturn() async {
+    _assertTrue('if (c) return 0; else return 1;');
+  }
+
+  test_ifElse_elseReturn() async {
+    _assertFalse('if (c) i++; else return 1;');
+  }
+
+  test_ifElse_noReturn() async {
+    _assertFalse('if (c) i++; else j++;');
+  }
+
+  test_ifElse_thenReturn() async {
+    _assertFalse('if (c) return 0; else j++;');
+  }
+
+  test_ifNullAssign() async {
+    _assertFalse('a ??= b;');
+  }
+
+  test_ifNullAssign_rhs() async {
+    _assertFalse('a ??= throw 42;');
+  }
+
+  test_indexExpression() async {
+    _assertFalse('a[b];');
+  }
+
+  test_indexExpression_index() async {
+    _assertTrue('a[throw 42];');
+  }
+
+  test_indexExpression_target() async {
+    _assertTrue("(throw 42)[b];");
+  }
+
+  test_instanceCreationExpression() async {
+    _assertFalse('new A(b);');
+  }
+
+  test_instanceCreationExpression_argumentThrows() async {
+    _assertTrue('new A(throw 42);');
+  }
+
+  test_isExpression() async {
+    _assertFalse('A is B;');
+  }
+
+  test_isExpression_throws() async {
+    _assertTrue('throw 42 is B;');
+  }
+
+  test_labeledStatement() async {
+    _assertFalse('label: a;');
+  }
+
+  test_labeledStatement_throws() async {
+    _assertTrue('label: throw 42;');
+  }
+
+  test_literal_boolean() async {
+    _assertFalse('true;');
+  }
+
+  test_literal_double() async {
+    _assertFalse('1.1;');
+  }
+
+  test_literal_integer() async {
+    _assertFalse('1;');
+  }
+
+  test_literal_null() async {
+    _assertFalse('null;');
+  }
+
+  test_literal_String() async {
+    _assertFalse('"str";');
+  }
+
+  test_methodInvocation() async {
+    _assertFalse('a.b(c);');
+  }
+
+  test_methodInvocation_argument() async {
+    _assertTrue('a.b(throw 42);');
+  }
+
+  test_methodInvocation_target() async {
+    _assertTrue("(throw 42).b(c);");
+  }
+
+  test_parenthesizedExpression() async {
+    _assertFalse('(a);');
+  }
+
+  test_parenthesizedExpression_throw() async {
+    _assertTrue('(throw 42);');
+  }
+
+  test_propertyAccess() async {
+    _assertFalse('new Object().a;');
+  }
+
+  test_propertyAccess_throws() async {
+    _assertTrue('(throw 42).a;');
+  }
+
+  test_rethrow() async {
+    _assertTrue('rethrow;');
+  }
+
+  test_return() async {
+    _assertTrue('return 0;');
+  }
+
+  test_superExpression() async {
+    _assertFalse('super.a;');
+  }
+
+  test_switch_allReturn() async {
+    _assertTrue('switch (i) { case 0: return 0; default: return 1; }');
+  }
+
+  test_switch_defaultWithNoStatements() async {
+    _assertFalse('switch (i) { case 0: return 0; default: }');
+  }
+
+  test_switch_fallThroughToNotReturn() async {
+    _assertFalse(r'''
+switch (i) {
+  case 0:
+  case 1:
+    break;
+  default:
+    return 1;
+}
+''');
+  }
+
+  test_switch_fallThroughToReturn() async {
+    _assertTrue(r'''
+switch (i) {
+  case 0:
+  case 1:
+    return 0;
+  default:
+    return 1;
+}
+''');
+  }
+
+  @failingTest
+  test_switch_includesContinue() async {
+    _assertTrue('''
+switch (i) {
+  zero: case 0: return 0;
+  case 1: continue zero;
+  default: return 1;
+}''');
+  }
+
+  test_switch_noDefault() async {
+    _assertFalse('switch (i) { case 0: return 0; }');
+  }
+
+  // The ExitDetector could conceivably follow switch continue labels and
+  // determine that `case 0` exits, `case 1` continues to an exiting case, and
+  // `default` exits, so the switch exits.
+  test_switch_nonReturn() async {
+    _assertFalse('switch (i) { case 0: i++; default: return 1; }');
+  }
+
+  test_thisExpression() async {
+    _assertFalse('this.a;');
+  }
+
+  test_throwExpression() async {
+    _assertTrue('throw new Object();');
+  }
+
+  test_tryStatement_noReturn() async {
+    _assertFalse('try {} catch (e, s) {} finally {}');
+  }
+
+  test_tryStatement_noReturn_noFinally() async {
+    _assertFalse('try {} catch (e, s) {}');
+  }
+
+  test_tryStatement_return_catch() async {
+    _assertFalse('try {} catch (e, s) { return 1; } finally {}');
+  }
+
+  test_tryStatement_return_catch_noFinally() async {
+    _assertFalse('try {} catch (e, s) { return 1; }');
+  }
+
+  test_tryStatement_return_finally() async {
+    _assertTrue('try {} catch (e, s) {} finally { return 1; }');
+  }
+
+  test_tryStatement_return_try_noCatch() async {
+    _assertTrue('try { return 1; } finally {}');
+  }
+
+  test_tryStatement_return_try_oneCatchDoesNotExit() async {
+    _assertFalse('try { return 1; } catch (e, s) {} finally {}');
+  }
+
+  test_tryStatement_return_try_oneCatchDoesNotExit_noFinally() async {
+    _assertFalse('try { return 1; } catch (e, s) {}');
+  }
+
+  test_tryStatement_return_try_oneCatchExits() async {
+    _assertTrue('''
+try {
+  return 1;
+} catch (e, s) {
+  return 1;
+} finally {}
+''');
+  }
+
+  test_tryStatement_return_try_oneCatchExits_noFinally() async {
+    _assertTrue('try { return 1; } catch (e, s) { return 1; }');
+  }
+
+  test_tryStatement_return_try_twoCatchesDoExit() async {
+    _assertTrue('''
+try { return 1; }
+on int catch (e, s) { return 1; }
+on String catch (e, s) { return 1; }
+finally {}
+''');
+  }
+
+  test_tryStatement_return_try_twoCatchesDoExit_noFinally() async {
+    _assertTrue('''
+try { return 1; }
+on int catch (e, s) { return 1; }
+on String catch (e, s) { return 1; }
+''');
+  }
+
+  test_tryStatement_return_try_twoCatchesDoNotExit() async {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) {}
+finally {}
+''');
+  }
+
+  test_tryStatement_return_try_twoCatchesDoNotExit_noFinally() async {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) {}
+''');
+  }
+
+  test_tryStatement_return_try_twoCatchesMixed() async {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) { return 1; }
+finally {}
+''');
+  }
+
+  test_tryStatement_return_try_twoCatchesMixed_noFinally() async {
+    _assertFalse('''
+try { return 1; }
+on int catch (e, s) {}
+on String catch (e, s) { return 1; }
+''');
+  }
+
+  test_variableDeclarationStatement_noInitializer() async {
+    _assertFalse('int i;');
+  }
+
+  test_variableDeclarationStatement_noThrow() async {
+    _assertFalse('int i = 0;');
+  }
+
+  test_variableDeclarationStatement_throw() async {
+    _assertTrue('int i = throw new Object();');
+  }
+
+  test_whileStatement_false_nonReturn() async {
+    _assertFalse("{ while (false) {} }");
+  }
+
+  test_whileStatement_throwCondition() async {
+    _assertTrue('{ while (throw 42) {} }');
+  }
+
+  test_whileStatement_true_break() async {
+    _assertFalse('{ while (true) { break; } }');
+  }
+
+  test_whileStatement_true_break_and_throw() async {
+    _assertFalse('{ while (true) { if (1==1) break; throw 42; } }');
+  }
+
+  test_whileStatement_true_continue() async {
+    _assertTrue('{ while (true) { continue; } }');
+  }
+
+  test_whileStatement_true_continueWithLabel() async {
+    _assertTrue('{ x: while (true) { continue x; } }');
+  }
+
+  test_whileStatement_true_doStatement_scopeRequired() async {
+    _assertTrue('{ while (true) { x: do { continue x; } while (true); } }');
+  }
+
+  test_whileStatement_true_if_return() async {
+    _assertTrue('{ while (true) { if (true) {return null;} } }');
+  }
+
+  test_whileStatement_true_noBreak() async {
+    _assertTrue('{ while (true) {} }');
+  }
+
+  test_whileStatement_true_return() async {
+    _assertTrue('{ while (true) { return null; } }');
+  }
+
+  test_whileStatement_true_throw() async {
+    _assertTrue('{ while (true) { throw 42; } }');
+  }
+
+  void _assertFalse(String code) {
+    _assertHasReturn(code, false);
+  }
+
+  void _assertHasReturn(String statementCode, bool expected) {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: '''
+void f() { // ref
+  $statementCode
+}
+''');
+
+    var parseResult = parseUnit(path);
+    expect(parseResult.errors, isEmpty);
+
+    var findNode = FindNode(parseResult.content, parseResult.unit);
+
+    var block = findNode.block('{ // ref');
+    var statement = block.statements.single;
+
+    var actual = ExitDetector.exits(statement);
+    expect(actual, expected);
+  }
+
+  void _assertTrue(String code) {
+    _assertHasReturn(code, true);
+  }
+}
+
+/// Tests for the [ExitDetector] that require that the AST be resolved.
+///
+/// See [ExitDetectorParsedStatementTest] for tests that do not require the AST to be resolved.
+/// TODO(paulberry): migrate this test away from the task model.
+/// See dartbug.com/35734.
+@reflectiveTest
+class ExitDetectorResolvedStatementTest extends DriverResolutionTest {
+  test_forStatement_implicitTrue_breakWithLabel() async {
+    await _assertNthStatementDoesNotExit(r'''
+void f() {
+  x: for (;;) {
+    if (1 < 2) {
+      break x;
+    }
+    return;
+  }
+}
+''', 0);
+  }
+
+  test_switch_withEnum_false_noDefault() async {
+    await _assertNthStatementDoesNotExit(r'''
+enum E { A, B }
+String f(E e) {
+  var x;
+  switch (e) {
+    case A:
+      x = 'A';
+    case B:
+      x = 'B';
+  }
+  return x;
+}
+''', 1);
+  }
+
+  test_switch_withEnum_false_withDefault() async {
+    await _assertNthStatementDoesNotExit(r'''
+enum E { A, B }
+String f(E e) {
+  var x;
+  switch (e) {
+    case A:
+      x = 'A';
+    default:
+      x = '?';
+  }
+  return x;
+}
+''', 1);
+  }
+
+  test_switch_withEnum_true_noDefault() async {
+    await _assertNthStatementDoesNotExit(r'''
+enum E { A, B }
+String f(E e) {
+  switch (e) {
+    case A:
+      return 'A';
+    case B:
+      return 'B';
+  }
+}
+''', 0);
+  }
+
+  test_switch_withEnum_true_withExitingDefault() async {
+    await _assertNthStatementExits(r'''
+enum E { A, B }
+String f(E e) {
+  switch (e) {
+    case A:
+      return 'A';
+    default:
+      return '?';
+  }
+}
+''', 0);
+  }
+
+  test_switch_withEnum_true_withNonExitingDefault() async {
+    await _assertNthStatementDoesNotExit(r'''
+enum E { A, B }
+String f(E e) {
+  var x;
+  switch (e) {
+    case A:
+      return 'A';
+    default:
+      x = '?';
+  }
+}
+''', 1);
+  }
+
+  test_whileStatement_breakWithLabel() async {
+    await _assertNthStatementDoesNotExit(r'''
+void f() {
+  x: while (true) {
+    if (1 < 2) {
+      break x;
+    }
+    return;
+  }
+}
+''', 0);
+  }
+
+  test_whileStatement_breakWithLabel_afterExiting() async {
+    await _assertNthStatementExits(r'''
+void f() {
+  x: while (true) {
+    return;
+    if (1 < 2) {
+      break x;
+    }
+  }
+}
+''', 0);
+  }
+
+  test_whileStatement_switchWithBreakWithLabel() async {
+    await _assertNthStatementDoesNotExit(r'''
+void f() {
+  x: while (true) {
+    switch (true) {
+      case false: break;
+      case true: break x;
+    }
+  }
+}
+''', 0);
+  }
+
+  test_yieldStatement_plain() async {
+    await _assertNthStatementDoesNotExit(r'''
+void f() sync* {
+  yield 1;
+}
+''', 0);
+  }
+
+  test_yieldStatement_star_plain() async {
+    await _assertNthStatementDoesNotExit(r'''
+void f() sync* {
+  yield* 1;
+}
+''', 0);
+  }
+
+  test_yieldStatement_star_throw() async {
+    await _assertNthStatementExits(r'''
+void f() sync* {
+  yield* throw '';
+}
+''', 0);
+  }
+
+  test_yieldStatement_throw() async {
+    await _assertNthStatementExits(r'''
+void f() sync* {
+  yield throw '';
+}
+''', 0);
+  }
+
+  Future<void> _assertHasReturn(String code, int n, bool expected) async {
+    var path = convertPath('/test/lib/test.dart');
+
+    newFile(path, content: code);
+
+    var session = driver.currentSession;
+    var resolvedResult = await session.getResolvedUnit(path);
+
+    var unit = resolvedResult.unit;
+    FunctionDeclaration function = unit.declarations.last;
+    BlockFunctionBody body = function.functionExpression.body;
+    Statement statement = body.block.statements[n];
+    expect(ExitDetector.exits(statement), expected);
+  }
+
+  /// Assert that the [n]th statement in the last function declaration of
+  /// [code] exits.
+  Future<void> _assertNthStatementDoesNotExit(String code, int n) async {
+    await _assertHasReturn(code, n, false);
+  }
+
+  /// Assert that the [n]th statement in the last function declaration of
+  /// [code] does not exit.
+  Future<void> _assertNthStatementExits(String code, int n) async {
+    await _assertHasReturn(code, n, true);
+  }
+}
diff --git a/pkg/analyzer/test/src/dart/resolver/test_all.dart b/pkg/analyzer/test/src/dart/resolver/test_all.dart
new file mode 100644
index 0000000..aff3b4f
--- /dev/null
+++ b/pkg/analyzer/test/src/dart/resolver/test_all.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.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'exit_detector_test.dart' as exit_detector;
+
+main() {
+  defineReflectiveSuite(() {
+    exit_detector.main();
+  }, name: 'resolver');
+}
diff --git a/pkg/analyzer/test/src/dart/test_all.dart b/pkg/analyzer/test/src/dart/test_all.dart
index 6d03856..adae467 100644
--- a/pkg/analyzer/test/src/dart/test_all.dart
+++ b/pkg/analyzer/test/src/dart/test_all.dart
@@ -9,6 +9,7 @@
 import 'constant/test_all.dart' as constant;
 import 'element/test_all.dart' as element;
 import 'resolution/test_all.dart' as resolution;
+import 'resolver/test_all.dart' as resolver;
 import 'sdk/test_all.dart' as sdk;
 
 /// Utility for manually running all tests.
@@ -19,6 +20,7 @@
     constant.main();
     element.main();
     resolution.main();
+    resolver.main();
     sdk.main();
   }, name: 'dart');
 }
diff --git a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
index 4a1e77b..5915938 100644
--- a/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/argument_type_not_assignable_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ArgumentTypeNotAssignableTest_Driver);
+    defineReflectiveTests(ArgumentTypeNotAssignableTest);
   });
 }
 
-abstract class ArgumentTypeNotAssignableTest extends ResolverTestCase {
+@reflectiveTest
+class ArgumentTypeNotAssignableTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_functionType() async {
     await assertErrorsInCode(r'''
 m() {
@@ -36,10 +40,3 @@
 ''', [StaticWarningCode.ARGUMENT_TYPE_NOT_ASSIGNABLE]);
   }
 }
-
-@reflectiveTest
-class ArgumentTypeNotAssignableTest_Driver
-    extends ArgumentTypeNotAssignableTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart b/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
index 58447f0..534c440 100644
--- a/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/can_be_null_after_null_aware_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(CanBeNullAfterNullAwareTest_Driver);
+    defineReflectiveTests(CanBeNullAfterNullAwareTest);
   });
 }
 
-abstract class CanBeNullAfterNullAwareTest extends ResolverTestCase {
+@reflectiveTest
+class CanBeNullAfterNullAwareTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_afterCascade() async {
     await assertErrorsInCode(r'''
 m(x) {
@@ -101,9 +105,3 @@
 ''', [HintCode.CAN_BE_NULL_AFTER_NULL_AWARE]);
   }
 }
-
-@reflectiveTest
-class CanBeNullAfterNullAwareTest_Driver extends CanBeNullAfterNullAwareTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
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 90c0e7d..f8b4aec 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
@@ -6,15 +6,15 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../dart/resolution/driver_resolution.dart';
-import '../dart/resolution/resolution.dart';
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(ConstConstructorWithMixinWithFieldTest_DriverTest);
+    defineReflectiveTests(ConstConstructorWithMixinWithFieldTest);
   });
 }
 
-mixin ConstConstructorWithMixinWithFieldMixin implements ResolutionTest {
+@reflectiveTest
+class ConstConstructorWithMixinWithFieldTest extends DriverResolutionTest {
   test_class_instance() async {
     addTestFile(r'''
 class A {
@@ -133,7 +133,3 @@
     assertNoTestErrors();
   }
 }
-
-@reflectiveTest
-class ConstConstructorWithMixinWithFieldTest_DriverTest
-    extends DriverResolutionTest with ConstConstructorWithMixinWithFieldMixin {}
diff --git a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
index a158007..7fb98b8 100644
--- a/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/division_optimization_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(DivisionOptimizationTest_Driver);
+    defineReflectiveTests(DivisionOptimizationTest);
   });
 }
 
-abstract class DivisionOptimizationTest extends ResolverTestCase {
+@reflectiveTest
+class DivisionOptimizationTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_divisionOptimization() async {
     await assertNoErrorsInCode(r'''
 f(int x, int y) {
@@ -65,9 +69,3 @@
 ''', [HintCode.DIVISION_OPTIMIZATION]);
   }
 }
-
-@reflectiveTest
-class DivisionOptimizationTest_Driver extends DivisionOptimizationTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
index 4692aee..f35bbcc 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_assignment_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InvalidAssignmentTest_Driver);
+    defineReflectiveTests(InvalidAssignmentTest);
   });
 }
 
-abstract class InvalidAssignmentTest extends ResolverTestCase {
+@reflectiveTest
+class InvalidAssignmentTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_instanceVariable() async {
     await assertErrorsInCode(r'''
 class A {
@@ -38,6 +42,24 @@
 ''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
   }
 
+  test_promotedTypeParameter_regress35306() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {}
+class C extends D {}
+class D {}
+
+void f<X extends A, Y extends B>(X x) {
+  if (x is Y) {
+    A a = x;
+    B b = x;
+    X x2 = x;
+    Y y = x;
+  }
+}
+''');
+  }
+
   test_staticVariable() async {
     await assertErrorsInCode(r'''
 class A {
@@ -51,6 +73,21 @@
 ''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
   }
 
+  test_typeParameterRecursion_regress35306() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {}
+class C extends D {}
+class D {}
+
+void f<X extends A, Y extends B>(X x) {
+  if (x is Y) {
+    D d = x;
+  }
+}
+''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
+  }
+
   test_variableDeclaration() async {
     // 17971
     await assertErrorsInCode(r'''
@@ -69,9 +106,3 @@
 ''', [StaticTypeWarningCode.INVALID_ASSIGNMENT]);
   }
 }
-
-@reflectiveTest
-class InvalidAssignmentTest_Driver extends InvalidAssignmentTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
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
new file mode 100644
index 0000000..684a9c3
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_named_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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(InvalidOverrideDifferentDefaultValuesNamedTest);
+  });
+}
+
+@reflectiveTest
+class InvalidOverrideDifferentDefaultValuesNamedTest
+    extends DriverResolutionTest {
+  test_baseClassInOtherLibrary() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  foo([a = 0]) {}
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart';
+
+class C extends A {
+  foo([a = 0]) {}
+}
+''');
+  }
+
+  test_differentValues() async {
+    await _assertError(r'''
+class A {
+  m({x = 0}) {}
+}
+class B extends A {
+  m({x = 1}) {}
+}''');
+  }
+
+  test_equalValues() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  foo({x = 1});
+}
+
+class C extends A {
+  foo({x = 3 - 2}) {}
+}
+''');
+  }
+
+  test_equalValues_function() async {
+    await assertNoErrorsInCode(r'''
+nothing() => 'nothing';
+
+class A {
+  foo(String a, {orElse = nothing}) {}
+}
+
+class B extends A {
+  foo(String a, {orElse = nothing}) {}
+}
+''');
+  }
+
+  test_explicitNull_overriddenWith_implicitNull() async {
+    // If the base class provided an explicit null value for a default
+    // parameter, then it is ok for the derived class to let the default value
+    // be implicit, because the implicit default value of null matches the
+    // explicit default value of null.
+    await assertNoErrorsInCode(r'''
+class A {
+  foo({x: null}) {}
+}
+class B extends A {
+  foo({x}) {}
+}
+''');
+  }
+
+  test_implicitNull_overriddenWith_value() async {
+    // If the base class lets the default parameter be implicit, then it is ok
+    // for the derived class to provide an explicit default value, even if it's
+    // not null.
+    await assertNoErrorsInCode(r'''
+class A {
+  foo({x}) {}
+}
+class B extends A {
+  foo({x = 1}) {}
+}
+''');
+  }
+
+  test_value_overriddenWith_implicitNull() async {
+    // 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'''
+class A {
+  foo({x: 1}) {}
+}
+class B extends A {
+  foo({x}) {}
+}
+''');
+  }
+
+  Future<void> _assertError(String code) async {
+    await assertErrorsInCode(code, [
+      StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_NAMED,
+    ]);
+  }
+}
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
new file mode 100644
index 0000000..0de7735
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_override_different_default_values_positional_test.dart
@@ -0,0 +1,118 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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(InvalidOverrideDifferentDefaultValuesPositionalTest);
+  });
+}
+
+@reflectiveTest
+class InvalidOverrideDifferentDefaultValuesPositionalTest
+    extends DriverResolutionTest {
+  test_baseClassInOtherLibrary() async {
+    newFile('/test/lib/a.dart', content: r'''
+class A {
+  foo([a = 0]) {}
+}
+''');
+    await assertNoErrorsInCode(r'''
+import 'a.dart';
+
+class C extends A {
+  foo([a = 0]) {}
+}
+''');
+  }
+
+  test_differentValues() async {
+    await _assertError(r'''
+class A {
+  m([x = 0]) {}
+}
+class B extends A {
+  m([x = 1]) {}
+}''');
+  }
+
+  test_equalValues() async {
+    await assertNoErrorsInCode(r'''
+abstract class A {
+  foo([x = 1]);
+}
+
+class C extends A {
+  foo([x = 3 - 2]) {}
+}
+''');
+  }
+
+  test_equalValues_function() async {
+    await assertNoErrorsInCode(r'''
+nothing() => 'nothing';
+
+class A {
+  foo(String a, [orElse = nothing]) {}
+}
+
+class B extends A {
+  foo(String a, [orElse = nothing]) {}
+}
+''');
+  }
+
+  test_explicitNull_overriddenWith_implicitNull() async {
+    // If the base class provided an explicit null value for a default
+    // parameter, then it is ok for the derived class to let the default value
+    // be implicit, because the implicit default value of null matches the
+    // explicit default value of null.
+    await assertNoErrorsInCode(r'''
+class A {
+  foo([x = null]) {}
+}
+class B extends A {
+  foo([x]) {}
+}
+''');
+  }
+
+  test_implicitNull_overriddenWith_value() async {
+    // If the base class lets the default parameter be implicit, then it is ok
+    // for the derived class to provide an explicit default value, even if it's
+    // not null.
+    await assertNoErrorsInCode(r'''
+class A {
+  foo([x]) {}
+}
+class B extends A {
+  foo([x = 1]) {}
+}
+''');
+  }
+
+  test_value_overriddenWith_implicitNull() async {
+    // 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'''
+class A {
+  foo([x = 1]) {}
+}
+class B extends A {
+  foo([x]) {}
+}
+''');
+  }
+
+  Future<void> _assertError(String code) async {
+    await assertErrorsInCode(code, [
+      StaticWarningCode.INVALID_OVERRIDE_DIFFERENT_DEFAULT_VALUES_POSITIONAL,
+    ]);
+  }
+}
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 3543168..d426e08 100644
--- a/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/invalid_required_param_test.dart
@@ -10,11 +10,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(InvalidRequiredParamTest_Driver);
+    defineReflectiveTests(InvalidRequiredParamTest);
   });
 }
 
-abstract class InvalidRequiredParamTest extends ResolverTestCase {
+@reflectiveTest
+class InvalidRequiredParamTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   @override
   void reset() {
     super.resetWith(packages: [
@@ -67,9 +71,3 @@
 ''');
   }
 }
-
-@reflectiveTest
-class InvalidRequiredParamTest_Driver extends InvalidRequiredParamTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
new file mode 100644
index 0000000..b842600
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/invalid_visibility_annotation_test.dart
@@ -0,0 +1,175 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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 '../../generated/hint_code_test.dart' show metaLibraryStub;
+import '../../generated/resolver_test_case.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(InvalidVisibilityAnnotationTest);
+  });
+}
+
+@reflectiveTest
+class InvalidVisibilityAnnotationTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  @override
+  void reset() {
+    super.resetWith(packages: [
+      ['meta', metaLibraryStub]
+    ]);
+  }
+
+  test_publicTopLevelVariable() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting final _a = 1;
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_topLevelVariable_multiplePrivate() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting final _a = 1, _b = 2;
+''', [
+      HintCode.INVALID_VISIBILITY_ANNOTATION,
+      HintCode.INVALID_VISIBILITY_ANNOTATION
+    ]);
+  }
+
+  test_topLevelVariable_multipleMixed() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting final _a = 1, b = 2;
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_topLevelVariable_multiplePublic() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting final a = 1, b = 2;
+''');
+  }
+
+  test_privateTopLevelFucntion() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting void _f() {}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateTopLevelFunction() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting void _f() {}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateEnum() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting enum _E {a, b, c}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateTypedef() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting typedef _T = Function();
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateClass() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting class _C {}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateMixin() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting mixin _M {}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateConstructor() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting C._() {}
+}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateMethod() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting void _m() {}
+}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_privateField() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting int _a;
+}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_fields_multiplePrivate() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting int _a, _b;
+}
+''', [
+      HintCode.INVALID_VISIBILITY_ANNOTATION,
+      HintCode.INVALID_VISIBILITY_ANNOTATION
+    ]);
+  }
+
+  test_fields_multipleMixed() async {
+    await assertErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting int _a, b;
+}
+''', [HintCode.INVALID_VISIBILITY_ANNOTATION]);
+  }
+
+  test_fields_multiplePublic() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+class C {
+  @visibleForTesting int a, b;
+}
+''');
+  }
+
+  test_valid() async {
+    await assertNoErrorsInCode(r'''
+import 'package:meta/meta.dart';
+@visibleForTesting void f() {}
+@visibleForTesting enum E {a, b, c}
+@visibleForTesting typedef T = Function();
+@visibleForTesting class C1 {}
+@visibleForTesting mixin M {}
+class C2 {
+  @visibleForTesting C2.named() {}
+}
+class C3 {
+  @visibleForTesting void m() {}
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/test_all.dart b/pkg/analyzer/test/src/diagnostics/test_all.dart
index 20b7c10..5deb7f2 100644
--- a/pkg/analyzer/test/src/diagnostics/test_all.dart
+++ b/pkg/analyzer/test/src/diagnostics/test_all.dart
@@ -10,12 +10,31 @@
 import 'division_optimization_test.dart' as division_optimization;
 import 'invalid_assignment_test.dart' as invalid_assignment;
 import 'invalid_cast_new_expr_test.dart' as invalid_cast_new_expr;
+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'
+    as invalid_override_different_default_values_positional;
 import 'invalid_required_param_test.dart' as invalid_required_param;
-import 'undefined_getter.dart' as undefined_getter;
+import 'top_level_instance_getter_test.dart' as top_level_instance_getter;
+import 'top_level_instance_method_test.dart' as top_level_instance_method;
+import 'type_check_is_not_null_test.dart' as type_check_is_not_null;
+import 'type_check_is_null_test.dart' as type_check_is_null;
+import 'undefined_getter_test.dart' as undefined_getter;
+import 'undefined_hidden_name_test.dart' as undefined_hidden_name;
+import 'undefined_operator_test.dart' as undefined_operator;
+import 'undefined_setter_test.dart' as undefined_setter;
+import 'undefined_shown_name_test.dart' as undefined_shown_name;
 import 'unnecessary_cast_test.dart' as unnecessary_cast;
+import 'unnecessary_no_such_method_test.dart' as unnecessary_no_such_method;
+import 'unnecessary_type_check_false_test.dart' as unnecessary_type_check_false;
+import 'unnecessary_type_check_true_test.dart' as unnecessary_type_check_true;
+import 'unused_catch_clause_test.dart' as unused_catch_clause;
+import 'unused_catch_stack_test.dart' as unused_catch_stack;
+import 'unused_element_test.dart' as unused_element;
 import 'unused_field_test.dart' as unused_field;
 import 'unused_import_test.dart' as unused_import;
 import 'unused_label_test.dart' as unused_label;
+import 'unused_local_variable_test.dart' as unused_local_variable;
 import 'unused_shown_name_test.dart' as unused_shown_name;
 import 'use_of_void_result_test.dart' as use_of_void_result;
 
@@ -27,12 +46,29 @@
     division_optimization.main();
     invalid_assignment.main();
     invalid_cast_new_expr.main();
+    invalid_override_different_default_values_named.main();
+    invalid_override_different_default_values_positional.main();
     invalid_required_param.main();
+    top_level_instance_getter.main();
+    top_level_instance_method.main();
+    type_check_is_not_null.main();
+    type_check_is_null.main();
     undefined_getter.main();
+    undefined_hidden_name.main();
+    undefined_operator.main();
+    undefined_setter.main();
+    undefined_shown_name.main();
     unnecessary_cast.main();
+    unnecessary_no_such_method.main();
+    unnecessary_type_check_false.main();
+    unnecessary_type_check_true.main();
+    unused_catch_clause.main();
+    unused_catch_stack.main();
+    unused_element.main();
     unused_field.main();
     unused_import.main();
     unused_label.main();
+    unused_local_variable.main();
     unused_shown_name.main();
     use_of_void_result.main();
   }, name: 'diagnostics');
diff --git a/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart b/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart
new file mode 100644
index 0000000..dae29d6
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/top_level_instance_getter_test.dart
@@ -0,0 +1,434 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/error/codes.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TopLevelInstanceGetterTest);
+  });
+}
+
+@reflectiveTest
+class TopLevelInstanceGetterTest extends DriverResolutionTest {
+  test_call() async {
+    await assertNoErrorsInCode('''
+class A {
+  int Function() get g => () => 0;
+}
+var a = new A();
+var b = a.g();
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[2];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+
+  test_field() async {
+    await assertNoErrorsInCode('''
+class A {
+  int g;
+}
+var b = new A().g;
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[1];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+
+  test_field_call() async {
+    await assertNoErrorsInCode('''
+class A {
+  int Function() g;
+}
+var a = new A();
+var b = a.g();
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[2];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+
+  test_field_prefixedIdentifier() async {
+    await assertNoErrorsInCode('''
+class A {
+  int g;
+}
+var a = new A();
+var b = a.g;
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[2];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+
+  test_getter() async {
+    await assertNoErrorsInCode('''
+class A {
+  int get g => 0;
+}
+var b = new A().g;
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[1];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+
+  test_implicitlyTyped() async {
+    await assertErrorsInCode('''
+class A {
+  get g => 0;
+}
+var b = new A().g;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_call() async {
+    await assertErrorsInCode('''
+class A {
+  get g => () => 0;
+}
+var a = new A();
+var b = a.g();
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_field() async {
+    await assertErrorsInCode('''
+class A {
+  var g = 0;
+}
+var b = new A().g;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_field_call() async {
+    await assertErrorsInCode('''
+class A {
+  var g = () => 0;
+}
+var a = new A();
+var b = a.g();
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_field_prefixedIdentifier() async {
+    await assertErrorsInCode('''
+class A {
+  var g = 0;
+}
+var a = new A();
+var b = a.g;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_fn() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
+    // generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = 0;
+}
+int f<T>(x) => 0;
+var a = new A();
+var b = f(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_fn_explicit_type_params() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+int f<T>(x) => 0;
+var a = new A();
+var b = f<int>(a.x);
+''');
+  }
+
+  test_implicitlyTyped_fn_not_generic() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+int f(x) => 0;
+var a = new A();
+var b = f(a.x);
+''');
+  }
+
+  test_implicitlyTyped_indexExpression() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+  int operator[](int value) => 0;
+}
+var a = new A();
+var b = a[a.x];
+''');
+  }
+
+  test_implicitlyTyped_invoke() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the
+    // closure is generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = (<T>(y) => 0)(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_invoke_explicit_type_params() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = (<T>(y) => 0)<int>(a.x);
+''');
+  }
+
+  test_implicitlyTyped_invoke_not_generic() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = ((y) => 0)(a.x);
+''');
+  }
+
+  test_implicitlyTyped_method() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because f is
+    // generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = 0;
+  int f<T>(int x) => 0;
+}
+var a = new A();
+var b = a.f(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_method_explicit_type_params() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+  int f<T>(x) => 0;
+}
+var a = new A();
+var b = a.f<int>(a.x);
+''');
+  }
+
+  test_implicitlyTyped_method_not_generic() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+  int f(x) => 0;
+}
+var a = new A();
+var b = a.f(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
+    // generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B<T> {
+  B(x);
+}
+var a = new A();
+var b = new B(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_new_explicit_type_params() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B<T> {
+  B(x);
+}
+var a = new A();
+var b = new B<int>(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_explicit_type_params_named() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B<T> {
+  B.named(x);
+}
+var a = new A();
+var b = new B<int>.named(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_explicit_type_params_prefixed() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    newFile('/test/lib/lib1.dart', content: '''
+class B<T> {
+  B(x);
+}
+''');
+    await assertNoErrorsInCode('''
+import 'lib1.dart' as foo;
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = new foo.B<int>(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_named() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
+    // generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B<T> {
+  B.named(x);
+}
+var a = new A();
+var b = new B.named(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_new_not_generic() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B {
+  B(x);
+}
+var a = new A();
+var b = new B(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_not_generic_named() async {
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+class A {
+  var x = 0;
+}
+class B {
+  B.named(x);
+}
+var a = new A();
+var b = new B.named(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_not_generic_prefixed() async {
+    newFile('/test/lib/lib1.dart', content: '''
+class B {
+  B(x);
+}
+''');
+    // The reference to a.x does not trigger TOP_LEVEL_INSTANCE_GETTER because
+    // it can't possibly affect the type of b.
+    await assertNoErrorsInCode('''
+import 'lib1.dart' as foo;
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = new foo.B(a.x);
+''');
+  }
+
+  test_implicitlyTyped_new_prefixed() async {
+    newFile('/test/lib/lib1.dart', content: '''
+class B<T> {
+  B(x);
+}
+''');
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because B is
+    // generic, so the type of a.x might affect the type of b.
+    await assertErrorsInCode('''
+import 'lib1.dart' as foo;
+class A {
+  var x = 0;
+}
+var a = new A();
+var b = new foo.B(a.x);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_prefixedIdentifier() async {
+    await assertErrorsInCode('''
+class A {
+  get g => 0;
+}
+var a = new A();
+var b = a.g;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_implicitlyTyped_propertyAccessLhs() async {
+    // The reference to a.x triggers TOP_LEVEL_INSTANCE_GETTER because the type
+    // of a.x affects the lookup of y, which in turn affects the type of b.
+    await assertErrorsInCode('''
+class A {
+  var x = new B();
+  int operator[](int value) => 0;
+}
+class B {
+  int y;
+}
+var a = new A();
+var b = (a.x).y;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_GETTER]);
+  }
+
+  test_prefixedIdentifier() async {
+    await assertNoErrorsInCode('''
+class A {
+  int get g => 0;
+}
+var a = new A();
+var b = a.g;
+''');
+    TopLevelVariableDeclaration b = result.unit.declarations[2];
+    expect(b.variables.variables[0].declaredElement.type.toString(), 'int');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart b/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.dart
new file mode 100644
index 0000000..4e6dde5
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/top_level_instance_method_test.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/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(TopLevelInstanceMethodTest);
+  });
+}
+
+@reflectiveTest
+class TopLevelInstanceMethodTest extends DriverResolutionTest {
+  test_noParameter() async {
+    await assertErrorsInCode('''
+class A {
+  f() => 0;
+}
+var x = new A().f();
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+  }
+
+  test_parameter() async {
+    await assertNoErrorsInCode('''
+class A {
+  int f(v) => 0;
+}
+var x = new A().f(0);
+''');
+  }
+
+  test_parameter_generic() async {
+    await assertErrorsInCode('''
+class A {
+  int f<T>(v) => 0;
+}
+var x = new A().f(0);
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+  }
+
+  test_parameter_generic_explicit() async {
+    await assertNoErrorsInCode('''
+class A {
+  int f<T>(v) => 0;
+}
+var x = new A().f<int>(0);
+''');
+  }
+
+  test_static() async {
+    await assertNoErrorsInCode('''
+class A {
+  static f() => 0;
+}
+var x = A.f();
+''');
+  }
+
+  test_tearOff() async {
+    await assertErrorsInCode('''
+class A {
+  f() => 0;
+}
+var x = new A().f;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+  }
+
+  test_tearOff_parameter() async {
+    await assertErrorsInCode('''
+class A {
+  int f(v) => 0;
+}
+var x = new A().f;
+''', [StrongModeCode.TOP_LEVEL_INSTANCE_METHOD]);
+  }
+
+  test_tearoff_static() async {
+    await assertNoErrorsInCode('''
+class A {
+  static f() => 0;
+}
+var x = A.f;
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart b/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_test.dart
new file mode 100644
index 0000000..a5d66af
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_check_is_not_null_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.
+
+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(TypeCheckIsNotNullTest);
+  });
+}
+
+@reflectiveTest
+class TypeCheckIsNotNullTest extends DriverResolutionTest {
+  test_not_Null() async {
+    await assertErrorsInCode(r'''
+bool m(i) {
+  return i is! Null;
+}
+''', [HintCode.TYPE_CHECK_IS_NOT_NULL]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart b/pkg/analyzer/test/src/diagnostics/type_check_is_null_test.dart
new file mode 100644
index 0000000..4f50661
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/type_check_is_null_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.
+
+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(TypeCheckIsNullTest);
+  });
+}
+
+@reflectiveTest
+class TypeCheckIsNullTest extends DriverResolutionTest {
+  test_is_Null() async {
+    await assertErrorsInCode(r'''
+bool m(i) {
+  return i is Null;
+}
+''', [HintCode.TYPE_CHECK_IS_NULL]);
+  }
+}
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
new file mode 100644
index 0000000..36dc5fb
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unchecked_use_of_nullable_value_test.dart
@@ -0,0 +1,561 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UncheckedUseOfNullableValueTest);
+  });
+}
+
+@reflectiveTest
+class UncheckedUseOfNullableValueTest extends ResolverTestCase {
+  @override
+  List<String> get enabledExperiments => [EnableString.non_nullable];
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_and_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  if(x && true) {}
+}
+''');
+  }
+
+  test_and_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  if(x && true) {}
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_as_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  num? x;
+  x as int;
+}
+''');
+  }
+
+  test_await_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() async {
+  Future x = Future.value(null);
+  await x;
+}
+''');
+  }
+
+  test_await_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() async {
+  Future? x;
+  await x;
+}
+''');
+  }
+
+  test_cascade_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x..isEven;
+}
+''');
+  }
+
+  test_cascade_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x..isEven;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_eq_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x == null;
+}
+''');
+  }
+
+  test_forLoop_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  List x = [];
+  for (var y in x) {}
+}
+''');
+  }
+
+  test_forLoop_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  List? x;
+  for (var y in x) {}
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_if_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  if (x) {}
+}
+''');
+  }
+
+  test_if_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  if (x) {}
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_index_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  List x = [1];
+  x[0];
+}
+''');
+  }
+
+  test_index_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  List? x;
+  x[0];
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_invoke_dynamicFunctionType_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  Function x = () {};
+  x();
+}
+''');
+  }
+
+  @failingTest
+  test_invoke_dynamicFunctionType_nullable() async {
+    // test is failing because nullable function invocations aren't being
+    // resolved correctly
+    await assertErrorsInCode(r'''
+m() {
+  Function? x;
+  x();
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_invoke_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  Function() x = () {};
+  x();
+}
+''');
+  }
+
+  @failingTest
+  test_invoke_nullable() async {
+    // test is failing because nullable function invocations aren't being
+    // resolved correctly
+    await assertErrorsInCode(r'''
+m() {
+  Function()? x;
+  x();
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_invoke_parenthesized_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  Function x = () {};
+  (x)();
+}
+''');
+  }
+
+  test_is_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x is int;
+}
+''');
+  }
+
+  test_member_hashCode_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x.hashCode;
+}
+''');
+  }
+
+  test_member_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x.isEven;
+}
+''');
+  }
+
+  test_member_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x.isEven;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_member_parenthesized_hashCode_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  (x).hashCode;
+}
+''');
+  }
+
+  test_member_parenthesized_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  (x).isEven;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_member_parenthesized_runtimeType_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  (x).runtimeType;
+}
+''');
+  }
+
+  test_member_questionDot_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x?.isEven;
+}
+''');
+  }
+
+  test_member_runtimeType_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x.runtimeType;
+}
+''');
+  }
+
+  test_method_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x.round();
+}
+''');
+  }
+
+  test_method_noSuchMethod_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x;
+  x.noSuchMethod(null);
+}
+''');
+  }
+
+  test_method_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x.round();
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_method_questionDot_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x?.round();
+}
+''');
+  }
+
+  test_method_toString_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x;
+  x.toString();
+}
+''');
+  }
+
+  test_minusEq_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x -= 1;
+}
+''');
+  }
+
+  test_minusEq_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x -= 1;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_not_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  if(!x) {}
+}
+''');
+  }
+
+  test_not_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  if(!x) {}
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_notEq_nullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int? x;
+  x != null;
+}
+''');
+  }
+
+  test_operatorMinus_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x - 3;
+}
+''');
+  }
+
+  test_operatorMinus_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x - 3;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorPlus_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x + 3;
+}
+''');
+  }
+
+  test_operatorPlus_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x + 3;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorPostfixDec_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  x--;
+}
+''');
+  }
+
+  test_operatorPostfixDec_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x--;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorPostfixInc_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x;
+  x++;
+}
+''');
+  }
+
+  test_operatorPostfixInc_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x++;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorPrefixDec_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  --x;
+}
+''');
+  }
+
+  test_operatorPrefixDec_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  --x;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorPrefixInc_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x;
+  ++x;
+}
+''');
+  }
+
+  test_operatorPrefixInc_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  ++x;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_operatorUnaryMinus_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x = 0;
+  -x;
+}
+''');
+  }
+
+  test_operatorUnaryMinus_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  -x;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_or_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  bool x = true;
+  if(x || false) {}
+}
+''');
+  }
+
+  test_or_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  if(x || false) {}
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_plusEq_nonNullable() async {
+    await assertNoErrorsInCode(r'''
+m() {
+  int x;
+  x += 1;
+}
+''');
+  }
+
+  test_plusEq_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  int? x;
+  x += 1;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_ternary_condition_nullable() async {
+    await assertErrorsInCode(r'''
+m() {
+  bool? x;
+  x ? 0 : 1;
+}
+''', [StaticWarningCode.UNCHECKED_USE_OF_NULLABLE_VALUE]);
+  }
+
+  test_ternary_lhs_nullable() async {
+    await assertNoErrorsInCode(r'''
+m(bool cond) {
+  int? x;
+  cond ? x : 1;
+}
+''');
+  }
+
+  test_ternary_rhs_nullable() async {
+    await assertNoErrorsInCode(r'''
+m(bool cond) {
+  int? x;
+  cond ? 0 : x;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter.dart
deleted file mode 100644
index c40128c..0000000
--- a/pkg/analyzer/test/src/diagnostics/undefined_getter.dart
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:analyzer/src/error/codes.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
-
-import '../../generated/resolver_test_case.dart';
-
-main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(UndefinedGetterTest);
-    defineReflectiveTests(UndefinedGetterTest_Driver);
-  });
-}
-
-@reflectiveTest
-class UndefinedGetterTest extends ResolverTestCase {
-  test_promotedTypeParameter_regress35305() async {
-    await assertErrorsInCode(r'''
-void f<X extends num, Y extends X>(Y y) {
-  if (y is int) {
-    y.isEven;
-  }
-}
-''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
-  }
-}
-
-@reflectiveTest
-class UndefinedGetterTest_Driver extends UndefinedGetterTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
new file mode 100644
index 0000000..e0f34b6
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_getter_test.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/analysis/experiments.dart';
+import 'package:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedGetterTest);
+    defineReflectiveTests(UndefinedGetterWithControlFlowCollectionsTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedGetterTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_ifStatement_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  if (x is String) {
+    x.length;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+  }
+
+  test_ifStatement_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  if (x is String) {
+    x.length;
+  }
+}
+''');
+  }
+
+  test_promotedTypeParameter_regress35305() async {
+    await assertErrorsInCode(r'''
+void f<X extends num, Y extends X>(Y y) {
+  if (y is int) {
+    y.isEven;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+  }
+}
+
+@reflectiveTest
+class UndefinedGetterWithControlFlowCollectionsTest extends ResolverTestCase {
+  @override
+  List<String> get enabledExperiments =>
+      [EnableString.control_flow_collections, EnableString.set_literals];
+
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_ifElement_inList_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return [if (x is String) x.length];
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+  }
+
+  test_ifElement_inList_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return [if (x is String) x.length];
+}
+''');
+  }
+
+  test_ifElement_inMap_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return {if (x is String) x : x.length};
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+  }
+
+  test_ifElement_inMap_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return {if (x is String) x : x.length};
+}
+''');
+  }
+
+  test_ifElement_inSet_notPromoted() async {
+    await assertErrorsInCode('''
+f(int x) {
+  return {if (x is String) x.length};
+}
+''', [StaticTypeWarningCode.UNDEFINED_GETTER], verify: false);
+  }
+
+  test_ifElement_inSet_promoted() async {
+    await assertNoErrorsInCode('''
+f(Object x) {
+  return {if (x is String) x.length};
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_test.dart
new file mode 100644
index 0000000..3391749
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_hidden_name_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.
+
+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(UndefinedHiddenNameTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedHiddenNameTest extends DriverResolutionTest {
+  test_export() async {
+    newFile('/test/lib/lib1.dart');
+    await assertErrorsInCode(r'''
+export 'lib1.dart' hide a;
+''', [HintCode.UNDEFINED_HIDDEN_NAME]);
+  }
+
+  test_import() async {
+    newFile('/test/lib/lib1.dart');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' hide a;
+''', [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_HIDDEN_NAME]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
new file mode 100644
index 0000000..b05ef9b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_operator_test.dart
@@ -0,0 +1,173 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+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(UndefinedOperatorTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedOperatorTest extends DriverResolutionTest {
+  test_binaryExpression() async {
+    await assertErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    a + 1;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_binaryExpression_inSubtype() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator +(B b) {}
+}
+f(var a) {
+  if (a is A) {
+    a + 1;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_indexBoth() async {
+    await assertErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    a[0]++;
+  }
+}
+''', [
+      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+    ]);
+  }
+
+  test_indexBoth_inSubtype() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator [](int index) {}
+}
+f(var a) {
+  if (a is A) {
+    a[0]++;
+  }
+}
+''', [
+      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+      StaticTypeWarningCode.UNDEFINED_OPERATOR,
+    ]);
+  }
+
+  test_indexGetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    a[0];
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_indexGetter_inSubtype() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator [](int index) {}
+}
+f(var a) {
+  if (a is A) {
+    a[0];
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_indexSetter() async {
+    await assertErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    a[0] = 1;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_indexSetter_inSubtype() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator []=(i, v) {}
+}
+f(var a) {
+  if (a is A) {
+    a[0] = 1;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_OPERATOR]);
+  }
+
+  test_postfixExpression() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    a++;
+  }
+}
+''');
+  }
+
+  test_postfixExpression_inSubtype() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator +(B b) {return new B();}
+}
+f(var a) {
+  if (a is A) {
+    a++;
+  }
+}
+''');
+  }
+
+  test_prefixExpression() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+f(var a) {
+  if (a is A) {
+    ++a;
+  }
+}
+''');
+  }
+
+  test_prefixExpression_inSubtype() async {
+    await assertNoErrorsInCode(r'''
+class A {}
+class B extends A {
+  operator +(B b) {return new B();}
+}
+f(var a) {
+  if (a is A) {
+    ++a;
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.dart
new file mode 100644
index 0000000..fd9bafd
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_setter_test.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:analyzer/src/error/codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UndefinedSetterTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedSetterTest extends DriverResolutionTest {
+  test_inSubtype() async {
+    await assertErrorsInCode(r'''
+class A {}
+class B extends A {
+  set b(x) {}
+}
+f(var a) {
+  if (a is A) {
+    a.b = 0;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+  }
+
+  test_inType() async {
+    await assertErrorsInCode(r'''
+class A {}
+f(var a) {
+  if(a is A) {
+    a.m = 0;
+  }
+}
+''', [StaticTypeWarningCode.UNDEFINED_SETTER]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart b/pkg/analyzer/test/src/diagnostics/undefined_shown_name_test.dart
new file mode 100644
index 0000000..9bbc57a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/undefined_shown_name_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.
+
+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(UndefinedShownNameTest);
+  });
+}
+
+@reflectiveTest
+class UndefinedShownNameTest extends DriverResolutionTest {
+  test_export() async {
+    newFile('/test/lib/lib1.dart');
+    await assertErrorsInCode(r'''
+export 'lib1.dart' show a;
+''', [HintCode.UNDEFINED_SHOWN_NAME]);
+  }
+
+  test_import() async {
+    newFile('/test/lib/lib1.dart');
+    await assertErrorsInCode(r'''
+import 'lib1.dart' show a;
+''', [HintCode.UNUSED_IMPORT, HintCode.UNDEFINED_SHOWN_NAME]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
index 855d252..28e76bf 100644
--- a/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_cast_test.dart
@@ -9,11 +9,12 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UnnecessaryCastTest_Driver);
+    defineReflectiveTests(UnnecessaryCastTest);
   });
 }
 
-abstract class UnnecessaryCastTest extends ResolverTestCase {
+@reflectiveTest
+class UnnecessaryCastTest extends ResolverTestCase {
   test_conditionalExpression() async {
     await assertNoErrorsInCode(r'''
 abstract class I {}
@@ -56,17 +57,6 @@
 ''');
   }
 
-  test_generics() async {
-    // dartbug.com/18953
-    await assertNoErrorsInCode(r'''
-import 'dart:async';
-Future<int> f() => new Future.value(0);
-void g(bool c) {
-  (c ? f(): new Future.value(0) as Future<int>).then((int value) {});
-}
-''');
-  }
-
   test_parameter_A() async {
     // dartbug.com/13855, dartbug.com/13732
     await assertNoErrorsInCode(r'''
@@ -105,14 +95,10 @@
 }
 ''', [HintCode.UNNECESSARY_CAST]);
   }
-}
 
-@reflectiveTest
-class UnnecessaryCastTest_Driver extends UnnecessaryCastTest {
   @override
   bool get enableNewAnalysisDriver => true;
 
-  @override
   test_generics() async {
     // dartbug.com/18953
     assertErrorsInCode(r'''
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_test.dart
new file mode 100644
index 0000000..e6f36ad
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_no_such_method_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/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnnecessaryNoSuchMethodTest);
+  });
+}
+
+@reflectiveTest
+class UnnecessaryNoSuchMethodTest extends DriverResolutionTest {
+  test_blockBody() async {
+    await assertErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) {
+    return super.noSuchMethod(y);
+  }
+}
+''', [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
+  }
+
+  test_blockBody_notReturnStatement() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) {
+    print(y);
+  }
+}
+''');
+  }
+
+  test_blockBody_notSingleStatement() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) {
+    print(y);
+    return super.noSuchMethod(y);
+  }
+}
+''');
+  }
+
+  test_expressionBody() async {
+    await assertErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) => super.noSuchMethod(y);
+}
+''', [HintCode.UNNECESSARY_NO_SUCH_METHOD]);
+  }
+
+  test_expressionBody_notNoSuchMethod() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) => super.hashCode;
+}
+''');
+  }
+
+  test_expressionBody_notSuper() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  noSuchMethod(x) => super.noSuchMethod(x);
+}
+class B extends A {
+  mmm();
+  noSuchMethod(y) => 42;
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_test.dart
new file mode 100644
index 0000000..6b48d25
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_false_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/src/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnnecessaryTypeCheckFalseTest);
+  });
+}
+
+@reflectiveTest
+class UnnecessaryTypeCheckFalseTest extends DriverResolutionTest {
+  test_null_not_Null() async {
+    await assertErrorsInCode(r'''
+bool b = null is! Null;
+''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+  }
+
+  test_type_not_dynamic() async {
+    await assertErrorsInCode(r'''
+m(i) {
+  bool b = i is! dynamic;
+}
+''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+  }
+
+  test_type_not_object() async {
+    await assertErrorsInCode(r'''
+m(i) {
+  bool b = i is! Object;
+}
+''', [HintCode.UNNECESSARY_TYPE_CHECK_FALSE]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_test.dart
new file mode 100644
index 0000000..44e96ea
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unnecessary_type_check_true_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/src/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnnecessaryTypeCheckTrueTest);
+  });
+}
+
+@reflectiveTest
+class UnnecessaryTypeCheckTrueTest extends DriverResolutionTest {
+  test_null_is_Null() async {
+    await assertErrorsInCode(r'''
+bool b = null is Null;
+''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+  }
+
+  test_type_is_dynamic() async {
+    await assertErrorsInCode(r'''
+m(i) {
+  bool b = i is dynamic;
+}
+''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+  }
+
+  test_type_is_object() async {
+    await assertErrorsInCode(r'''
+m(i) {
+  bool b = i is Object;
+}
+''', [HintCode.UNNECESSARY_TYPE_CHECK_TRUE]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart b/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.dart
new file mode 100644
index 0000000..841f0df
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_catch_clause_test.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.
+
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnusedCatchClauseTest);
+  });
+}
+
+@reflectiveTest
+class UnusedCatchClauseTest extends DriverResolutionTest {
+  @override
+  bool get enableUnusedLocalVariable => true;
+
+  test_on_unusedException() async {
+    await assertErrorsInCode(r'''
+main() {
+  try {
+  } on String catch (exception) {
+  }
+}
+''', [HintCode.UNUSED_CATCH_CLAUSE]);
+  }
+
+  test_on_usedException() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  try {
+  } on String catch (exception) {
+    print(exception);
+  }
+}
+''');
+  }
+
+  test_unusedException() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  try {
+  } catch (exception) {
+  }
+}
+''');
+  }
+
+  test_usedException() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  try {
+  } catch (exception) {
+    print(exception);
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart b/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart
new file mode 100644
index 0000000..0a7330b
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_catch_stack_test.dart
@@ -0,0 +1,66 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnusedCatchStackTest);
+  });
+}
+
+@reflectiveTest
+class UnusedCatchStackTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_on_unusedStack() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  try {
+  } on String catch (exception, stackTrace) {
+  }
+}
+''', [HintCode.UNUSED_CATCH_STACK]);
+  }
+
+  test_on_usedStack() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+main() {
+  try {
+  } on String catch (exception, stackTrace) {
+    print(stackTrace);
+  }
+}
+''');
+  }
+
+  test_unusedStack() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  try {
+  } catch (exception, stackTrace) {
+  }
+}
+''', [HintCode.UNUSED_CATCH_STACK]);
+  }
+
+  test_usedStack() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+main() {
+  try {
+  } catch (exception, stackTrace) {
+    print(stackTrace);
+  }
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_element_test.dart b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
new file mode 100644
index 0000000..871023a
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_element_test.dart
@@ -0,0 +1,577 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../dart/resolution/driver_resolution.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnusedElementTest);
+  });
+}
+
+@reflectiveTest
+class UnusedElementTest extends DriverResolutionTest {
+  @override
+  bool get enableUnusedElement => true;
+
+  test_class_isUsed_extends() async {
+    await assertNoErrorsInCode(r'''
+class _A {}
+class B extends _A {}
+''');
+  }
+
+  test_class_isUsed_fieldDeclaration() async {
+    await assertNoErrorsInCode(r'''
+class Foo {
+  _Bar x;
+}
+
+class _Bar {
+}
+''');
+  }
+
+  test_class_isUsed_implements() async {
+    await assertNoErrorsInCode(r'''
+class _A {}
+class B implements _A {}
+''');
+  }
+
+  test_class_isUsed_instanceCreation() async {
+    await assertNoErrorsInCode(r'''
+class _A {}
+main() {
+  new _A();
+}
+''');
+  }
+
+  test_class_isUsed_staticFieldAccess() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  static const F = 42;
+}
+main() {
+  _A.F;
+}
+''');
+  }
+
+  test_class_isUsed_staticMethodInvocation() async {
+    await assertNoErrorsInCode(r'''
+class _A {
+  static m() {}
+}
+main() {
+  _A.m();
+}
+''');
+  }
+
+  test_class_isUsed_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+class _A {}
+main() {
+  var v = new List<_A>();
+  print(v);
+}
+''');
+  }
+
+  test_class_notUsed_inClassMember() async {
+    await assertErrorsInCode(r'''
+class _A {
+  static staticMethod() {
+    new _A();
+  }
+  instanceMethod() {
+    new _A();
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_class_notUsed_inConstructorName() async {
+    await assertErrorsInCode(r'''
+class _A {
+  _A() {}
+  _A.named() {}
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_class_notUsed_isExpression() async {
+    await assertErrorsInCode(r'''
+class _A {}
+main(p) {
+  if (p is _A) {
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_class_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+class _A {}
+main() {
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_class_notUsed_variableDeclaration() async {
+    await assertErrorsInCode(r'''
+class _A {}
+main() {
+  _A v;
+  print(v);
+}
+print(x) {}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_enum_isUsed_fieldReference() async {
+    await assertNoErrorsInCode(r'''
+enum _MyEnum {A, B, C}
+main() {
+  print(_MyEnum.B);
+}
+''');
+  }
+
+  test_enum_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+enum _MyEnum {A, B, C}
+main() {
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_functionLocal_isUsed_closure() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  print(() {});
+}
+print(x) {}
+''');
+  }
+
+  test_functionLocal_isUsed_invocation() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  f() {}
+  f();
+}
+''');
+  }
+
+  test_functionLocal_isUsed_reference() async {
+    await assertNoErrorsInCode(r'''
+main() {
+  f() {}
+  print(f);
+}
+print(x) {}
+''');
+  }
+
+  test_functionLocal_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+main() {
+  f() {}
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_functionLocal_notUsed_referenceFromItself() async {
+    await assertErrorsInCode(r'''
+main() {
+  _f(int p) {
+    _f(p - 1);
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_functionTop_isUsed_invocation() async {
+    await assertNoErrorsInCode(r'''
+_f() {}
+main() {
+  _f();
+}
+''');
+  }
+
+  test_functionTop_isUsed_reference() async {
+    await assertNoErrorsInCode(r'''
+_f() {}
+main() {
+  print(_f);
+}
+print(x) {}
+''');
+  }
+
+  test_functionTop_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+_f() {}
+main() {
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_functionTop_notUsed_referenceFromItself() async {
+    await assertErrorsInCode(r'''
+_f(int p) {
+  _f(p - 1);
+}
+main() {
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_functionTypeAlias_isUsed_isExpression() async {
+    await assertNoErrorsInCode(r'''
+typedef _F(a, b);
+main(f) {
+  if (f is _F) {
+    print('F');
+  }
+}
+''');
+  }
+
+  test_functionTypeAlias_isUsed_reference() async {
+    await assertNoErrorsInCode(r'''
+typedef _F(a, b);
+main(_F f) {
+}
+''');
+  }
+
+  test_functionTypeAlias_isUsed_typeArgument() async {
+    await assertNoErrorsInCode(r'''
+typedef _F(a, b);
+main() {
+  var v = new List<_F>();
+  print(v);
+}
+''');
+  }
+
+  test_functionTypeAlias_isUsed_variableDeclaration() async {
+    await assertNoErrorsInCode(r'''
+typedef _F(a, b);
+class A {
+  _F f;
+}
+''');
+  }
+
+  test_functionTypeAlias_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+typedef _F(a, b);
+main() {
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_getter_isUsed_invocation_implicitThis() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  get _g => null;
+  useGetter() {
+    var v = _g;
+  }
+}
+''');
+  }
+
+  test_getter_isUsed_invocation_PrefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  get _g => null;
+}
+main(A a) {
+  var v = a._g;
+}
+''');
+  }
+
+  test_getter_isUsed_invocation_PropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  get _g => null;
+}
+main() {
+  var v = new A()._g;
+}
+''');
+  }
+
+  test_getter_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+class A {
+  get _g => null;
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_getter_notUsed_referenceFromItself() async {
+    await assertErrorsInCode(r'''
+class A {
+  get _g {
+    return _g;
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_method_isUsed_hasReference_implicitThis() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+  useMethod() {
+    print(_m);
+  }
+}
+print(x) {}
+''');
+  }
+
+  test_method_isUsed_hasReference_implicitThis_subclass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+  useMethod() {
+    print(_m);
+  }
+}
+class B extends A {
+  _m() {}
+}
+print(x) {}
+''');
+  }
+
+  test_method_isUsed_hasReference_PrefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+}
+main(A a) {
+  a._m;
+}
+''');
+  }
+
+  test_method_isUsed_hasReference_PropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+}
+main() {
+  new A()._m;
+}
+''');
+  }
+
+  test_method_isUsed_invocation_implicitThis() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+  useMethod() {
+    _m();
+  }
+}
+''');
+  }
+
+  test_method_isUsed_invocation_implicitThis_subclass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+  useMethod() {
+    _m();
+  }
+}
+class B extends A {
+  _m() {}
+}
+''');
+  }
+
+  test_method_isUsed_invocation_MemberElement() async {
+    await assertNoErrorsInCode(r'''
+class A<T> {
+  _m(T t) {}
+}
+main(A<int> a) {
+  a._m(0);
+}
+''');
+  }
+
+  test_method_isUsed_invocation_propagated() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+}
+main() {
+  var a = new A();
+  a._m();
+}
+''');
+  }
+
+  test_method_isUsed_invocation_static() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+}
+main() {
+  A a = new A();
+  a._m();
+}
+''');
+  }
+
+  test_method_isUsed_invocation_subclass() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  _m() {}
+}
+class B extends A {
+  _m() {}
+}
+main(A a) {
+  a._m();
+}
+''');
+  }
+
+  test_method_isUsed_notPrivate() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  m() {}
+}
+main() {
+}
+''');
+  }
+
+  test_method_isUsed_staticInvocation() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  static _m() {}
+}
+main() {
+  A._m();
+}
+''');
+  }
+
+  test_method_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+class A {
+  static _m() {}
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_method_notUsed_referenceFromItself() async {
+    await assertErrorsInCode(r'''
+class A {
+  static _m(int p) {
+    _m(p - 1);
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_setter_isUsed_invocation_implicitThis() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  set _s(x) {}
+  useSetter() {
+    _s = 42;
+  }
+}
+''');
+  }
+
+  test_setter_isUsed_invocation_PrefixedIdentifier() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  set _s(x) {}
+}
+main(A a) {
+  a._s = 42;
+}
+''');
+  }
+
+  test_setter_isUsed_invocation_PropertyAccess() async {
+    await assertNoErrorsInCode(r'''
+class A {
+  set _s(x) {}
+}
+main() {
+  new A()._s = 42;
+}
+''');
+  }
+
+  test_setter_notUsed_noReference() async {
+    await assertErrorsInCode(r'''
+class A {
+  set _s(x) {}
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_setter_notUsed_referenceFromItself() async {
+    await assertErrorsInCode(r'''
+class A {
+  set _s(int x) {
+    if (x > 5) {
+      _s = x - 1;
+    }
+  }
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+
+  test_topLevelVariable_isUsed() async {
+    await assertNoErrorsInCode(r'''
+int _a = 1;
+main() {
+  _a;
+}
+''');
+  }
+
+  test_topLevelVariable_isUsed_plusPlus() async {
+    await assertNoErrorsInCode(r'''
+int _a = 0;
+main() {
+  var b = _a++;
+  b;
+}
+''');
+  }
+
+  test_topLevelVariable_notUsed() async {
+    await assertErrorsInCode(r'''
+int _a = 1;
+main() {
+  _a = 2;
+}
+''', [HintCode.UNUSED_ELEMENT]);
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
index 21fad18..3fa352c 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_field_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UnusedFieldTest_Driver);
+    defineReflectiveTests(UnusedFieldTest);
   });
 }
 
-abstract class UnusedFieldTest extends ResolverTestCase {
+@reflectiveTest
+class UnusedFieldTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   @override
   bool get enableUnusedElement => true;
 
@@ -188,9 +192,3 @@
 ''', [HintCode.UNUSED_FIELD]);
   }
 }
-
-@reflectiveTest
-class UnusedFieldTest_Driver extends UnusedFieldTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_import_test.dart b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
index 55667a1..34319e4 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_import_test.dart
@@ -10,11 +10,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UnusedImportTest_Driver);
+    defineReflectiveTests(UnusedImportTest);
   });
 }
 
-abstract class UnusedImportTest extends ResolverTestCase {
+@reflectiveTest
+class UnusedImportTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_annotationOnDirective() async {
     Source source = addSource(r'''
 library L;
@@ -311,9 +315,3 @@
     verify([source, source2]);
   }
 }
-
-@reflectiveTest
-class UnusedImportTest_Driver extends UnusedImportTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_label_test.dart b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
index 7a94420..e14f291 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_label_test.dart
@@ -9,11 +9,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UnusedLabelTest_Driver);
+    defineReflectiveTests(UnusedLabelTest);
   });
 }
 
-abstract class UnusedLabelTest extends ResolverTestCase {
+@reflectiveTest
+class UnusedLabelTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_unused_inSwitch() async {
     await assertErrorsInCode(r'''
 f(x) {
@@ -60,9 +64,3 @@
 ''');
   }
 }
-
-@reflectiveTest
-class UnusedLabelTest_Driver extends UnusedLabelTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart b/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart
new file mode 100644
index 0000000..ee12d06
--- /dev/null
+++ b/pkg/analyzer/test/src/diagnostics/unused_local_variable_test.dart
@@ -0,0 +1,132 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/src/dart/error/hint_codes.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../generated/resolver_test_case.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(UnusedLocalVariableTest);
+  });
+}
+
+@reflectiveTest
+class UnusedLocalVariableTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
+  test_inFor_underscore_ignored() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+main() {
+  for (var _ in [1,2,3]) {
+    for (var __ in [4,5,6]) {
+      // do something
+    }
+  }
+}
+''');
+  }
+
+  test_inFunction() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  var v = 1;
+  v = 2;
+}
+''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_inMethod() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+class A {
+  foo() {
+    var v = 1;
+    v = 2;
+  }
+}
+''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_isInvoked() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+typedef Foo();
+main() {
+  Foo foo;
+  foo();
+}
+''');
+  }
+
+  test_isNullAssigned() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+typedef Foo();
+main() {
+  var v;
+  v ??= doSomething();
+}
+doSomething() => 42;
+''');
+  }
+
+  test_isRead_notUsed_compoundAssign() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  var v = 1;
+  v += 2;
+}
+''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_isRead_notUsed_postfixExpr() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  var v = 1;
+  v++;
+}
+''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_isRead_notUsed_prefixExpr() async {
+    enableUnusedLocalVariable = true;
+    await assertErrorsInCode(r'''
+main() {
+  var v = 1;
+  ++v;
+}
+''', [HintCode.UNUSED_LOCAL_VARIABLE]);
+  }
+
+  test_isRead_usedArgument() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+main() {
+  var v = 1;
+  print(++v);
+}
+print(x) {}
+''');
+  }
+
+  test_isRead_usedInvocationTarget() async {
+    enableUnusedLocalVariable = true;
+    await assertNoErrorsInCode(r'''
+class A {
+  foo() {}
+}
+main() {
+  var a = new A();
+  a.foo();
+}
+''');
+  }
+}
diff --git a/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
index 2535989..7b9f834 100644
--- a/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/unused_shown_name_test.dart
@@ -10,11 +10,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UnusedShownNameTest_Driver);
+    defineReflectiveTests(UnusedShownNameTest);
   });
 }
 
-abstract class UnusedShownNameTest extends ResolverTestCase {
+@reflectiveTest
+class UnusedShownNameTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_unreferenced() async {
     Source source = addSource(r'''
 library L;
@@ -97,9 +101,3 @@
     verify([source, source2]);
   }
 }
-
-@reflectiveTest
-class UnusedShownNameTest_Driver extends UnusedShownNameTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
diff --git a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
index 5f7a014..dfe12c9 100644
--- a/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
+++ b/pkg/analyzer/test/src/diagnostics/use_of_void_result_test.dart
@@ -8,11 +8,15 @@
 
 main() {
   defineReflectiveSuite(() {
-    defineReflectiveTests(UseOfVoidResultTest_Driver);
+    defineReflectiveTests(UseOfVoidResultTest);
   });
 }
 
-abstract class UseOfVoidResultTest extends ResolverTestCase {
+@reflectiveTest
+class UseOfVoidResultTest extends ResolverTestCase {
+  @override
+  bool get enableNewAnalysisDriver => true;
+
   test_implicitReturnValue() async {
     await assertNoErrorsInCode(r'''
 f() {}
@@ -33,9 +37,3 @@
 ''');
   }
 }
-
-@reflectiveTest
-class UseOfVoidResultTest_Driver extends UseOfVoidResultTest {
-  @override
-  bool get enableNewAnalysisDriver => true;
-}
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 ebcd8d0..ad6a248 100644
--- a/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
+++ b/pkg/analyzer/test/src/fasta/recovery/missing_code_test.dart
@@ -57,9 +57,9 @@
 
   void test_missingColonAndValue_last() {
     testRecovery('''
-f() => {a };
+f() => {a: b, c };
 ''', [ParserErrorCode.EXPECTED_TOKEN, ParserErrorCode.MISSING_IDENTIFIER], '''
-f() => {a: _s_};
+f() => {a: b, c: _s_};
 ''');
   }
 
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 49e4be9..c8aed44 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
@@ -50,7 +50,8 @@
         contextUnit,
         analysisResult.session.declaredVariables,
         analysisResult.typeProvider,
-        analysisResult.typeSystem);
+        analysisResult.typeSystem,
+        analysisOptions);
   }
 
   void test_canBeConst_false_argument_invocation() async {
diff --git a/pkg/analyzer/test/src/services/available_declarations_test.dart b/pkg/analyzer/test/src/services/available_declarations_test.dart
index 8d2834a..2f03798 100644
--- a/pkg/analyzer/test/src/services/available_declarations_test.dart
+++ b/pkg/analyzer/test/src/services/available_declarations_test.dart
@@ -16,6 +16,10 @@
 main() {
   defineReflectiveSuite(() {
     defineReflectiveTests(AvailableDeclarationsTest);
+    defineReflectiveTests(ChangeFileTest);
+    defineReflectiveTests(DeclarationTest);
+    defineReflectiveTests(ExportTest);
+    defineReflectiveTests(GetLibrariesTest);
   });
 }
 
@@ -86,21 +90,133 @@
 }
 
 @reflectiveTest
-class AvailableDeclarationsTest extends AbstractContextTest {
-  DeclarationsTracker tracker;
+class AvailableDeclarationsTest extends _Base {
+  test_changesStream_noDuplicates() async {
+    newFile('/home/aaa/lib/a.dart', content: 'class A {}');
 
-  final List<LibraryChange> changes = [];
+    newFile('/home/bbb/pubspec.yaml', content: r'''
+dependencies:
+  aaa: any
+''');
+    addDotPackagesDependency('/home/bbb/.packages', 'aaa', '/home/aaa');
+    newFile('/home/bbb/lib/b.dart', content: 'class B {}');
 
-  final Map<int, Library> idToLibrary = {};
-  final Map<String, Library> uriToLibrary = {};
+    newFile('/home/ccc/pubspec.yaml', content: r'''
+dependencies:
+  aaa: any
+''');
+    addDotPackagesDependency('/home/ccc/.packages', 'aaa', '/home/aaa');
+    newFile('/home/ccc/lib/c.dart', content: 'class C {}');
 
-  @override
-  setUp() {
-    super.setUp();
-    _createTracker();
+    createAnalysisContexts();
+
+    var bPath = convertPath('/home/bbb');
+    var cPath = convertPath('/home/ccc');
+
+    var bAnalysisContext = analysisContextCollection.contextFor(bPath);
+    var cAnalysisContext = analysisContextCollection.contextFor(cPath);
+
+    tracker.addContext(bAnalysisContext);
+    tracker.addContext(cAnalysisContext);
+    await _doAllTrackerWork();
+
+    var uniquePathSet = Set<String>();
+    for (var change in changes) {
+      for (var library in change.changed) {
+        if (!uniquePathSet.add(library.path)) {
+          fail('Not unique path: ${library.path}');
+        }
+      }
+    }
   }
 
-  test_changeFile_added_exported() async {
+  test_discardContexts() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+class A {}
+''');
+
+    // No libraries initially.
+    expect(uriToLibrary, isEmpty);
+
+    // Add the context, and discard everything immediately.
+    tracker.addContext(testAnalysisContext);
+    tracker.discardContexts();
+
+    // There is no context.
+    expect(tracker.getContext(testAnalysisContext), isNull);
+
+    // There is no work to do.
+    expect(tracker.hasWork, isFalse);
+    await _doAllTrackerWork();
+
+    // So, there are no new libraries.
+    expect(uriToLibrary, isEmpty);
+  }
+
+  test_getContext() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+class B {}
+''');
+    var addContext = tracker.addContext(testAnalysisContext);
+    expect(tracker.getContext(testAnalysisContext), same(addContext));
+  }
+
+  test_getLibrary() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+class C {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+
+    var id = uriToLibrary['package:test/test.dart'].id;
+    var library = tracker.getLibrary(id);
+    expect(library.id, id);
+    expect(library.uriStr, 'package:test/test.dart');
+  }
+
+  test_readByteStore() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    newFile('/home/test/lib/b.dart', content: r'''
+class B {}
+''');
+    newFile('/home/test/lib/test.dart', content: r'''
+export 'a.dart' show A;
+part 'b.dart';
+class C {}
+enum E {v}
+''');
+
+    // The byte store is empty, fill it.
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    // Re-create tracker, will read from byte store.
+    _createTracker();
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    _assertHasLibrary('package:test/test.dart', declarations: [
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
+      _ExpectedDeclaration.enum_('E'),
+      _ExpectedDeclaration.enumConstant('v', 'E'),
+    ]);
+  }
+
+  static Future pumpEventQueue([int times = 5000]) {
+    if (times == 0) return new Future.value();
+    return new Future.delayed(Duration.zero, () => pumpEventQueue(times - 1));
+  }
+}
+
+@reflectiveTest
+class ChangeFileTest extends _Base {
+  test_added_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -121,15 +237,15 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasNoLibrary('package:test/c.dart');
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
 
     newFile(c, content: r'''
@@ -139,34 +255,34 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
   }
 
-  test_changeFile_added_library() async {
+  test_added_library() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
 
     newFile(a, content: r'''
 class A {}
 ''');
-    tracker.addContext(testAnalysisContext);
+    var declarationsContext = tracker.addContext(testAnalysisContext);
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
     ]);
     _assertHasNoLibrary('package:test/b.dart');
 
@@ -177,14 +293,22 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
     ]);
+
+    var librariesObject = declarationsContext.getLibraries(
+      '/home/test/lib/test.dart',
+    );
+    expect(
+      librariesObject.context.map((library) => library.uriStr).toSet(),
+      containsAll(['package:test/a.dart', 'package:test/b.dart']),
+    );
   }
 
-  test_changeFile_added_part() async {
+  test_added_part() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -200,11 +324,11 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
     ]);
     _assertHasNoLibrary('package:test/b.dart');
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
 
     newFile(b, content: r'''
@@ -215,16 +339,128 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasNoLibrary('package:test/b.dart');
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
   }
 
-  test_changeFile_deleted_exported() async {
+  test_chooseContext_inAnalysisRoot() async {
+    var homePath = convertPath('/home');
+    var testPath = convertPath('/home/test');
+    var filePath = convertPath('/home/test/lib/test.dart');
+
+    var homeContext = analysisContextCollection.contextFor(homePath);
+    var testContext = analysisContextCollection.contextFor(testPath);
+
+    tracker.addContext(homeContext);
+    tracker.addContext(testContext);
+    await _doAllTrackerWork();
+
+    newFile(filePath, content: 'class A {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('package:test/test.dart'),
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+
+    newFile(filePath, content: 'class B {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('package:test/test.dart'),
+      'B',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+  }
+
+  test_chooseContext_inPackage() async {
+    var homePath = convertPath('/home');
+    var testPath = convertPath('/home/test');
+    var filePath = convertPath('/packages/aaa/lib/a.dart');
+
+    newFile('/home/test/pubspec.yaml', content: r'''
+name: test
+dependencies:
+  aaa: any
+''');
+    addTestPackageDependency('aaa', '/packages/aaa');
+
+    var homeContext = analysisContextCollection.contextFor(homePath);
+    var testContext = analysisContextCollection.contextFor(testPath);
+
+    tracker.addContext(homeContext);
+    tracker.addContext(testContext);
+    await _doAllTrackerWork();
+
+    newFile(filePath, content: 'class A {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('package:aaa/a.dart'),
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:aaa/a.dart::A'],
+    );
+
+    newFile(filePath, content: 'class B {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('package:aaa/a.dart'),
+      'B',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:aaa/a.dart::B'],
+    );
+  }
+
+  test_chooseContext_inSdk() async {
+    var filePath = convertPath('/sdk/lib/math/math.dart');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    newFile(filePath, content: 'class A {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('dart:math'),
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['dart:math::A'],
+    );
+
+    newFile(filePath, content: 'class B {}');
+    uriToLibrary.clear();
+    tracker.changeFile(filePath);
+    await _doAllTrackerWork();
+
+    _assertDeclaration(
+      _getLibrary('dart:math'),
+      'B',
+      DeclarationKind.CLASS,
+      relevanceTags: ['dart:math::B'],
+    );
+  }
+
+  test_deleted_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -248,19 +484,19 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
 
     deleteFile(c);
@@ -268,19 +504,19 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasNoLibrary('package:test/c.dart');
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
   }
 
-  test_changeFile_deleted_library() async {
+  test_deleted_library() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
 
@@ -300,7 +536,7 @@
     _assertHasLibrary('package:test/b.dart');
   }
 
-  test_changeFile_deleted_part() async {
+  test_deleted_part() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -320,11 +556,11 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
 
     deleteFile(b);
@@ -332,14 +568,14 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
   }
 
-  test_changeFile_updated_exported() async {
+  test_updated_exported() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -363,19 +599,19 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
 
     newFile(c, content: r'''
@@ -385,23 +621,23 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C2'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
-      _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C2'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C2', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C2'),
     ]);
     _assertHasLibrary('package:test/d.dart', declarations: [
-      _ExpectedDeclaration('D', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('D'),
     ]);
   }
 
-  test_changeFile_updated_library() async {
+  test_updated_library() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
 
@@ -415,10 +651,10 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
     ]);
 
     newFile(a, content: r'''
@@ -428,14 +664,14 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A2', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A2'),
     ]);
     _assertHasLibrary('package:test/b.dart', declarations: [
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('B'),
     ]);
   }
 
-  test_changeFile_updated_part() async {
+  test_updated_part() async {
     var a = convertPath('/home/test/lib/a.dart');
     var b = convertPath('/home/test/lib/b.dart');
     var c = convertPath('/home/test/lib/c.dart');
@@ -455,11 +691,11 @@
 
     await _doAllTrackerWork();
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
 
     newFile(b, content: r'''
@@ -470,21 +706,426 @@
     await _doAllTrackerWork();
 
     _assertHasLibrary('package:test/a.dart', declarations: [
-      _ExpectedDeclaration('A', DeclarationKind.CLASS),
-      _ExpectedDeclaration('B2', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B2'),
     ]);
     _assertHasLibrary('package:test/c.dart', declarations: [
-      _ExpectedDeclaration('C', DeclarationKind.CLASS),
+      _ExpectedDeclaration.class_('C'),
     ]);
   }
+}
 
-  test_export() async {
-    newFile('/home/test/lib/a.dart', content: r'''
+@reflectiveTest
+class DeclarationTest extends _Base {
+  test_CLASS() async {
+    newFile('/home/test/lib/test.dart', content: r'''
 class A {}
+
+abstract class B {}
+
+@deprecated
+class C {}
+
+/// aaa
+///
+/// bbb bbb
+/// ccc ccc
+class D {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+    _assertDeclaration(
+      library,
+      'B',
+      DeclarationKind.CLASS,
+      isAbstract: true,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+    _assertDeclaration(
+      library,
+      'C',
+      DeclarationKind.CLASS,
+      isDeprecated: true,
+      relevanceTags: ['package:test/test.dart::C'],
+    );
+    _assertDeclaration(
+      library,
+      'D',
+      DeclarationKind.CLASS,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb\nccc ccc',
+      relevanceTags: ['package:test/test.dart::D'],
+    );
+  }
+
+  test_CLASS_TYPE_ALIAS() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+mixin M {}
+
+class A = Object with M;
+
+@deprecated
+class B = Object with M;
+
+/// aaa
+///
+/// bbb bbb
+class C = Object with M;
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.CLASS_TYPE_ALIAS,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+    _assertDeclaration(
+      library,
+      'B',
+      DeclarationKind.CLASS_TYPE_ALIAS,
+      isDeprecated: true,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+    _assertDeclaration(
+      library,
+      'C',
+      DeclarationKind.CLASS_TYPE_ALIAS,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      relevanceTags: ['package:test/test.dart::C'],
+    );
+  }
+
+  test_ENUM() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+enum A {v}
+
+@deprecated
+enum B {v}
+
+/// aaa
+///
+/// bbb bbb
+enum C {v}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.ENUM,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+    _assertDeclaration(
+      library,
+      'B',
+      DeclarationKind.ENUM,
+      isDeprecated: true,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+    _assertDeclaration(
+      library,
+      'C',
+      DeclarationKind.ENUM,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      relevanceTags: ['package:test/test.dart::C'],
+    );
+  }
+
+  test_ENUM_CONSTANT() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+enum MyEnum {
+  a,
+
+  @deprecated
+  b,
+
+  /// aaa
+  ///
+  /// bbb bbb
+  c
+}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'a',
+      DeclarationKind.ENUM_CONSTANT,
+      name2: 'MyEnum',
+      relevanceTags: ['package:test/test.dart::MyEnum'],
+    );
+    _assertDeclaration(
+      library,
+      'b',
+      DeclarationKind.ENUM_CONSTANT,
+      isDeprecated: true,
+      name2: 'MyEnum',
+      relevanceTags: ['package:test/test.dart::MyEnum'],
+    );
+    _assertDeclaration(
+      library,
+      'c',
+      DeclarationKind.ENUM_CONSTANT,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      name2: 'MyEnum',
+      relevanceTags: ['package:test/test.dart::MyEnum'],
+    );
+  }
+
+  test_FUNCTION() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+void a() {}
+
+@deprecated
+void b() {}
+
+/// aaa
+///
+/// bbb bbb
+void c() {}
+
+List<String> d(Map<String, int> p1, int p2, {double p3}) {}
+
+void e<T extends num, U>() {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(library, 'a', DeclarationKind.FUNCTION,
+        parameterNames: [],
+        parameters: '()',
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'b', DeclarationKind.FUNCTION,
+        isDeprecated: true,
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'c', DeclarationKind.FUNCTION,
+        docSummary: 'aaa',
+        docComplete: 'aaa\n\nbbb bbb',
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'd', DeclarationKind.FUNCTION,
+        parameters: '(Map<String, int> p1, int p2, {double p3})',
+        parameterNames: ['p1', 'p2', 'p3'],
+        parameterTypes: ['Map<String, int>', 'int', 'double'],
+        requiredParameterCount: 2,
+        returnType: 'List<String>');
+    _assertDeclaration(library, 'e', DeclarationKind.FUNCTION,
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        returnType: 'void',
+        typeParameters: '<T extends num, U>');
+  }
+
+  test_FUNCTION_TYPE_ALIAS() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+typedef A = void Function();
+
+@deprecated
+typedef B = void Function();
+
+/// aaa
+///
+/// bbb bbb
+typedef C = void Function();
+
+typedef D = int Function(int p1, [double p2, String p3]);
+
+typedef E = void Function(int, double, {String p3});
+
+typedef F = void Function<T extends num, U>();
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(library, 'A', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        relevanceTags: ['package:test/test.dart::A'],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'B', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        isDeprecated: true,
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        relevanceTags: ['package:test/test.dart::B'],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'C', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        docSummary: 'aaa',
+        docComplete: 'aaa\n\nbbb bbb',
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        relevanceTags: ['package:test/test.dart::C'],
+        requiredParameterCount: 0,
+        returnType: 'void');
+    _assertDeclaration(library, 'D', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        parameters: '(int p1, [double p2, String p3])',
+        parameterNames: ['p1', 'p2', 'p3'],
+        parameterTypes: ['int', 'double', 'String'],
+        relevanceTags: ['package:test/test.dart::D'],
+        requiredParameterCount: 1,
+        returnType: 'int');
+    _assertDeclaration(library, 'E', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        parameters: '(int, double, {String p3})',
+        parameterNames: ['', '', 'p3'],
+        parameterTypes: ['int', 'double', 'String'],
+        relevanceTags: ['package:test/test.dart::E'],
+        requiredParameterCount: 2,
+        returnType: 'void');
+    _assertDeclaration(library, 'F', DeclarationKind.FUNCTION_TYPE_ALIAS,
+        parameters: '()',
+        parameterNames: [],
+        parameterTypes: [],
+        requiredParameterCount: 0,
+        relevanceTags: ['package:test/test.dart::F'],
+        returnType: 'void',
+        typeParameters: '<T extends num, U>');
+  }
+
+  test_GETTER() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+int get a => 0;
+
+@deprecated
+int get b => 0;
+
+/// aaa
+///
+/// bbb bbb
+int get c => 0;
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(library, 'a', DeclarationKind.GETTER, returnType: 'int');
+    _assertDeclaration(
+      library,
+      'b',
+      DeclarationKind.GETTER,
+      isDeprecated: true,
+      returnType: 'int',
+    );
+    _assertDeclaration(
+      library,
+      'c',
+      DeclarationKind.GETTER,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      returnType: 'int',
+    );
+  }
+
+  test_library_isDeprecated() async {
+    newFile('/home/test/lib/a.dart', content: '');
+    newFile('/home/test/lib/b.dart', content: r'''
+@deprecated
+library my.lib;
+''');
+    newFile('/home/test/lib/c.dart', content: r'''
+@Deprecated('description')
+library my.lib;
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+
+    expect(uriToLibrary['package:test/a.dart'].isDeprecated, isFalse);
+    expect(uriToLibrary['package:test/b.dart'].isDeprecated, isTrue);
+    expect(uriToLibrary['package:test/c.dart'].isDeprecated, isTrue);
+  }
+
+  test_library_partDirective_empty() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+part ' ';
+
+class A {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+  }
+
+  test_library_partDirective_incomplete() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+part
+
+class A {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.CLASS,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+  }
+
+  test_library_parts() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+part of 'test.dart';
+class A {}
+''');
+    newFile('/home/test/lib/b.dart', content: r'''
+part of 'test.dart';
 class B {}
 ''');
     newFile('/home/test/lib/test.dart', content: r'''
-export 'a.dart';
+part 'a.dart';
+part 'b.dart';
 class C {}
 ''');
     tracker.addContext(testAnalysisContext);
@@ -497,7 +1138,189 @@
     ]);
   }
 
-  test_export_combinators_hide() async {
+  test_library_publicOnly() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+part of 'test.dart';
+class A {}
+class _A {}
+''');
+    newFile('/home/test/lib/test.dart', content: r'''
+part 'a.dart';
+class B {}
+class _B {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/test.dart', declarations: [
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+    ]);
+  }
+
+  test_location() async {
+    var code = r'''
+class A {}
+
+class B {}
+''';
+    var testPath = newFile('/home/test/lib/test.dart', content: code).path;
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.CLASS,
+      locationOffset: code.indexOf('A {}'),
+      locationPath: testPath,
+      locationStartColumn: 7,
+      locationStartLine: 1,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+    _assertDeclaration(
+      library,
+      'B',
+      DeclarationKind.CLASS,
+      locationOffset: code.indexOf('B {}'),
+      locationPath: testPath,
+      locationStartColumn: 7,
+      locationStartLine: 3,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+  }
+
+  test_MIXIN() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+mixin A {}
+
+@deprecated
+mixin B {}
+
+/// aaa
+///
+/// bbb bbb
+/// ccc ccc
+mixin C {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'A',
+      DeclarationKind.MIXIN,
+      relevanceTags: ['package:test/test.dart::A'],
+    );
+    _assertDeclaration(
+      library,
+      'B',
+      DeclarationKind.MIXIN,
+      isDeprecated: true,
+      relevanceTags: ['package:test/test.dart::B'],
+    );
+    _assertDeclaration(
+      library,
+      'C',
+      DeclarationKind.MIXIN,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb\nccc ccc',
+      relevanceTags: ['package:test/test.dart::C'],
+    );
+  }
+
+  test_SETTER() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+set a(int value) {}
+
+@deprecated
+set b(int value) {}
+
+/// aaa
+///
+/// bbb bbb
+set c(int value) {}
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(
+      library,
+      'a',
+      DeclarationKind.SETTER,
+      parameters: '(int value)',
+      parameterNames: ['value'],
+      parameterTypes: ['int'],
+      requiredParameterCount: 1,
+    );
+    _assertDeclaration(
+      library,
+      'b',
+      DeclarationKind.SETTER,
+      isDeprecated: true,
+      parameters: '(int value)',
+      parameterNames: ['value'],
+      parameterTypes: ['int'],
+      requiredParameterCount: 1,
+    );
+    _assertDeclaration(
+      library,
+      'c',
+      DeclarationKind.SETTER,
+      docSummary: 'aaa',
+      docComplete: 'aaa\n\nbbb bbb',
+      parameters: '(int value)',
+      parameterNames: ['value'],
+      parameterTypes: ['int'],
+      requiredParameterCount: 1,
+    );
+  }
+
+  test_VARIABLE() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+int a;
+
+@deprecated
+int b;
+
+/// aaa
+///
+/// bbb bbb
+int c;
+
+const d = 0;
+
+final double e = 2.7;
+''');
+
+    tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var library = _getLibrary('package:test/test.dart');
+    _assertDeclaration(library, 'a', DeclarationKind.VARIABLE,
+        returnType: 'int');
+    _assertDeclaration(library, 'b', DeclarationKind.VARIABLE,
+        isDeprecated: true, returnType: 'int');
+    _assertDeclaration(library, 'c', DeclarationKind.VARIABLE,
+        docSummary: 'aaa', docComplete: 'aaa\n\nbbb bbb', returnType: 'int');
+    _assertDeclaration(library, 'd', DeclarationKind.VARIABLE,
+        isConst: true, relevanceTags: ['dart:core::int'], returnType: '');
+    _assertDeclaration(library, 'e', DeclarationKind.VARIABLE,
+        isFinal: true,
+        relevanceTags: ['dart:core::double'],
+        returnType: 'double');
+  }
+}
+
+@reflectiveTest
+class ExportTest extends _Base {
+  test_combinators_hide() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
 class B {}
@@ -517,7 +1340,7 @@
     ]);
   }
 
-  test_export_combinators_show() async {
+  test_combinators_show() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
 class B {}
@@ -536,7 +1359,24 @@
     ]);
   }
 
-  test_export_cycle() async {
+  test_combinators_show_enum() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+enum E1 {a}
+enum E2 {b}
+''');
+    newFile('/home/test/lib/test.dart', content: r'''
+export 'a.dart' show E1;
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/test.dart', declarations: [
+      _ExpectedDeclaration.enum_('E1'),
+      _ExpectedDeclaration.enumConstant('a', 'E1'),
+    ]);
+  }
+
+  test_cycle() async {
     newFile('/home/test/lib/a.dart', content: r'''
 export 'b.dart';
 class A {}
@@ -570,7 +1410,25 @@
     ]);
   }
 
-  test_export_missing() async {
+  test_enum() async {
+    newFile('/home/test/lib/test.dart', content: r'''
+enum E1 {a, b}
+enum E2 {a, b}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/test.dart', declarations: [
+      _ExpectedDeclaration.enum_('E1'),
+      _ExpectedDeclaration.enumConstant('a', 'E1'),
+      _ExpectedDeclaration.enumConstant('b', 'E1'),
+      _ExpectedDeclaration.enum_('E2'),
+      _ExpectedDeclaration.enumConstant('a', 'E2'),
+      _ExpectedDeclaration.enumConstant('b', 'E2'),
+    ]);
+  }
+
+  test_missing() async {
     newFile('/home/test/lib/test.dart', content: r'''
 export 'a.dart';
 class C {}
@@ -583,7 +1441,7 @@
     ]);
   }
 
-  test_export_sequence() async {
+  test_sequence() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
 ''');
@@ -615,7 +1473,7 @@
     ]);
   }
 
-  test_export_shadowedByLocal() async {
+  test_shadowedByLocal() async {
     newFile('/home/test/lib/a.dart', content: r'''
 class A {}
 class B {}
@@ -634,7 +1492,29 @@
     ]);
   }
 
-  test_getLibraries_bazel() async {
+  test_simple() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+class B {}
+''');
+    newFile('/home/test/lib/test.dart', content: r'''
+export 'a.dart';
+class C {}
+''');
+    tracker.addContext(testAnalysisContext);
+
+    await _doAllTrackerWork();
+    _assertHasLibrary('package:test/test.dart', declarations: [
+      _ExpectedDeclaration.class_('A'),
+      _ExpectedDeclaration.class_('B'),
+      _ExpectedDeclaration.class_('C'),
+    ]);
+  }
+}
+
+@reflectiveTest
+class GetLibrariesTest extends _Base {
+  test_bazel() async {
     newFile('/home/aaa/lib/a.dart', content: 'class A {}');
     newFile('/home/aaa/lib/src/a2.dart', content: 'class A2 {}');
 
@@ -698,7 +1578,7 @@
       _ExpectedDeclaration.class_('MaterialButton'),
     ]);
     _assertHasLibrary(
-      toUri('/home/material_button/test/button_test.dart').toString(),
+      toUriStr('/home/material_button/test/button_test.dart'),
       declarations: [
         _ExpectedDeclaration.class_('MaterialButtonTest'),
       ],
@@ -747,7 +1627,7 @@
         libraries.context,
         uriList: [
           'package:material_button/button.dart',
-          toUri('/home/material_button/test/button_test.dart').toString(),
+          toUriStr('/home/material_button/test/button_test.dart'),
         ],
         only: true,
       );
@@ -778,7 +1658,64 @@
     }
   }
 
-  test_getLibraries_pub() async {
+  test_excludeSelf() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+    var c = convertPath('/home/test/lib/c.dart');
+
+    newFile(a);
+    newFile(b);
+    newFile(c);
+
+    var context = tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var aList = _uriListOfContextLibraries(context, a);
+    expect(
+      aList,
+      unorderedEquals([
+        'package:test/b.dart',
+        'package:test/c.dart',
+      ]),
+    );
+
+    var bList = _uriListOfContextLibraries(context, b);
+    expect(
+      bList,
+      unorderedEquals([
+        'package:test/a.dart',
+        'package:test/c.dart',
+      ]),
+    );
+  }
+
+  test_excludeSelf_part() async {
+    var a = convertPath('/home/test/lib/a.dart');
+    var b = convertPath('/home/test/lib/b.dart');
+    var c = convertPath('/home/test/lib/c.dart');
+
+    newFile(a, content: r'''
+part 'b.dart';
+''');
+    newFile(b, content: r'''
+part of 'a.dart';
+''');
+    newFile(c);
+
+    var context = tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var aList = _uriListOfContextLibraries(context, a);
+    expect(aList, unorderedEquals(['package:test/c.dart']));
+
+    var bList = _uriListOfContextLibraries(context, b);
+    expect(bList, unorderedEquals(['package:test/c.dart']));
+
+    var cList = _uriListOfContextLibraries(context, c);
+    expect(cList, unorderedEquals(['package:test/a.dart']));
+  }
+
+  test_pub() async {
     newFile('/home/aaa/lib/a.dart', content: 'class A {}');
     newFile('/home/aaa/lib/src/a2.dart', content: 'class A2 {}');
 
@@ -887,7 +1824,7 @@
         uriList: [
           'package:test/t.dart',
           'package:test/src/t2.dart',
-          toUri('/home/test/bin/t3.dart').toString(),
+          toUriStr('/home/test/bin/t3.dart'),
         ],
         only: true,
       );
@@ -914,7 +1851,7 @@
         uriList: [
           'package:test/t.dart',
           'package:test/src/t2.dart',
-          toUri('/home/test/test/t4.dart').toString(),
+          toUriStr('/home/test/test/t4.dart'),
         ],
         only: true,
       );
@@ -946,7 +1883,21 @@
     }
   }
 
-  test_getLibraries_setDependencies() async {
+  test_sdk_excludesPrivate() async {
+    newFile('/home/test/lib/test.dart', content: '');
+
+    var context = tracker.addContext(testAnalysisContext);
+    await _doAllTrackerWork();
+
+    var path = convertPath('/home/test/lib/_.dart');
+    var libraries = context.getLibraries(path);
+    expect(
+      libraries.sdk.where((library) => library.uriStr.startsWith('dart:_')),
+      isEmpty,
+    );
+  }
+
+  test_setDependencies() async {
     newFile('/home/aaa/lib/a.dart', content: r'''
 export 'src/a2.dart' show A2;
 class A1 {}
@@ -992,7 +1943,7 @@
       _ExpectedDeclaration.class_('T2'),
     ]);
     _assertHasLibrary(
-      toUri('/home/test/test/t3.dart').toString(),
+      toUriStr('/home/test/test/t3.dart'),
       declarations: [
         _ExpectedDeclaration.class_('T3'),
       ],
@@ -1013,7 +1964,7 @@
         uriList: [
           'package:test/t.dart',
           'package:test/src/t2.dart',
-          toUri('/home/test/test/t3.dart').toString(),
+          toUriStr('/home/test/test/t3.dart'),
         ],
         only: true,
       );
@@ -1037,14 +1988,14 @@
         uriList: [
           'package:test/t.dart',
           'package:test/src/t2.dart',
-          toUri('/home/test/test/t3.dart').toString(),
+          toUriStr('/home/test/test/t3.dart'),
         ],
         only: true,
       );
     }
   }
 
-  test_getLibraries_setDependencies_twice() async {
+  test_setDependencies_twice() async {
     newFile('/home/aaa/lib/a.dart', content: r'''
 class A {}
 ''');
@@ -1109,129 +2060,93 @@
     }
   }
 
-  test_kindsOfDeclarations() async {
-    newFile('/home/test/lib/test.dart', content: r'''
-class MyClass {}
-class MyClassTypeAlias = Object with MyMixin;
-enum MyEnum {a, b, c}
-void myFunction() {}
-typedef MyFunctionTypeAlias = void Function();
-mixin MyMixin {}
-var myVariable1, myVariable2;
-''');
-    tracker.addContext(testAnalysisContext);
-
-    await _doAllTrackerWork();
-    _assertHasLibrary('package:test/test.dart', declarations: [
-      _ExpectedDeclaration.class_('MyClass'),
-      _ExpectedDeclaration.classTypeAlias('MyClassTypeAlias'),
-      _ExpectedDeclaration.enum_('MyEnum'),
-      _ExpectedDeclaration.function('myFunction'),
-      _ExpectedDeclaration.functionTypeAlias('MyFunctionTypeAlias'),
-      _ExpectedDeclaration.mixin('MyMixin'),
-      _ExpectedDeclaration.variable('myVariable1'),
-      _ExpectedDeclaration.variable('myVariable2'),
-    ]);
+  static void _assertHasLibraries(List<Library> libraries,
+      {@required List<String> uriList, bool only = false}) {
+    var actualUriList = libraries.map((lib) => lib.uriStr).toList();
+    if (only) {
+      expect(actualUriList, unorderedEquals(uriList));
+    } else {
+      expect(actualUriList, containsAll(uriList));
+    }
   }
 
-  test_parts() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-part of 'test.dart';
-class A {}
-''');
-    newFile('/home/test/lib/b.dart', content: r'''
-part of 'test.dart';
-class B {}
-''');
-    newFile('/home/test/lib/test.dart', content: r'''
-part 'a.dart';
-part 'b.dart';
-class C {}
-''');
-    tracker.addContext(testAnalysisContext);
-
-    await _doAllTrackerWork();
-    _assertHasLibrary('package:test/test.dart', declarations: [
-      _ExpectedDeclaration.class_('A'),
-      _ExpectedDeclaration.class_('B'),
-      _ExpectedDeclaration.class_('C'),
-    ]);
+  static List<String> _uriListOfContextLibraries(
+    DeclarationsContext context,
+    String path,
+  ) {
+    return context.getLibraries(path).context.map((l) => l.uriStr).toList();
   }
+}
 
-  test_publicOnly() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-part of 'test.dart';
-class A {}
-class _A {}
-''');
-    newFile('/home/test/lib/test.dart', content: r'''
-part 'a.dart';
-class B {}
-class _B {}
-''');
-    tracker.addContext(testAnalysisContext);
+class _Base extends AbstractContextTest {
+  DeclarationsTracker tracker;
 
-    await _doAllTrackerWork();
-    _assertHasLibrary('package:test/test.dart', declarations: [
-      _ExpectedDeclaration.class_('A'),
-      _ExpectedDeclaration.class_('B'),
-    ]);
-  }
+  final List<LibraryChange> changes = [];
 
-  test_readByteStore() async {
-    newFile('/home/test/lib/a.dart', content: r'''
-class A {}
-''');
-    newFile('/home/test/lib/b.dart', content: r'''
-class B {}
-''');
-    newFile('/home/test/lib/test.dart', content: r'''
-export 'a.dart' show A;
-part 'b.dart';
-class C {}
-''');
+  final Map<int, Library> idToLibrary = {};
+  final Map<String, Library> uriToLibrary = {};
 
-    // The byte store is empty, fill it.
-    tracker.addContext(testAnalysisContext);
-    await _doAllTrackerWork();
-
-    // Re-create tracker, will read from byte store.
+  @override
+  setUp() {
+    super.setUp();
     _createTracker();
-    tracker.addContext(testAnalysisContext);
-    await _doAllTrackerWork();
-
-    _assertHasLibrary('package:test/test.dart', declarations: [
-      _ExpectedDeclaration.class_('A'),
-      _ExpectedDeclaration.class_('B'),
-      _ExpectedDeclaration.class_('C'),
-    ]);
   }
 
-  test_removeContext_afterAddContext() async {
-    newFile('/home/test/lib/test.dart', content: r'''
-class A {}
-''');
-
-    // No libraries initially.
-    expect(uriToLibrary, isEmpty);
-
-    // Add the context, and remove it immediately.
-    tracker.addContext(testAnalysisContext);
-    tracker.removeContext(testAnalysisContext);
-
-    // There is no work to do.
-    expect(tracker.hasWork, isFalse);
-    await _doAllTrackerWork();
-
-    // So, there are no new libraries.
-    expect(uriToLibrary, isEmpty);
+  void _assertDeclaration(
+    Library library,
+    String name,
+    DeclarationKind kind, {
+    String docComplete,
+    String docSummary,
+    bool isAbstract = false,
+    bool isConst = false,
+    bool isDeprecated = false,
+    bool isFinal = false,
+    int locationOffset,
+    String locationPath,
+    int locationStartColumn,
+    int locationStartLine,
+    String name2,
+    String parameters,
+    List<String> parameterNames,
+    List<String> parameterTypes,
+    List<String> relevanceTags,
+    int requiredParameterCount,
+    String returnType,
+    String typeParameters,
+  }) {
+    var declaration = _getDeclaration(library, name);
+    expect(declaration.docComplete, docComplete);
+    expect(declaration.docSummary, docSummary);
+    expect(declaration.name, name);
+    expect(declaration.name2, name2);
+    expect(declaration.kind, kind);
+    expect(declaration.isAbstract, isAbstract);
+    expect(declaration.isConst, isConst);
+    expect(declaration.isDeprecated, isDeprecated);
+    expect(declaration.isFinal, isFinal);
+    expect(declaration.parameters, parameters);
+    expect(declaration.parameterNames, parameterNames);
+    expect(declaration.parameterTypes, parameterTypes);
+    expect(declaration.relevanceTags, relevanceTags);
+    expect(declaration.requiredParameterCount, requiredParameterCount);
+    expect(declaration.returnType, returnType);
+    expect(declaration.typeParameters, typeParameters);
+    if (locationOffset != null) {
+      expect(declaration.locationOffset, locationOffset);
+      expect(declaration.locationPath, locationPath);
+      expect(declaration.locationStartColumn, locationStartColumn);
+      expect(declaration.locationStartLine, locationStartLine);
+    }
   }
 
   void _assertHasDeclaration(Library library, _ExpectedDeclaration expected) {
     expect(
       library.declarations,
       contains(predicate((Declaration d) {
-        return d.name == expected.name && d.kind == expected.kind;
+        return d.name == expected.name &&
+            d.name2 == expected.name2 &&
+            d.kind == expected.kind;
       })),
       reason: '$expected',
     );
@@ -1264,9 +2179,8 @@
     tracker.changes.listen((change) {
       changes.add(change);
       for (var library in change.changed) {
-        var uriStr = library.uri.toString();
         idToLibrary[library.id] = library;
-        uriToLibrary[uriStr] = library;
+        uriToLibrary[library.uriStr] = library;
       }
       idToLibrary.removeWhere((uriStr, library) {
         return change.removed.contains(library.id);
@@ -1284,53 +2198,55 @@
     await pumpEventQueue();
   }
 
-  static Future pumpEventQueue([int times = 5000]) {
-    if (times == 0) return new Future.value();
-    return new Future.delayed(Duration.zero, () => pumpEventQueue(times - 1));
+  Declaration _getDeclaration(Library library, String name) {
+    return library.declarations
+        .singleWhere((declaration) => declaration.name == name);
   }
 
-  static void _assertHasLibraries(List<Library> libraries,
-      {@required List<String> uriList, bool only = false}) {
-    var actualUriList = libraries.map((lib) => lib.uri.toString()).toList();
-    if (only) {
-      expect(actualUriList, unorderedEquals(uriList));
-    } else {
-      expect(actualUriList, containsAll(uriList));
-    }
+  Library _getLibrary(String uriStr) {
+    var library = uriToLibrary[uriStr];
+    expect(library, isNotNull);
+    return library;
   }
 }
 
-//class _ExpectedLibrary {
-//  final Uri uri;
-//  final String path;
-//}
-
 class _ExpectedDeclaration {
-  final String name;
   final DeclarationKind kind;
+  final String name;
+  final String name2;
 
-  _ExpectedDeclaration(this.name, this.kind);
+  _ExpectedDeclaration(this.kind, this.name, this.name2);
 
-  _ExpectedDeclaration.class_(String name) : this(name, DeclarationKind.CLASS);
+  _ExpectedDeclaration.class_(String name)
+      : this(DeclarationKind.CLASS, name, null);
 
   _ExpectedDeclaration.classTypeAlias(String name)
-      : this(name, DeclarationKind.CLASS_TYPE_ALIAS);
+      : this(DeclarationKind.CLASS_TYPE_ALIAS, name, null);
 
-  _ExpectedDeclaration.enum_(String name) : this(name, DeclarationKind.ENUM);
+  _ExpectedDeclaration.enum_(String name)
+      : this(DeclarationKind.ENUM, name, null);
+
+  _ExpectedDeclaration.enumConstant(String name, String name2)
+      : this(DeclarationKind.ENUM_CONSTANT, name, name2);
 
   _ExpectedDeclaration.function(String name)
-      : this(name, DeclarationKind.FUNCTION);
+      : this(DeclarationKind.FUNCTION, name, null);
 
   _ExpectedDeclaration.functionTypeAlias(String name)
-      : this(name, DeclarationKind.FUNCTION_TYPE_ALIAS);
+      : this(DeclarationKind.FUNCTION_TYPE_ALIAS, name, null);
 
-  _ExpectedDeclaration.mixin(String name) : this(name, DeclarationKind.MIXIN);
+  _ExpectedDeclaration.mixin(String name)
+      : this(DeclarationKind.MIXIN, name, null);
 
   _ExpectedDeclaration.variable(String name)
-      : this(name, DeclarationKind.VARIABLE);
+      : this(DeclarationKind.VARIABLE, name, null);
 
   @override
   String toString() {
-    return '($name, $kind)';
+    if (name2 != null) {
+      return '($kind, $name, $name2)';
+    } else {
+      return '($kind, $name)';
+    }
   }
 }
diff --git a/pkg/analyzer/test/src/summary/resynthesize_common.dart b/pkg/analyzer/test/src/summary/resynthesize_common.dart
index 186beca..dd5daa7 100644
--- a/pkg/analyzer/test/src/summary/resynthesize_common.dart
+++ b/pkg/analyzer/test/src/summary/resynthesize_common.dart
@@ -30,6 +30,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../generated/test_support.dart';
+import '../../util/element_type_matchers.dart';
 import '../abstract_single_unit.dart';
 import 'element_text.dart';
 import 'test_strategies.dart';
@@ -9796,7 +9797,7 @@
           reason: desc);
       if (original.element.enclosingElement == null &&
           original.element is FunctionElement) {
-        expect(resynthesized.element, new TypeMatcher<FunctionElement>());
+        expect(resynthesized.element, isFunctionElement);
         expect(resynthesized.element.enclosingElement, isNull, reason: desc);
         compareFunctionElements(
             resynthesized.element, original.element, '$desc.element',
diff --git a/pkg/analyzer/test/src/task/strong/checker_test.dart b/pkg/analyzer/test/src/task/strong/checker_test.dart
index be924cf..f46df08 100644
--- a/pkg/analyzer/test/src/task/strong/checker_test.dart
+++ b/pkg/analyzer/test/src/task/strong/checker_test.dart
@@ -3983,7 +3983,10 @@
 
     SubClonable<T> s = object;
     takesSubClonable<T>(object);
-    h(object);
+    // Issue #35799: According to the language team, this should work, but both
+    // analyzer and CFE currently reject it, likely due to a strange
+    // representation of promoted type variables.
+    // h(object);
   }
 }
 ''');
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 c443700..80c62f1 100644
--- a/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
+++ b/pkg/analyzer/test/src/task/strong/inferred_type_test.dart
@@ -21,71 +21,6 @@
   });
 }
 
-@reflectiveTest
-class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
-  @override
-  bool get mayCheckTypesOfLocals => true;
-
-  @override
-  Future<CompilationUnitElement> checkFileElement(String content) async {
-    CompilationUnit unit = await checkFile(content);
-    return unit.declaredElement;
-  }
-
-  @override
-  @failingTest
-  test_circularReference_viaClosures() {
-    return super.test_circularReference_viaClosures();
-  }
-
-  @override
-  @failingTest
-  test_circularReference_viaClosures_initializerTypes() {
-    return super.test_circularReference_viaClosures_initializerTypes();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error1() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error1();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error2() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error2();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_error3() {
-    // Test doesn't work with the old task model
-    return super.test_instantiateToBounds_typeName_error3();
-  }
-
-  @override
-  @failingTest
-  test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
-    return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
-  }
-
-  @override
-  @failingTest
-  test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
-    return super
-        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
-  }
-
-  @failingTest
-  @override
-  test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
-    return super
-        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
-  }
-}
-
 mixin InferredTypeMixin {
   /// Extra top-level errors if needed due to being analyze multiple times.
   bool get hasExtraTaskModelPass => true;
@@ -1570,7 +1505,7 @@
 Iterable<Map<int, int>> bar() sync* {
   yield /*info:INFERRED_TYPE_LITERAL*/{};
   yield /*error:YIELD_OF_INVALID_TYPE*/new List();
-  yield* /*error:YIELD_OF_INVALID_TYPE*/{};
+  yield* {};
   yield* /*info:INFERRED_TYPE_ALLOCATION*/new List();
 }
 ''');
@@ -4457,6 +4392,71 @@
 }
 
 @reflectiveTest
+class InferredTypeTest extends AbstractStrongTest with InferredTypeMixin {
+  @override
+  bool get mayCheckTypesOfLocals => true;
+
+  @override
+  Future<CompilationUnitElement> checkFileElement(String content) async {
+    CompilationUnit unit = await checkFile(content);
+    return unit.declaredElement;
+  }
+
+  @override
+  @failingTest
+  test_circularReference_viaClosures() {
+    return super.test_circularReference_viaClosures();
+  }
+
+  @override
+  @failingTest
+  test_circularReference_viaClosures_initializerTypes() {
+    return super.test_circularReference_viaClosures_initializerTypes();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_typeName_error1() {
+    // Test doesn't work with the old task model
+    return super.test_instantiateToBounds_typeName_error1();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_typeName_error2() {
+    // Test doesn't work with the old task model
+    return super.test_instantiateToBounds_typeName_error2();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_typeName_error3() {
+    // Test doesn't work with the old task model
+    return super.test_instantiateToBounds_typeName_error3();
+  }
+
+  @override
+  @failingTest
+  test_instantiateToBounds_typeName_OK_hasBound_definedAfter() {
+    return super.test_instantiateToBounds_typeName_OK_hasBound_definedAfter();
+  }
+
+  @override
+  @failingTest
+  test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1() {
+    return super
+        .test_unsafeBlockClosureInference_functionCall_explicitDynamicParam_viaExpr1();
+  }
+
+  @failingTest
+  @override
+  test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1() {
+    return super
+        .test_unsafeBlockClosureInference_functionCall_explicitTypeParam_viaExpr1();
+  }
+}
+
+@reflectiveTest
 class InferredTypeTest_Driver extends AbstractStrongTest
     with InferredTypeMixin {
   @override
diff --git a/pkg/analyzer/test/src/workspace/package_build_test.dart b/pkg/analyzer/test/src/workspace/package_build_test.dart
index 71a2cf0..7fd9011 100644
--- a/pkg/analyzer/test/src/workspace/package_build_test.dart
+++ b/pkg/analyzer/test/src/workspace/package_build_test.dart
@@ -489,7 +489,6 @@
   PackageBuildWorkspace _createPackageBuildWorkspace() {
     final contextBuilder = new MockContextBuilder();
     final packagesForWorkspace = new MockPackages();
-    final packageMapForWorkspace = <String, List<Folder>>{'project': []};
     contextBuilder.packagesMapMap[convertPath('/workspace')] =
         packagesForWorkspace;
     contextBuilder.packagesToMapMap[packagesForWorkspace] = {
diff --git a/pkg/analyzer/tool/messages/generate.dart b/pkg/analyzer/tool/messages/generate.dart
index b0e7c53..a88a897 100644
--- a/pkg/analyzer/tool/messages/generate.dart
+++ b/pkg/analyzer/tool/messages/generate.dart
@@ -15,7 +15,7 @@
 import 'dart:io';
 
 import 'package:analyzer/error/error.dart';
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:analyzer/src/dart/error/syntactic_errors.dart';
 import 'package:front_end/src/testing/package_root.dart' as pkgRoot;
 import 'package:front_end/src/fasta/scanner.dart';
diff --git a/pkg/analyzer/tool/summary/check_test.dart b/pkg/analyzer/tool/summary/check_test.dart
index c7ddf9e..ff689ba 100644
--- a/pkg/analyzer/tool/summary/check_test.dart
+++ b/pkg/analyzer/tool/summary/check_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:front_end/src/testing/package_root.dart' as package_root;
 import 'package:path/path.dart';
 
diff --git a/pkg/analyzer/tool/summary/generate.dart b/pkg/analyzer/tool/summary/generate.dart
index d99b76a..d4d5157 100644
--- a/pkg/analyzer/tool/summary/generate.dart
+++ b/pkg/analyzer/tool/summary/generate.dart
@@ -20,7 +20,7 @@
 import 'dart:convert';
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:analyzer/src/dart/analysis/experiments.dart';
 import 'package:front_end/src/fasta/scanner/string_scanner.dart';
 import 'package:front_end/src/scanner/token.dart' show Token;
diff --git a/pkg/analyzer/tool/task_dependency_graph/check_test.dart b/pkg/analyzer/tool/task_dependency_graph/check_test.dart
index 3452f40..efc365d 100644
--- a/pkg/analyzer/tool/task_dependency_graph/check_test.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/check_test.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:front_end/src/testing/package_root.dart' as package_root;
 import 'package:path/path.dart';
 
diff --git a/pkg/analyzer/tool/task_dependency_graph/generate.dart b/pkg/analyzer/tool/task_dependency_graph/generate.dart
index 3a9aa7b..da4e3a9 100644
--- a/pkg/analyzer/tool/task_dependency_graph/generate.dart
+++ b/pkg/analyzer/tool/task_dependency_graph/generate.dart
@@ -19,13 +19,13 @@
 import 'dart:io' hide File;
 import 'dart:io' as io;
 
+import 'package:analysis_tool/tools.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/file_system/physical_file_system.dart';
-import 'package:analyzer/src/codegen/tools.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_cli/lib/src/build_mode.dart b/pkg/analyzer_cli/lib/src/build_mode.dart
index 2c64108..ee2a239 100644
--- a/pkg/analyzer_cli/lib/src/build_mode.dart
+++ b/pkg/analyzer_cli/lib/src/build_mode.dart
@@ -193,11 +193,17 @@
   PackageBundleAssembler assembler;
   final Map<String, UnlinkedUnit> uriToUnit = <String, UnlinkedUnit>{};
 
+  // May be null.
+  final DependencyTracker dependencyTracker;
+
   BuildMode(this.resourceProvider, this.options, this.stats, this.contextCache,
       {PerformanceLog logger, PackageBundleProvider packageBundleProvider})
       : logger = logger ?? new PerformanceLog(null),
         packageBundleProvider = packageBundleProvider ??
-            new DirectPackageBundleProvider(resourceProvider);
+            new DirectPackageBundleProvider(resourceProvider),
+        dependencyTracker = options.summaryDepsOutput != null
+            ? DependencyTracker(options.summaryDepsOutput)
+            : null;
 
   bool get _shouldOutputSummary =>
       options.buildSummaryOutput != null ||
@@ -306,6 +312,11 @@
         }
       }
 
+      if (dependencyTracker != null) {
+        io.File file = new io.File(dependencyTracker.outputPath);
+        file.writeAsStringSync(dependencyTracker.dependencies.join('\n'));
+      }
+
       if (options.buildSummaryOnly) {
         return ErrorSeverity.NONE;
       } else {
@@ -323,11 +334,25 @@
    */
   void _computeLinkedLibraries(Set<String> libraryUris) {
     logger.run('Link output summary', () {
-      LinkedLibrary getDependency(String absoluteUri) =>
-          summaryDataStore.linkedMap[absoluteUri];
+      void trackDependency(String absoluteUri) {
+        if (dependencyTracker != null) {
+          var summaryUri = summaryDataStore.uriToSummaryPath[absoluteUri];
+          if (summaryUri != null) {
+            dependencyTracker.record(summaryUri);
+          }
+        }
+      }
 
-      UnlinkedUnit getUnit(String absoluteUri) =>
-          summaryDataStore.unlinkedMap[absoluteUri] ?? uriToUnit[absoluteUri];
+      LinkedLibrary getDependency(String absoluteUri) {
+        trackDependency(absoluteUri);
+        return summaryDataStore.linkedMap[absoluteUri];
+      }
+
+      UnlinkedUnit getUnit(String absoluteUri) {
+        trackDependency(absoluteUri);
+        return summaryDataStore.unlinkedMap[absoluteUri] ??
+            uriToUnit[absoluteUri];
+      }
 
       Map<String, LinkedLibraryBuilder> linkResult = link(libraryUris,
           getDependency, getUnit, analysisDriver.declaredVariables.get);
@@ -694,3 +719,19 @@
     return cache.get(inputs, path);
   }
 }
+
+/**
+ * Tracks paths to dependencies, really just a thin api around a Set<String>.
+ */
+class DependencyTracker {
+  final _dependencies = Set<String>();
+
+  Iterable<String> get dependencies => _dependencies;
+
+  /// The path to the file to create once tracking is done.
+  final String outputPath;
+
+  DependencyTracker(this.outputPath);
+
+  void record(String path) => _dependencies.add(path);
+}
diff --git a/pkg/analyzer_cli/lib/src/options.dart b/pkg/analyzer_cli/lib/src/options.dart
index 81712bc..6330d84 100644
--- a/pkg/analyzer_cli/lib/src/options.dart
+++ b/pkg/analyzer_cli/lib/src/options.dart
@@ -150,6 +150,10 @@
   /// Dart analyzer snapshot.
   final bool trainSnapshot;
 
+  /// Path to a file to dump summary dependency information to for any given
+  /// build.
+  final String summaryDepsOutput;
+
   /// Initialize options from the given parsed [args].
   CommandLineOptions._fromArgs(ArgResults args)
       : buildAnalysisOutput = cast(args['build-analysis-output']),
@@ -191,7 +195,8 @@
         lintsAreFatal = cast(args['fatal-lints']),
         trainSnapshot = cast(args['train-snapshot']),
         verbose = cast(args['verbose']),
-        color = cast(args['color']);
+        color = cast(args['color']),
+        summaryDepsOutput = cast(args['summary-deps-output']);
 
   /// The path to an analysis options file
   String get analysisOptionsFile =>
@@ -405,6 +410,9 @@
       ..addFlag('color',
           help: 'Use ansi colors when printing messages.',
           defaultsTo: ansi.terminalSupportsAnsi(),
+          hide: hide)
+      ..addOption('summary-deps-output',
+          help: 'Path to a file to dump summary dependency info to.',
           hide: hide);
 
     // Hidden flags.
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
index d1ab672..5ce4c0e 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/change_builder_dart.dart
@@ -18,12 +18,14 @@
 import 'package:analyzer_plugin/protocol/protocol_common.dart'
     hide Element, ElementKind;
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_core.dart';
+import 'package:analyzer_plugin/src/utilities/change_builder/dart/import_library_element.dart';
 import 'package:analyzer_plugin/src/utilities/string_utilities.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_workspace.dart';
 import 'package:analyzer_plugin/utilities/range_factory.dart';
 import 'package:charcode/ascii.dart';
+import 'package:meta/meta.dart';
 
 /**
  * A [ChangeBuilder] used to build changes in Dart files.
@@ -1203,6 +1205,35 @@
   }
 
   @override
+  ImportLibraryElementResult importLibraryElement({
+    @required ResolvedLibraryResult targetLibrary,
+    @required String targetPath,
+    @required int targetOffset,
+    @required LibraryElement requestedLibrary,
+    @required String requestedName,
+  }) {
+    if (librariesToImport.isNotEmpty) {
+      throw StateError('Only one library can be safely imported.');
+    }
+
+    var request = importLibraryElementImpl(
+      targetResolvedLibrary: targetLibrary,
+      targetPath: targetPath,
+      targetOffset: targetOffset,
+      requestedLibrary: requestedLibrary,
+      requestedName: requestedName,
+    );
+
+    var prefix = request.prefix;
+    if (request.uri != null) {
+      var uriText = _getLibraryUriText(request.uri);
+      librariesToImport[request.uri] = _LibraryToImport(uriText, prefix);
+    }
+
+    return ImportLibraryElementResultImpl(prefix);
+  }
+
+  @override
   void replaceTypeWithFuture(
       TypeAnnotation typeAnnotation, TypeProvider typeProvider) {
     InterfaceType futureType = typeProvider.futureType;
@@ -1511,6 +1542,14 @@
   }
 }
 
+/// Information about a library to import.
+class ImportLibraryElementResultImpl implements ImportLibraryElementResult {
+  @override
+  final String prefix;
+
+  ImportLibraryElementResultImpl(this.prefix);
+}
+
 class _EnclosingElementFinder {
   ClassElement enclosingClass;
   ExecutableElement enclosingExecutable;
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
new file mode 100644
index 0000000..086f7c6
--- /dev/null
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/import_library_element.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/results.dart';
+import 'package:analyzer/dart/element/element.dart';
+import 'package:analyzer/dart/element/visitor.dart';
+import 'package:analyzer_plugin/src/utilities/change_builder/dart/syntactic_scope.dart';
+import 'package:meta/meta.dart';
+
+ImportLibraryRequest importLibraryElementImpl({
+  @required ResolvedLibraryResult targetResolvedLibrary,
+  @required String targetPath,
+  @required int targetOffset,
+  @required LibraryElement requestedLibrary,
+  @required String requestedName,
+}) {
+  var targetLibrary = targetResolvedLibrary.element;
+
+  var requestedLibraryUri = requestedLibrary.source.uri;
+  var requestedElement = requestedLibrary.exportNamespace.get(requestedName);
+  var requestedElementUri = requestedElement.librarySource.uri;
+
+  // If the element is defined in this library, then no prefix needed.
+  if (targetLibrary == requestedElement.library) {
+    return ImportLibraryRequest(null, null);
+  }
+
+  var requestedElements = requestedLibrary.exportNamespace.definedNames;
+  _removeEntryForDynamic(requestedElements);
+
+  // Find URIs of all libraries that import the requested name into the target.
+  var unprefixedNameUriSet = Set<Uri>();
+  for (var import in targetLibrary.imports) {
+    var definedNames = import.namespace.definedNames;
+    if (import.prefix == null) {
+      var element = definedNames[requestedName];
+      if (element != null) {
+        unprefixedNameUriSet.add(element.librarySource.uri);
+      }
+    }
+  }
+
+  // Find names that will be shadowed by a new unprefixed import.
+  var collector = NotSyntacticScopeReferencedNamesCollector(
+    targetResolvedLibrary.element,
+    requestedElements.keys.toSet(),
+  );
+  for (var resolvedUnit in targetResolvedLibrary.units) {
+    resolvedUnit.unit.accept(collector);
+  }
+
+  // Find names that will shadow unprefixed references.
+  var scopeNames = Set<String>();
+  targetLibrary.accept(_TopLevelNamesCollector(scopeNames));
+  for (var resolvedUnit in targetResolvedLibrary.units) {
+    if (resolvedUnit.path == targetPath) {
+      resolvedUnit.unit.accept(
+        SyntacticScopeNamesCollector(scopeNames, targetOffset),
+      );
+    }
+  }
+
+  var canUseUnprefixedImport = true;
+
+  // If a name is inherited, it will be shadowed by a new unprefixed import.
+  if (collector.inheritedNames.isNotEmpty) {
+    canUseUnprefixedImport = false;
+  }
+
+  // If a name is imported, and it is not the same as the one from the
+  // requested library, then a new unprefixed import will cause ambiguity.
+  for (var name in collector.importedNames.keys) {
+    var importedUri = collector.importedNames[name];
+    var requestedUri = requestedElements[name]?.librarySource?.uri;
+    if (requestedUri != importedUri) {
+      canUseUnprefixedImport = false;
+      break;
+    }
+  }
+
+  // If syntactic scope at the offset has the requested name, then the name
+  // from an unprefixed import will be shadowed.
+  if (scopeNames.contains(requestedName)) {
+    canUseUnprefixedImport = false;
+  }
+
+  // If the requested name is ambiguous from existing unprefixed imports,
+  // or is not the same element as the one from the requested library, then
+  // we cannot use unprefixed import.
+  if (unprefixedNameUriSet.isNotEmpty) {
+    if (unprefixedNameUriSet.length > 1 ||
+        unprefixedNameUriSet.first != requestedElementUri) {
+      canUseUnprefixedImport = false;
+    }
+  }
+
+  // Find import prefixes with which the name is ambiguous.
+  var ambiguousWithImportPrefixes = Set<String>();
+  for (var import in targetLibrary.imports) {
+    var definedNames = import.namespace.definedNames;
+    if (import.prefix != null) {
+      var prefix = import.prefix.name;
+      var prefixedName = '$prefix.$requestedName';
+      var importedElement = definedNames[prefixedName];
+      if (importedElement != null &&
+          importedElement.librarySource.uri != requestedElementUri) {
+        ambiguousWithImportPrefixes.add(prefix);
+      }
+    }
+  }
+
+  // Check for existing imports of the requested library.
+  for (var import in targetLibrary.imports) {
+    if (import.importedLibrary.source.uri == requestedLibraryUri) {
+      var importedNames = import.namespace.definedNames;
+      if (import.prefix == null) {
+        if (canUseUnprefixedImport &&
+            importedNames.containsKey(requestedName)) {
+          return ImportLibraryRequest(null, null);
+        }
+      } else {
+        var prefix = import.prefix.name;
+        var prefixedName = '$prefix.$requestedName';
+        if (importedNames.containsKey(prefixedName) &&
+            !ambiguousWithImportPrefixes.contains(prefix)) {
+          return ImportLibraryRequest(null, prefix);
+        }
+      }
+    }
+  }
+
+  // If the name cannot be used without import prefix, generate one.
+  String prefix;
+  if (!canUseUnprefixedImport) {
+    prefix = 'prefix';
+    for (var index = 0;; index++) {
+      prefix = 'prefix$index';
+      if (!collector.referencedNames.contains(prefix)) {
+        break;
+      }
+    }
+  }
+
+  return ImportLibraryRequest(requestedLibraryUri, prefix);
+}
+
+/// The type `dynamic` is part of 'dart:core', but has no library.
+void _removeEntryForDynamic(Map<String, Element> requestedElements) {
+  requestedElements.removeWhere((_, element) {
+    if (element.librarySource == null) {
+      assert(element.displayName == 'dynamic');
+      return true;
+    }
+    return false;
+  });
+}
+
+/// Information about a library to import.
+class ImportLibraryRequest {
+  /// The URI of the library to import, or `null` if the requested library is
+  /// already imported, with the [prefix], so no new import is required.
+  final Uri uri;
+
+  /// The prefix with which ths requested library is already imported,
+  /// or should be imported, or `null` is no prefix is necessary.
+  final String prefix;
+
+  ImportLibraryRequest(this.uri, this.prefix);
+}
+
+/// Element visitor that collects names of top-level elements.
+class _TopLevelNamesCollector extends GeneralizingElementVisitor<void> {
+  final Set<String> names;
+
+  _TopLevelNamesCollector(this.names);
+
+  @override
+  void visitElement(Element element) {
+    if (element is LibraryElement || element is CompilationUnitElement) {
+      super.visitElement(element);
+    } else if (element is ImportElement) {
+      var prefix = element.prefix?.displayName;
+      if (prefix != null) {
+        names.add(prefix);
+      }
+    } else if (element.enclosingElement is CompilationUnitElement) {
+      names.add(element.displayName);
+    }
+  }
+}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
new file mode 100644
index 0000000..71cf0f0
--- /dev/null
+++ b/pkg/analyzer_plugin/lib/src/utilities/change_builder/dart/syntactic_scope.dart
@@ -0,0 +1,322 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/ast/visitor.dart';
+import 'package:analyzer/dart/element/element.dart';
+
+/// AST visitor that collects names that are referenced, but the target element
+/// is not defined in the syntactic scope of the reference.  Resolution of
+/// such names will change when the import scope of the library changes.
+class NotSyntacticScopeReferencedNamesCollector
+    extends GeneralizingAstVisitor<void> {
+  /// The library that contains resolved AST(s) being visited.
+  final LibraryElement enclosingLibraryElement;
+
+  /// The names that we need to check.
+  final Set<String> interestingNames;
+
+  /// All the referenced unqualified names.
+  final Set<String> referencedNames = Set<String>();
+
+  /// The subset of [interestingNames] that are resolved to a top-level
+  /// element that is not in the syntactic scope of the reference, and the
+  /// library [Uri] is the value in the mapping.
+  final Map<String, Uri> importedNames = {};
+
+  /// The subset of [interestingNames] that are resolved to inherited names.
+  final Set<String> inheritedNames = Set<String>();
+
+  Element enclosingUnitMemberElement;
+
+  NotSyntacticScopeReferencedNamesCollector(
+    this.enclosingLibraryElement,
+    this.interestingNames,
+  );
+
+  @override
+  void visitCombinator(Combinator node) {}
+
+  @override
+  void visitCompilationUnitMember(CompilationUnitMember node) {
+    enclosingUnitMemberElement = node.declaredElement;
+    super.visitCompilationUnitMember(node);
+    enclosingUnitMemberElement = null;
+  }
+
+  @override
+  void visitSimpleIdentifier(SimpleIdentifier node) {
+    var name = node.name;
+    referencedNames.add(name);
+
+    if (node.isQualified) return;
+    if (!interestingNames.contains(name)) return;
+
+    var element = node.staticElement;
+    if (element == null) return;
+
+    if (_inSyntacticScope(element)) return;
+
+    if (element.enclosingElement is CompilationUnitElement) {
+      importedNames[name] = element.librarySource.uri;
+    } else {
+      inheritedNames.add(name);
+    }
+  }
+
+  bool _inSyntacticScope(Element element) {
+    if (element.enclosingElement is CompilationUnitElement &&
+        element.enclosingElement.enclosingElement == enclosingLibraryElement) {
+      return true;
+    }
+
+    while (element != null) {
+      if (element == enclosingUnitMemberElement) return true;
+      element = element.enclosingElement;
+    }
+    return false;
+  }
+}
+
+/// AST visitor that collects syntactic scope names visible at the [offset].
+///
+/// The AST does not need to be resolved.
+class SyntacticScopeNamesCollector extends RecursiveAstVisitor<void> {
+  final Set<String> names;
+  final int offset;
+
+  SyntacticScopeNamesCollector(this.names, this.offset);
+
+  @override
+  void visitBlock(Block node) {
+    if (!_isCoveredBy(node)) return;
+
+    super.visitBlock(node);
+
+    for (var statement in node.statements) {
+      if (statement is FunctionDeclarationStatement) {
+        _addName(statement.functionDeclaration.name);
+      } else if (statement is VariableDeclarationStatement) {
+        _addVariables(statement.variables);
+      }
+    }
+  }
+
+  @override
+  void visitCatchClause(CatchClause node) {
+    if (!_isCoveredBy(node)) return;
+
+    if (node.exceptionParameter != null) {
+      _addName(node.exceptionParameter);
+    }
+
+    if (node.stackTraceParameter != null) {
+      _addName(node.stackTraceParameter);
+    }
+
+    node.body.accept(this);
+  }
+
+  @override
+  void visitClassDeclaration(ClassDeclaration node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+    _visitClassOrMixinMembers(node);
+  }
+
+  @override
+  void visitClassTypeAlias(ClassTypeAlias node) {
+    if (!_isCoveredBy(node)) return;
+    _addTypeParameters(node.typeParameters);
+  }
+
+  @override
+  void visitConstructorDeclaration(ConstructorDeclaration node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addFormalParameters(node.parameters);
+
+    node.body.accept(this);
+  }
+
+  @override
+  void visitForEachStatement(ForEachStatement node) {
+    if (!_isCoveredBy(node)) return;
+
+    if (node.loopVariable != null && _isCoveredBy(node.body)) {
+      _addName(node.loopVariable.identifier);
+    }
+
+    node.iterable?.accept(this);
+    node.body.accept(this);
+  }
+
+  @override
+  void visitForElement(ForElement node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addForLoopParts(node.forLoopParts, node.body);
+
+    super.visitForElement(node);
+  }
+
+  @override
+  void visitForStatement(ForStatement node) {
+    if (!_isCoveredBy(node)) return;
+
+    if (node.variables != null) {
+      _addVariables(node.variables);
+    }
+
+    node.condition?.accept(this);
+    node.updaters?.accept(this);
+    node.body.accept(this);
+  }
+
+  @override
+  void visitForStatement2(ForStatement2 node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addForLoopParts(node.forLoopParts, node.body);
+
+    super.visitForStatement2(node);
+  }
+
+  @override
+  void visitFunctionDeclaration(FunctionDeclaration node) {
+    if (!_isCoveredBy(node)) return;
+
+    var function = node.functionExpression;
+    _addTypeParameters(function.typeParameters);
+
+    if (function.parameters != null && offset > function.parameters.offset) {
+      _addFormalParameters(function.parameters);
+    }
+
+    function.body.accept(this);
+  }
+
+  @override
+  void visitFunctionTypeAlias(FunctionTypeAlias node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+
+    if (offset > node.parameters.offset) {
+      _addFormalParameters(node.parameters);
+    }
+  }
+
+  @override
+  void visitGenericFunctionType(GenericFunctionType node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+
+    if (offset > node.parameters.offset) {
+      _addFormalParameters(node.parameters);
+    }
+  }
+
+  @override
+  void visitGenericTypeAlias(GenericTypeAlias node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+
+    node.functionType.accept(this);
+  }
+
+  @override
+  void visitMethodDeclaration(MethodDeclaration node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+
+    if (node.parameters != null && offset > node.parameters.offset) {
+      _addFormalParameters(node.parameters);
+    }
+
+    node.body.accept(this);
+  }
+
+  @override
+  void visitMixinDeclaration(MixinDeclaration node) {
+    if (!_isCoveredBy(node)) return;
+
+    _addTypeParameters(node.typeParameters);
+    _visitClassOrMixinMembers(node);
+  }
+
+  void _addForLoopParts(ForLoopParts forLoopParts, AstNode body) {
+    if (forLoopParts is ForEachPartsWithDeclaration) {
+      if (_isCoveredBy(body)) {
+        _addName(forLoopParts.loopVariable.identifier);
+      }
+    } else if (forLoopParts is ForPartsWithDeclarations) {
+      _addVariables(forLoopParts.variables);
+    }
+  }
+
+  void _addFormalParameter(FormalParameter parameter) {
+    if (parameter is DefaultFormalParameter) {
+      _addFormalParameter(parameter.parameter);
+    } else if (parameter is FunctionTypedFormalParameter) {
+      _addName(parameter.identifier);
+      var parameters = parameter.parameters;
+      if (parameters != null && _isCoveredBy(parameters)) {
+        _addFormalParameters(parameters);
+      }
+    } else if (parameter is SimpleFormalParameter) {
+      _addName(parameter.identifier);
+    } else {
+      throw UnimplementedError('(${parameter.runtimeType}) $parameter');
+    }
+  }
+
+  void _addFormalParameters(FormalParameterList parameterList) {
+    for (var parameter in parameterList.parameters) {
+      _addFormalParameter(parameter);
+    }
+  }
+
+  void _addName(SimpleIdentifier node) {
+    if (node != null) {
+      names.add(node.name);
+    }
+  }
+
+  void _addTypeParameters(TypeParameterList typeParameterList) {
+    if (typeParameterList == null) return;
+
+    for (var typeParameter in typeParameterList.typeParameters) {
+      _addName(typeParameter.name);
+    }
+  }
+
+  void _addVariables(VariableDeclarationList variableList) {
+    for (var field in variableList.variables) {
+      _addName(field.name);
+    }
+  }
+
+  bool _isCoveredBy(AstNode node) {
+    return node.offset < offset && offset < node.end;
+  }
+
+  void _visitClassOrMixinMembers(ClassOrMixinDeclaration node) {
+    if (offset < node.leftBracket.offset) return;
+
+    for (var member in node.members) {
+      if (member is FieldDeclaration) {
+        _addVariables(member.fields);
+      } else if (member is MethodDeclaration) {
+        _addName(member.name);
+      }
+    }
+
+    node.members.accept(this);
+  }
+}
diff --git a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
index 69a0aae..2449bb7 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/completion/completion_target.dart
@@ -123,6 +123,19 @@
   final int argIndex;
 
   /**
+   * If the target is an argument in an [ArgumentList], then this is the
+   * invoked [ExecutableElement], otherwise this is `null`.
+   */
+  ExecutableElement _executableElement;
+
+  /**
+   * If the target is an argument in an [ArgumentList], then this is the
+   * corresponding [ParameterElement] in the invoked [ExecutableElement],
+   * otherwise this is `null`.
+   */
+  ParameterElement _parameterElement;
+
+  /**
    * Compute the appropriate [CompletionTarget] for the given [offset] within
    * the [compilationUnit].
    *
@@ -250,6 +263,38 @@
             _computeDroppedToken(containingNode, entity, offset);
 
   /**
+   * If the target is an argument in an argument list, and the invocation is
+   * resolved, return the invoked [ExecutableElement].
+   */
+  ExecutableElement get executableElement {
+    if (_executableElement == null) {
+      var argumentList = containingNode;
+      if (argumentList is NamedExpression) {
+        argumentList = argumentList.parent;
+      }
+      if (argumentList is! ArgumentList) {
+        return null;
+      }
+
+      var invocation = argumentList.parent;
+
+      Element executable;
+      if (invocation is Annotation) {
+        executable = invocation.element;
+      } else if (invocation is InstanceCreationExpression) {
+        executable = invocation.constructorName.staticElement;
+      } else if (invocation is MethodInvocation) {
+        executable = invocation.methodName.staticElement;
+      }
+
+      if (executable is ExecutableElement) {
+        _executableElement = executable;
+      }
+    }
+    return _executableElement;
+  }
+
+  /**
    * Return `true` if the [containingNode] is a cascade
    * and the completion insertion is not between the two dots.
    * For example, `..d^` and `..^d` are considered a cascade
@@ -267,6 +312,21 @@
   }
 
   /**
+   * If the target is an argument in an argument list, and the invocation is
+   * resolved, return the corresponding [ParameterElement].
+   */
+  ParameterElement get parameterElement {
+    if (_parameterElement == null) {
+      var executable = executableElement;
+      if (executable != null) {
+        _parameterElement = _getParameterElement(
+            executable.parameters, containingNode, argIndex);
+      }
+    }
+    return _parameterElement;
+  }
+
+  /**
    * Return a source range that represents the region of text that should be
    * replaced when a suggestion based on this target is selected, given that the
    * completion was requested at the given [requestOffset].
@@ -328,63 +388,9 @@
   /**
    * Return `true` if the target is a functional argument in an argument list.
    * The target [AstNode] hierarchy *must* be resolved for this to work.
-   * See [maybeFunctionalArgument].
    */
   bool isFunctionalArgument() {
-    if (!maybeFunctionalArgument()) {
-      return false;
-    }
-    AstNode parent = containingNode.parent;
-    if (parent is ArgumentList) {
-      parent = parent.parent;
-    }
-    if (parent is InstanceCreationExpression) {
-      DartType instType = parent.staticType;
-      if (instType != null) {
-        Element intTypeElem = instType.element;
-        if (intTypeElem is ClassElement) {
-          SimpleIdentifier constructorName = parent.constructorName.name;
-          ConstructorElement constructor = constructorName != null
-              ? intTypeElem.getNamedConstructor(constructorName.name)
-              : intTypeElem.unnamedConstructor;
-          return constructor != null &&
-              _isFunctionalParameter(
-                  constructor.parameters, argIndex, containingNode);
-        }
-      }
-    } else if (parent is MethodInvocation) {
-      SimpleIdentifier methodName = parent.methodName;
-      if (methodName != null) {
-        Element methodElem = methodName.staticElement;
-        if (methodElem is MethodElement) {
-          return _isFunctionalParameter(
-              methodElem.parameters, argIndex, containingNode);
-        } else if (methodElem is FunctionElement) {
-          return _isFunctionalParameter(
-              methodElem.parameters, argIndex, containingNode);
-        }
-      }
-    }
-    return false;
-  }
-
-  /**
-   * Return `true` if the target maybe a functional argument in an argument list.
-   * This is used in determining whether the target [AstNode] hierarchy
-   * needs to be resolved so that [isFunctionalArgument] will work.
-   */
-  bool maybeFunctionalArgument() {
-    if (argIndex != null) {
-      if (containingNode is ArgumentList) {
-        return true;
-      }
-      if (containingNode is NamedExpression) {
-        if (containingNode.parent is ArgumentList) {
-          return true;
-        }
-      }
-    }
-    return false;
+    return parameterElement?.type is FunctionType;
   }
 
   static int _computeArgIndex(AstNode containingNode, Object entity) {
@@ -501,6 +507,32 @@
   }
 
   /**
+   * Return the [ParameterElement] that corresponds to the given [argumentNode]
+   * at the given [argumentIndex].
+   */
+  static ParameterElement _getParameterElement(
+    List<ParameterElement> parameters,
+    AstNode argumentNode,
+    int argumentIndex,
+  ) {
+    if (argumentNode is NamedExpression) {
+      var name = argumentNode.name?.label?.name;
+      for (var parameter in parameters) {
+        if (parameter.name == name) {
+          return parameter;
+        }
+      }
+      return null;
+    }
+
+    if (argumentIndex < parameters.length) {
+      return parameters[argumentIndex];
+    }
+
+    return null;
+  }
+
+  /**
    * Determine whether [node] could possibly be the [entity] for a
    * [CompletionTarget] associated with the given [offset].
    */
@@ -554,27 +586,4 @@
       return false;
     }
   }
-
-  /**
-   * Return `true` if the parameter is a functional parameter.
-   */
-  static bool _isFunctionalParameter(List<ParameterElement> parameters,
-      int paramIndex, AstNode containingNode) {
-    DartType paramType;
-    if (paramIndex < parameters.length) {
-      ParameterElement param = parameters[paramIndex];
-      if (param.isNamed) {
-        if (containingNode is NamedExpression) {
-          String name = containingNode.name?.label?.name;
-          param = parameters.firstWhere(
-              (ParameterElement param) => param.isNamed && param.name == name,
-              orElse: () => null);
-          paramType = param?.type;
-        }
-      } else {
-        paramType = param.type;
-      }
-    }
-    return paramType is FunctionType || paramType is FunctionTypeAlias;
-  }
 }
diff --git a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
index ba1ec8f..dca1c1a 100644
--- a/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
+++ b/pkg/analyzer_plugin/lib/src/utilities/visitors/local_declaration_visitor.dart
@@ -48,6 +48,8 @@
   void declaredTopLevelVar(
       VariableDeclarationList varList, VariableDeclaration varDecl);
 
+  void declaredTypeParameter(TypeParameter node) {}
+
   /**
    * Throw an exception indicating that [LocalDeclarationVisitor] should
    * stop visiting. This is caught in [visit] which then exits normally.
@@ -100,10 +102,15 @@
     node.declarations.forEach((Declaration declaration) {
       if (declaration is ClassDeclaration) {
         declaredClass(declaration);
+        _visitTypeParameters(declaration, declaration.typeParameters);
       } else if (declaration is EnumDeclaration) {
         declaredEnum(declaration);
       } else if (declaration is FunctionDeclaration) {
         declaredFunction(declaration);
+        _visitTypeParameters(
+          declaration,
+          declaration.functionExpression.typeParameters,
+        );
       } else if (declaration is TopLevelVariableDeclaration) {
         var varList = declaration.variables;
         if (varList != null) {
@@ -113,10 +120,17 @@
         }
       } else if (declaration is ClassTypeAlias) {
         declaredClassTypeAlias(declaration);
+        _visitTypeParameters(declaration, declaration.typeParameters);
       } else if (declaration is FunctionTypeAlias) {
         declaredFunctionTypeAlias(declaration);
+        _visitTypeParameters(declaration, declaration.typeParameters);
       } else if (declaration is GenericTypeAlias) {
         declaredGenericTypeAlias(declaration);
+        _visitTypeParameters(declaration, declaration.typeParameters);
+        _visitTypeParameters(
+          declaration.functionType,
+          declaration.functionType.typeParameters,
+        );
       }
     });
   }
@@ -224,6 +238,7 @@
         });
       } else if (member is MethodDeclaration) {
         declaredMethod(member);
+        _visitTypeParameters(member, member.typeParameters);
       }
     }
   }
@@ -271,6 +286,10 @@
               String name = id.name;
               if (name != null && name.length > 0) {
                 declaredFunction(declaration);
+                _visitTypeParameters(
+                  declaration,
+                  declaration.functionExpression.typeParameters,
+                );
               }
             }
           }
@@ -278,6 +297,16 @@
       }
     }
   }
+
+  void _visitTypeParameters(AstNode node, TypeParameterList typeParameters) {
+    if (typeParameters == null) return;
+
+    if (node.offset < offset && offset < node.end) {
+      for (var typeParameter in typeParameters.typeParameters) {
+        declaredTypeParameter(typeParameter);
+      }
+    }
+  }
 }
 
 /**
diff --git a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
index 7e02aea..4dca383 100644
--- a/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
+++ b/pkg/analyzer_plugin/lib/utilities/assist/assist.dart
@@ -102,10 +102,17 @@
   final String message;
 
   /**
-   * Initialize a newly created kind of assist to have the given [id],
-   * [priority] and [message].
+   * A list of any associated error codes. Assists with associated error codes
+   * can be presented as "fixes" for the associated errors by clients.
    */
-  const AssistKind(this.id, this.priority, this.message);
+  final List<String> associatedErrorCodes;
+
+  /**
+   * Initialize a newly created kind of assist to have the given [id],
+   * [priority], [message] and optionally any [associatedErrorCodes].
+   */
+  const AssistKind(this.id, this.priority, this.message,
+      {this.associatedErrorCodes});
 
   @override
   String toString() => id;
diff --git a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
index 25932c0..50e2721 100644
--- a/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
+++ b/pkg/analyzer_plugin/lib/utilities/change_builder/change_builder_dart.dart
@@ -4,6 +4,7 @@
 
 import 'dart:async';
 
+import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/analysis/session.dart';
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
@@ -12,6 +13,7 @@
 import 'package:analyzer/src/generated/source.dart';
 import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
 import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dart';
+import 'package:meta/meta.dart';
 
 /**
  * The optional generator for prefix that should be used for new imports.
@@ -214,7 +216,7 @@
   void writeOverride(
     FunctionType signature, {
     StringBuffer displayTextBuffer,
-    bool invokeSuper: true,
+    bool invokeSuper: false,
   });
 
   /**
@@ -354,6 +356,34 @@
   String importLibrary(Uri uri);
 
   /**
+   * Ensure that the [requestedLibrary] is imported into the [targetLibrary],
+   * and the top-level [requestedName] is accessible at the [targetOffset] of
+   * the file with the [targetPath].
+   *
+   * Parameters [targetPath] and [targetOffset] are used to determine if the
+   * unprefixed reference to the [requestedName] will be shadowed by a local
+   * declaration in the target syntactic scope.
+   *
+   * If there is already an import for the [requestedLibrary], and the
+   * [requestedName] refers to the same element in the namespace of the import
+   * directive, and the name of the element is not ambiguous in existing import
+   * directives, and the name does not conflict with existing declarations and
+   * references, return the import prefix of the existing import directive.
+   *
+   * If there is no existing import, or there is a conflict, a new import is
+   * added, possibly with an import prefix.
+   *
+   * This method can be used only alone, and only once.
+   */
+  ImportLibraryElementResult importLibraryElement({
+    @required ResolvedLibraryResult targetLibrary,
+    @required String targetPath,
+    @required int targetOffset,
+    @required LibraryElement requestedLibrary,
+    @required String requestedName,
+  });
+
+  /**
    * Optionally create an edit to replace the given [typeAnnotation] with the
    * type `Future` (with the given type annotation as the type argument). The
    * [typeProvider] is used to check the current type, because if it is already
@@ -375,3 +405,10 @@
    */
   void addSuperTypesAsSuggestions(DartType type);
 }
+
+/// Information about a library to import.
+abstract class ImportLibraryElementResult {
+  /// If the library is already imported with a prefix, or should be imported
+  /// with a prefix, the prefix name (without `.`).  Otherwise `null`.
+  String get prefix;
+}
diff --git a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
index e306286..eca6b97 100644
--- a/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
+++ b/pkg/analyzer_plugin/lib/utilities/completion/relevance.dart
@@ -7,6 +7,14 @@
 // suggestions in Dart code.
 //
 
+/// The relevance boost for available declarations with the matching tag.
+const int DART_RELEVANCE_BOOST_AVAILABLE_DECLARATION = 10;
+
+/// The relevance boost for available enum constants with the matching tag.
+///
+/// It is so large to move enum constants to the very top.
+const int DART_RELEVANCE_BOOST_AVAILABLE_ENUM = 1100;
+
 const int DART_RELEVANCE_BOOST_SUBTYPE = 100;
 const int DART_RELEVANCE_BOOST_TYPE = 200;
 const int DART_RELEVANCE_COMMON_USAGE = 1200;
@@ -26,3 +34,4 @@
 const int DART_RELEVANCE_NAMED_PARAMETER = 1060;
 const int DART_RELEVANCE_NAMED_PARAMETER_REQUIRED = 1065;
 const int DART_RELEVANCE_PARAMETER = 1059;
+const int DART_RELEVANCE_TYPE_PARAMETER = 1058;
diff --git a/pkg/analyzer_plugin/pubspec.yaml b/pkg/analyzer_plugin/pubspec.yaml
index e331c5c..c1c6502 100644
--- a/pkg/analyzer_plugin/pubspec.yaml
+++ b/pkg/analyzer_plugin/pubspec.yaml
@@ -16,5 +16,7 @@
   pub_semver: '^1.3.2'
 
 dev_dependencies:
+  analysis_tool:
+    path: ../analysis_tool
   test_reflective_loader: ^0.1.8
   test: ^1.0.0
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
index 3cd8e09..a3be8b8 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/change_builder_dart_test.dart
@@ -21,6 +21,7 @@
 import 'package:test_reflective_loader/test_reflective_loader.dart';
 
 import '../../../support/abstract_context.dart';
+import 'dart/dart_change_builder_mixin.dart';
 
 main() {
   defineReflectiveSuite(() {
@@ -33,37 +34,9 @@
   });
 }
 
-mixin BuilderTestMixin implements AbstractContextTest {
-  SourceEdit getEdit(DartChangeBuilder builder) {
-    SourceChange sourceChange = builder.sourceChange;
-    expect(sourceChange, isNotNull);
-    List<SourceFileEdit> fileEdits = sourceChange.edits;
-    expect(fileEdits, hasLength(1));
-    SourceFileEdit fileEdit = fileEdits[0];
-    expect(fileEdit, isNotNull);
-    List<SourceEdit> edits = fileEdit.edits;
-    expect(edits, hasLength(1));
-    return edits[0];
-  }
-
-  List<SourceEdit> getEdits(DartChangeBuilder builder) {
-    SourceChange sourceChange = builder.sourceChange;
-    expect(sourceChange, isNotNull);
-    List<SourceFileEdit> fileEdits = sourceChange.edits;
-    expect(fileEdits, hasLength(1));
-    SourceFileEdit fileEdit = fileEdits[0];
-    expect(fileEdit, isNotNull);
-    return fileEdit.edits;
-  }
-
-  /// Return a newly created Dart change builder.
-  DartChangeBuilderImpl newBuilder() =>
-      new DartChangeBuilder(session) as DartChangeBuilderImpl;
-}
-
 @reflectiveTest
 class DartChangeBuilderImplTest extends AbstractContextTest
-    with BuilderTestMixin {
+    with DartChangeBuilderMixin {
   test_createFileEditBuilder() async {
     String path = convertPath('/home/test/lib/test.dart');
     addSource(path, 'library test;');
@@ -78,7 +51,7 @@
 
 @reflectiveTest
 class DartEditBuilderImplTest extends AbstractContextTest
-    with BuilderTestMixin {
+    with DartChangeBuilderMixin {
   test_writeClassDeclaration_interfaces() async {
     String path = convertPath('/home/test/lib/test.dart');
     addSource(path, 'class A {}');
@@ -1527,7 +1500,7 @@
 
 @reflectiveTest
 class DartFileEditBuilderImplTest extends AbstractContextTest
-    with BuilderTestMixin {
+    with DartChangeBuilderMixin {
   TypeProvider get typeProvider {
     return new TestTypeProvider(null, driver);
   }
@@ -1629,7 +1602,8 @@
 }
 
 @reflectiveTest
-class ImportLibraryTest extends AbstractContextTest with BuilderTestMixin {
+class ImportLibraryTest extends AbstractContextTest
+    with DartChangeBuilderMixin {
   test_afterLibraryDirective_dart() async {
     await _assertImportLibrary(
       initialCode: '''
@@ -2059,7 +2033,8 @@
 }
 
 @reflectiveTest
-class WriteOverrideTest extends AbstractContextTest with BuilderTestMixin {
+class WriteOverrideTest extends AbstractContextTest
+    with DartChangeBuilderMixin {
   test_getter_abstract() async {
     await _assertWriteOverride(
       content: '''
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/dart_change_builder_mixin.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/dart_change_builder_mixin.dart
new file mode 100644
index 0000000..aea3ed8
--- /dev/null
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/dart_change_builder_mixin.dart
@@ -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.
+
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
+import 'package:analyzer_plugin/utilities/change_builder/change_builder_dart.dart';
+import 'package:test/test.dart';
+
+import '../../../../support/abstract_context.dart';
+
+mixin DartChangeBuilderMixin implements AbstractContextTest {
+  SourceEdit getEdit(DartChangeBuilder builder) {
+    List<SourceEdit> edits = getEdits(builder);
+    expect(edits, hasLength(1));
+    return edits[0];
+  }
+
+  List<SourceEdit> getEdits(DartChangeBuilder builder) {
+    SourceChange sourceChange = builder.sourceChange;
+    expect(sourceChange, isNotNull);
+
+    List<SourceFileEdit> fileEdits = sourceChange.edits;
+    expect(fileEdits, hasLength(1));
+
+    SourceFileEdit fileEdit = fileEdits[0];
+    expect(fileEdit, isNotNull);
+    return fileEdit.edits;
+  }
+
+  /// Return a newly created Dart change builder.
+  DartChangeBuilderImpl newBuilder() =>
+      new DartChangeBuilder(session) as DartChangeBuilderImpl;
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
new file mode 100644
index 0000000..7f5ea6f
--- /dev/null
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/import_library_element_test.dart
@@ -0,0 +1,761 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:async';
+
+import 'package:analyzer_plugin/protocol/protocol_common.dart';
+import 'package:analyzer_plugin/src/utilities/change_builder/change_builder_dart.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../support/abstract_context.dart';
+import 'dart_change_builder_mixin.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(ImportLibraryElementTest);
+    defineReflectiveTests(ImportLibraryElement_existingImport_Test);
+    defineReflectiveTests(ImportLibraryElement_newImport_withoutPrefix_Test);
+    defineReflectiveTests(ImportLibraryElement_newImport_withPrefix_Test);
+  });
+}
+
+@reflectiveTest
+class ImportLibraryElement_existingImport_Test extends _Base {
+  test_dartCore_implicit() async {
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'dart:math';
+''',
+      uriStr: 'dart:core',
+      name: 'String',
+    );
+  }
+
+  test_dartCore_withPrefix() async {
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'dart:core' as my_core;
+import 'dart:math';
+''',
+      uriStr: 'dart:core',
+      name: 'String',
+      expectedPrefix: 'my_core',
+    );
+  }
+
+  test_withoutPrefix() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+    );
+  }
+
+  test_withoutPrefix_exported() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'a.dart';
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/b.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'A',
+    );
+  }
+
+  test_withoutPrefix_referencedNames_sameElements() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'a.dart';
+
+class B {}
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/b.dart';
+
+A a;
+B b;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'B',
+    );
+  }
+
+  test_withoutPrefix_twoImports_sameElement() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'package:test/a.dart';
+''');
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'C',
+    );
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'C',
+    );
+  }
+
+  test_withPrefix() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' as p;
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedPrefix: 'p',
+    );
+  }
+
+  test_withPrefix_twoImports_sameElement() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'package:test/a.dart';
+''');
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' as p;
+import 'package:test/b.dart' as p;
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'C',
+      expectedPrefix: 'p',
+    );
+
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' as p;
+import 'package:test/b.dart' as p;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'C',
+      expectedPrefix: 'p',
+    );
+  }
+}
+
+@reflectiveTest
+class ImportLibraryElement_newImport_withoutPrefix_Test extends _Base {
+  test_exported() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'a.dart';
+''');
+    await _assertImportLibraryElement(
+      initialCode: '',
+      uriStr: 'package:test/b.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/b.dart';
+''',
+    );
+  }
+
+  test_exported_differentUri() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    newFile('/home/test/lib/b.dart', content: r'''
+export 'a.dart';
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+''',
+    );
+  }
+
+  test_noConflict_otherImport_hide() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+class B {}
+''');
+    newFile('/home/test/lib/b.dart', content: 'class B {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' hide B;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'B',
+      expectedCode: r'''
+import 'package:test/a.dart' hide B;
+import 'package:test/b.dart';
+''',
+    );
+  }
+
+  test_noConflict_otherImport_show() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+class B {}
+''');
+    newFile('/home/test/lib/b.dart', content: 'class B {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' show A;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'B',
+      expectedCode: r'''
+import 'package:test/a.dart' show A;
+import 'package:test/b.dart';
+''',
+    );
+  }
+
+  test_noShadow_syntacticScope_localVariable() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+var foo = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f() {
+^
+}
+
+void g() {
+  var foo = 1;
+  foo;
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+void f() {
+
+}
+
+void g() {
+  var foo = 1;
+  foo;
+}
+''',
+    );
+  }
+
+  test_noShadow_syntacticScope_typeParameter() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C<A> {
+  A f;
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+class C<A> {
+  A f;
+}
+''',
+    );
+  }
+
+  test_thisName_notShadowed_localVariable_otherFunction() async {
+    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f() {
+^
+}
+
+void g() {
+  var foo = '';
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedCode: r'''
+import 'package:test/a.dart';
+
+void f() {
+
+}
+
+void g() {
+  var foo = '';
+}
+''',
+    );
+  }
+
+  test_unrelated() async {
+    newFile('/home/test/lib/a.dart', content: 'class A {}');
+    newFile('/home/test/lib/b.dart', content: 'class B {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'B',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+''',
+    );
+  }
+}
+
+@reflectiveTest
+class ImportLibraryElement_newImport_withPrefix_Test extends _Base {
+  test_existingImport_nameIsAmbiguous() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/b.dart', content: 'class C {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'C',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart';
+import 'package:test/b.dart' as prefix0;
+''',
+    );
+  }
+
+  test_existingImport_nameIsAmbiguous_prefixed() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/b.dart', content: 'class C {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart' as p;
+import 'package:test/b.dart' as p;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'C',
+      expectedCode: r'''
+import 'package:test/a.dart' as p;
+import 'package:test/b.dart' as p;
+import 'package:test/b.dart';
+''',
+    );
+  }
+
+  test_nameIsAmbiguous() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/b.dart', content: 'class C {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'C',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart' as prefix0;
+''',
+    );
+  }
+
+  test_shadow_otherName_imported() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    newFile('/home/test/lib/b.dart', content: r'''
+class A {}
+class B {}
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+
+A a;
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'B',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/b.dart' as prefix0;
+
+A a;
+''',
+    );
+  }
+
+  test_shadow_otherName_inherited() async {
+    newFile('/home/test/lib/b.dart', content: '''
+int foo = 0;
+int bar = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class A {
+  void bar() {}
+}
+
+class X extends A {
+  voif f() {
+    bar();
+  }
+}
+''',
+      uriStr: 'package:test/b.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/b.dart' as prefix0;
+
+class A {
+  void bar() {}
+}
+
+class X extends A {
+  voif f() {
+    bar();
+  }
+}
+''',
+    );
+  }
+
+  test_shadowed_class() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'package:test/a.dart';
+
+class C {}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'C',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart';
+import 'package:test/a.dart' as prefix0;
+
+class C {}
+''',
+    );
+  }
+
+  @failingTest
+  test_shadowed_class_inPart() async {
+    newFile('/home/test/lib/a.dart', content: 'class C {}');
+    newFile('/home/test/lib/p.dart', content: 'class C {}');
+    // TODO(scheglov) "import" must be before "part"
+    await _assertImportLibraryElement(
+      initialCode: r'''
+part 'p.dart';
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'C',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+part 'p.dart';
+''',
+    );
+  }
+
+  test_shadowed_formalParameter() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+var foo = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f(int foo) {^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+void f(int foo) {}
+''',
+    );
+  }
+
+  test_shadowed_function() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+var foo = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void foo() {^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+void foo() {}
+''',
+    );
+  }
+
+  test_shadowed_function_local_after() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+var foo = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f() {
+  void foo() {}
+^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+void f() {
+  void foo() {}
+}
+''',
+    );
+  }
+
+  test_shadowed_function_local_before() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+var foo = 0;
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f() {^
+  void foo() {}
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+void f() {
+  void foo() {}
+}
+''',
+    );
+  }
+
+  test_shadowed_importPrefix() async {
+    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+import 'dart:math' as foo;
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'dart:math' as foo;
+
+import 'package:test/a.dart' as prefix0;
+''',
+    );
+  }
+
+  test_shadowed_localVariable_after() async {
+    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+main() {
+  var foo = '';
+^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+main() {
+  var foo = '';
+}
+''',
+    );
+  }
+
+  test_shadowed_localVariable_before() async {
+    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+main() {^
+  var foo = '';
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+main() {
+  var foo = '';
+}
+''',
+    );
+  }
+
+  test_shadowed_method() async {
+    newFile('/home/test/lib/a.dart', content: 'int foo = 0;');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class A {
+  void foo() {}
+  
+  void bar() {^}
+}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'foo',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+class A {
+  void foo() {}
+  
+  void bar() {}
+}
+''',
+    );
+  }
+
+  test_shadowed_typeParameter_class() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class C<A> {^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+class C<A> {}
+''',
+    );
+  }
+
+  test_shadowed_typeParameter_function() async {
+    newFile('/home/test/lib/a.dart', content: r'''
+class A {}
+''');
+    await _assertImportLibraryElement(
+      initialCode: r'''
+void f<A>() {^}
+''',
+      uriStr: 'package:test/a.dart',
+      name: 'A',
+      expectedPrefix: 'prefix0',
+      expectedCode: r'''
+import 'package:test/a.dart' as prefix0;
+
+void f<A>() {}
+''',
+    );
+  }
+}
+
+@reflectiveTest
+class ImportLibraryElementTest extends _Base {
+  test_thisLibrary() async {
+    await _assertImportLibraryElement(
+      initialCode: r'''
+class A {}
+''',
+      uriStr: 'package:test/test.dart',
+      name: 'A',
+    );
+  }
+}
+
+class _Base extends AbstractContextTest with DartChangeBuilderMixin {
+  void _assertEmptyChange(DartChangeBuilderImpl builder) {
+    var change = builder.sourceChange;
+    expect(change, isNotNull);
+    expect(change.edits, isEmpty);
+  }
+
+  Future<void> _assertImportLibraryElement(
+      {String initialCode,
+      String uriStr,
+      String name,
+      String expectedPrefix,
+      String expectedCode}) async {
+    var offset = initialCode.indexOf('^');
+    if (offset > 0) {
+      initialCode =
+          initialCode.substring(0, offset) + initialCode.substring(offset + 1);
+    } else {
+      offset = initialCode.length;
+    }
+
+    var path = convertPath('/home/test/lib/test.dart');
+    newFile(path, content: initialCode);
+
+    var resolvedLibrary = await session.getResolvedLibrary(path);
+    var requestedLibrary = await session.getLibraryByUri(uriStr);
+
+    var element = requestedLibrary.exportNamespace.get(name);
+    expect(element, isNotNull, reason: '`$name` in $uriStr');
+
+    var builder = newBuilder();
+    await builder.addFileEdit(path, (builder) {
+      var result = builder.importLibraryElement(
+        targetLibrary: resolvedLibrary,
+        targetPath: path,
+        targetOffset: offset,
+        requestedLibrary: requestedLibrary,
+        requestedName: name,
+      );
+      expect(result.prefix, expectedPrefix);
+    });
+
+    if (expectedCode != null) {
+      var edits = getEdits(builder);
+      var resultCode = SourceEdit.applySequence(initialCode, edits);
+      expect(resultCode, expectedCode);
+    } else {
+      _assertEmptyChange(builder);
+    }
+  }
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart
new file mode 100644
index 0000000..d4f04be
--- /dev/null
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/syntactic_scope_test.dart
@@ -0,0 +1,645 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. 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_plugin/src/utilities/change_builder/dart/syntactic_scope.dart';
+import 'package:test/test.dart';
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import '../../../../support/abstract_context.dart';
+
+main() {
+  defineReflectiveSuite(() {
+    defineReflectiveTests(NotSyntacticScopeReferencedNamesCollectorTest);
+    defineReflectiveTests(SyntacticScopeNamesCollectorTest);
+  });
+}
+
+@reflectiveTest
+class NotSyntacticScopeReferencedNamesCollectorTest
+    extends AbstractContextTest {
+  test_notSyntacticScopeNames() async {
+    var path = convertPath('/home/test/lib/test.dart');
+
+    newFile('/home/test/lib/a.dart', content: r'''
+var N1;
+''');
+
+    newFile(path, content: r'''
+import 'package:test/a.dart';
+
+class A {
+  var N2;
+  
+  void N3() {}
+  
+  get N4 => null;
+  
+  set N5(_) {}
+}
+
+var S1;
+
+class B<S2> extends A {
+  var S3;
+  
+  void S4() {}
+  
+  get S5 => null;
+  
+  set S6(_) {}
+  
+  void f<S7>(S8) {
+    var S9;
+    N1;
+    N1 = 0;
+    N2;
+    N3;
+    N4;
+    N5 = 0;
+    B;
+    S1;
+    S1 = 0;
+    S2;
+    S3;
+    S4;
+    S5;
+    S6 = 0;
+    S7;
+    S8;
+    S9;
+  }
+}
+''');
+
+    var resolvedUnit = await session.getResolvedUnit(path);
+    var collector = NotSyntacticScopeReferencedNamesCollector(
+      resolvedUnit.libraryElement,
+      (<String>[]
+            ..addAll(List.generate(20, (i) => 'N$i'))
+            ..addAll(List.generate(20, (i) => 'S$i')))
+          .toSet(),
+    );
+    resolvedUnit.unit.accept(collector);
+
+    expect(
+      collector.importedNames,
+      containsPair('N1', Uri.parse('package:test/a.dart')),
+    );
+
+    expect(
+      collector.inheritedNames,
+      unorderedEquals(['N2', 'N3', 'N4', 'N5']),
+    );
+  }
+
+  test_referencedNames() async {
+    var path = convertPath('/home/test/lib/test.dart');
+    newFile(path, content: r'''
+class N1 {}
+
+N2 N3<N4>(N5 N6, N7) {
+  N7.N8(N9);
+}
+''');
+
+    var resolvedUnit = await session.getResolvedUnit(path);
+    var collector = NotSyntacticScopeReferencedNamesCollector(
+      resolvedUnit.libraryElement,
+      <String>[].toSet(),
+    );
+    resolvedUnit.unit.accept(collector);
+
+    expect(
+      collector.referencedNames,
+      unorderedEquals(['N1', 'N2', 'N3', 'N4', 'N5', 'N6', 'N7', 'N8', 'N9']),
+    );
+  }
+}
+
+@reflectiveTest
+class SyntacticScopeNamesCollectorTest extends AbstractContextTest {
+  test_Block() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  N2 N3, N4;
+  ^2
+  {
+    ^3
+    var N5;
+    ^4
+  }
+  ^5
+  var N6;
+  ^6
+  {
+    ^7
+    var N7;
+    ^8
+  }
+  ^9
+}
+''', expected: r'''
+1: N3, N4, N6
+2: N3, N4, N6
+3: N3, N4, N5, N6
+4: N3, N4, N5, N6
+5: N3, N4, N6
+6: N3, N4, N6
+7: N3, N4, N6, N7
+8: N3, N4, N6, N7
+9: N3, N4, N6
+''');
+  }
+
+  test_CatchClause() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  try {
+    var N2;
+    ^2
+  } on N3 catch (N4, N5) {
+    ^3
+  } catch (N6) {
+    ^4
+  }
+  ^5
+}
+''', expected: r'''
+1: {}
+2: N2
+3: N4, N5
+4: N6
+5: {}
+''');
+  }
+
+  test_ClassDeclaration() {
+    _assertScopeNames(code: r'''
+class N1<N2 ^1> extends ^2 N3<N4 ^3> with ^4 N5, N6 implements ^5 N7, N8 {
+  ^6
+  N9 N10, N11;
+  
+  N1.N12() {}
+  
+  N13 N14<N15>() {}
+  
+  ^7
+}
+
+class N16<N17> {
+  ^8
+}
+''', expected: r'''
+1: N2
+2: N2
+3: N2
+4: N2
+5: N2
+6: N2, N10, N11, N14
+7: N2, N10, N11, N14
+8: N17
+''');
+  }
+
+  test_ClassTypeAlias() {
+    _assertScopeNames(code: r'''
+class N1<N2 ^1> = N3<N4 ^2> with N5<N6 ^3> implements N7;
+''', expected: r'''
+1: N2
+2: N2
+3: N2
+''');
+  }
+
+  test_CollectionForElement_ForEachPartsWithDeclaration() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  [
+    0 ^1,
+    for (var N2 in N3 ^2) {
+      ^3
+    },
+    ^4
+    for (var N4 in N5) {
+      ^5
+    },
+    ^6
+  ];
+  ^7
+}
+''', expected: r'''
+1: {}
+2: {}
+3: N2
+4: {}
+5: N4
+6: {}
+7: {}
+''');
+  }
+
+  test_CollectionForElement_ForPartsWithDeclarations() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  [
+    0 ^1,
+    for (var N2 = 0 ^2; ^3; ^4) {
+      ^5
+    },
+    ^6
+    for (var N3 = 0 ^7; ^8; ^9) {
+      ^10
+    },
+    ^11
+  ];
+  ^12
+}
+''', expected: r'''
+1: {}
+2: N2
+3: N2
+4: N2
+5: N2
+6: {}
+7: N3
+8: N3
+9: N3
+10: N3
+11: {}
+12: {}
+''');
+  }
+
+  test_ConstructorDeclaration() {
+    _assertScopeNames(code: r'''
+class N1<N2> extends N3 {
+  N1.N4(N5 ^1) {
+    ^2
+  }
+  ^3
+}
+''', expected: r'''
+1: N2, N5
+2: N2, N5
+3: N2
+''');
+  }
+
+  test_ForEachStatement_identifier() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N2 in N3 ^2) {
+    ^3
+  }
+  ^4
+}
+''', expected: r'''
+1: {}
+2: {}
+3: {}
+4: {}
+''');
+  }
+
+  test_ForEachStatement_iterable() {
+    _assertScopeNames(code: r'''
+N1() {
+  for (var N2 in (){ var N3; ^1 }()) {
+    ^2
+  }
+  ^3
+}
+''', expected: r'''
+1: N3
+2: N2
+3: {}
+''');
+  }
+
+  test_ForEachStatement_loopVariable() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (var N2 in N3 ^2) {
+    ^3
+  }
+  ^4
+}
+''', expected: r'''
+1: {}
+2: {}
+3: N2
+4: {}
+''');
+  }
+
+  test_FormalParameter_functionTyped() {
+    _assertScopeNames(code: r'''
+N1 N2(N3 N4(N5 N6 ^1, N7), N8 ^2) {
+  ^3
+}
+''', expected: r'''
+1: N4, N6, N7, N8
+2: N4, N8
+3: N4, N8
+''');
+  }
+
+  test_ForStatement2_ForEachPartsWithDeclaration() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (var N2 in N3 ^2) {
+    ^3
+  }
+  ^4
+}
+''', expected: r'''
+1: {}
+2: {}
+3: N2
+4: {}
+''');
+  }
+
+  test_ForStatement2_ForEachPartsWithIdentifier() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N2 in N3 ^2) {
+    ^3
+  }
+  ^4
+}
+''', expected: r'''
+1: {}
+2: {}
+3: {}
+4: {}
+''');
+  }
+
+  test_ForStatement2_ForPartsWithDeclarations_condition() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N1 N2; (){ var N3; ^2 }(); ^3) {
+    ^4
+  }
+  ^5
+}
+''', expected: r'''
+1: {}
+2: N2, N3
+3: N2
+4: N2
+5: {}
+''');
+  }
+
+  test_ForStatement2_ForPartsWithDeclarations_updaters() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N1 N2; ^2; (){ var N3; ^3 }()) {
+    ^4
+  }
+  ^5
+}
+''', expected: r'''
+1: {}
+2: N2
+3: N2, N3
+4: N2
+5: {}
+''');
+  }
+
+  test_ForStatement2_ForPartsWithDeclarations_variables() {
+    _enableExperiments();
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N2 N3, N4 ^2; N5 ^3; N6 ^4) {
+    ^5
+  }
+  ^6
+}
+''', expected: r'''
+1: {}
+2: N3, N4
+3: N3, N4
+4: N3, N4
+5: N3, N4
+6: {}
+''');
+  }
+
+  test_ForStatement_condition() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N1 N2; (){ var N3; ^2 }(); ^3) {
+    ^4
+  }
+  ^5
+}
+''', expected: r'''
+1: {}
+2: N2, N3
+3: N2
+4: N2
+5: {}
+''');
+  }
+
+  test_ForStatement_updaters() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N1 N2; ^2; (){ var N3; ^3 }()) {
+    ^4
+  }
+  ^5
+}
+''', expected: r'''
+1: {}
+2: N2
+3: N2, N3
+4: N2
+5: {}
+''');
+  }
+
+  test_ForStatement_variables() {
+    _assertScopeNames(code: r'''
+N1() {
+  ^1
+  for (N2 N3, N4 ^2; N5 ^3; N6 ^4) {
+    ^5
+  }
+  ^6
+}
+''', expected: r'''
+1: {}
+2: N3, N4
+3: N3, N4
+4: N3, N4
+5: N3, N4
+6: {}
+''');
+  }
+
+  test_FunctionDeclaration() {
+    _assertScopeNames(code: r'''
+N1 N2<N3 extends N4 ^1>(N5 N6 ^2, [N7 N8 = N9, N10]) {
+  ^3
+}
+''', expected: r'''
+1: N3
+2: N3, N6, N8, N10
+3: N3, N6, N8, N10
+''');
+  }
+
+  test_FunctionTypeAlias() {
+    _assertScopeNames(code: r'''
+typedef N1 N2<N3 ^1>(N3 N4, N5 ^2);
+''', expected: r'''
+1: N3
+2: N3, N4, N5
+''');
+  }
+
+  test_GenericFunctionType() {
+    _assertScopeNames(code: r'''
+N1 Function<N2 ^1>(N3, N4 N5 ^2) N6;
+''', expected: r'''
+1: N2
+2: N2, N5
+''');
+  }
+
+  test_GenericTypeAlias() {
+    _assertScopeNames(code: r'''
+typedef N1<N2 ^1> = Function<N3 ^2>(N4 N5, N6 ^3);
+''', expected: r'''
+1: N2
+2: N2, N3
+3: N2, N3, N5
+''');
+  }
+
+  test_MethodDeclaration() {
+    _assertScopeNames(code: r'''
+class N1<N2> {
+  N3 N4, N5;
+  
+  ^1
+  
+  N6 ^2 N7<N8 ^3>(N9 N10, N11 ^4) {
+    ^5
+  }
+}
+''', expected: r'''
+1: N2, N4, N5, N7
+2: N2, N4, N5, N7, N8
+3: N2, N4, N5, N7, N8
+4: N2, N4, N5, N7, N8, N10, N11
+5: N2, N4, N5, N7, N8, N10, N11
+''');
+  }
+
+  test_MixinDeclaration() {
+    _assertScopeNames(code: r'''
+mixin N1<N2> on N3, N4 ^1 implements N5 ^2 {
+  ^3
+  N6 N7, N8;
+  ^4
+  
+  N9(N10 ^5) {
+    ^6
+  }
+  
+  ^7
+}
+''', expected: r'''
+1: N2
+2: N2
+3: N2, N7, N8, N9
+4: N2, N7, N8, N9
+5: N2, N7, N8, N9, N10
+6: N2, N7, N8, N9, N10
+7: N2, N7, N8, N9
+''');
+  }
+
+  void _assertScopeNames({String code, String expected}) {
+    var matches = RegExp(r'\^\d{1,2}').allMatches(code).toList();
+
+    var matchOffsets = <String, int>{};
+    var delta = 0;
+    for (var match in matches) {
+      var newStart = match.start - delta;
+      var newEnd = match.end - delta;
+      matchOffsets[code.substring(newStart + 1, newEnd)] = newStart;
+      delta += match.end - match.start;
+      code = code.substring(0, newStart) + code.substring(newEnd);
+    }
+
+    var path = convertPath('/home/test/lib/a.dart');
+    newFile(path, content: code);
+
+    var parsedResult = session.getParsedUnit(path);
+    expect(parsedResult.errors, isEmpty);
+
+    var unit = parsedResult.unit;
+    var buffer = StringBuffer();
+    for (var offsetName in matchOffsets.keys) {
+      var offset = matchOffsets[offsetName];
+      var nameSet = Set<String>();
+
+      unit.accept(SyntacticScopeNamesCollector(nameSet, offset));
+
+      var nameList = nameSet.toList();
+      nameList.sort((a, b) {
+        expect(a.startsWith('N'), isTrue);
+        expect(b.startsWith('N'), isTrue);
+        return int.parse(a.substring(1)) - int.parse(b.substring(1));
+      });
+
+      buffer.write('$offsetName: ');
+      if (nameList.isEmpty) {
+        buffer.writeln('{}');
+      } else {
+        buffer.writeln(nameList.join(', '));
+      }
+    }
+
+    var actual = buffer.toString();
+    if (actual != expected) {
+      print(actual);
+    }
+    expect(actual, expected);
+  }
+
+  void _enableExperiments() {
+    createAnalysisOptionsFile(
+      experiments: [
+        EnableString.control_flow_collections,
+        EnableString.spread_collections,
+      ],
+    );
+  }
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart
new file mode 100644
index 0000000..9d53f53
--- /dev/null
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/dart/test_all.dart
@@ -0,0 +1,16 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:test_reflective_loader/test_reflective_loader.dart';
+
+import 'import_library_element_test.dart' as import_library_element;
+import 'syntactic_scope_test.dart' as syntactic_scope;
+
+/// Utility for manually running all tests.
+main() {
+  defineReflectiveSuite(() {
+    import_library_element.main();
+    syntactic_scope.main();
+  });
+}
diff --git a/pkg/analyzer_plugin/test/src/utilities/change_builder/test_all.dart b/pkg/analyzer_plugin/test/src/utilities/change_builder/test_all.dart
index 2c50f7e..2e5d995 100644
--- a/pkg/analyzer_plugin/test/src/utilities/change_builder/test_all.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/change_builder/test_all.dart
@@ -6,11 +6,13 @@
 
 import 'change_builder_core_test.dart' as change_builder_core_test;
 import 'change_builder_dart_test.dart' as change_builder_dart_test;
+import 'dart/test_all.dart' as dart_all;
 
 /// Utility for manually running all tests.
 main() {
   defineReflectiveSuite(() {
     change_builder_core_test.main();
     change_builder_dart_test.main();
+    dart_all.main();
   });
 }
diff --git a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
index 241ec1f..37958bb 100644
--- a/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
+++ b/pkg/analyzer_plugin/test/src/utilities/completion/completion_target_test.dart
@@ -4,10 +4,10 @@
 
 import 'dart:async';
 
-import 'package:analyzer/dart/analysis/results.dart';
 import 'package:analyzer/dart/ast/ast.dart';
+import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/src/generated/parser.dart' as analyzer;
-import 'package:analyzer/src/generated/source.dart';
+import 'package:analyzer/src/test_utilities/find_element.dart';
 import 'package:analyzer_plugin/src/utilities/completion/completion_target.dart';
 import 'package:test/test.dart';
 import 'package:test_reflective_loader/test_reflective_loader.dart';
@@ -16,604 +16,976 @@
 
 main() {
   defineReflectiveSuite(() {
+    defineReflectiveTests(ArgumentListCompletionTargetTest);
     defineReflectiveTests(CompletionTargetTest);
   });
 }
 
 @reflectiveTest
-class CompletionTargetTest extends AbstractContextTest {
-  Source testSource;
-  int completionOffset;
-  CompletionTarget target;
+class ArgumentListCompletionTargetTest extends _Base {
+  test_Annotation_named() async {
+    await createTarget('''
+class Foo {
+  const Foo({int a, String b});
+}
 
-  bool get usingFastaParser => analyzer.Parser.useFasta;
-
-  Future<void> addTestSource(String content) async {
-    expect(completionOffset, isNull, reason: 'Call addTestSource exactly once');
-    completionOffset = content.indexOf('^');
-    expect(completionOffset, isNot(equals(-1)), reason: 'missing ^');
-    int nextOffset = content.indexOf('^', completionOffset + 1);
-    expect(nextOffset, equals(-1), reason: 'too many ^');
-    content = content.substring(0, completionOffset) +
-        content.substring(completionOffset + 1);
-    testSource = addSource('/test.dart', content);
-    ResolvedUnitResult result = await driver.getResult(testSource.fullName);
-    target = new CompletionTarget.forOffset(result.unit, completionOffset);
+@Foo(b: ^)
+main() {}
+''');
+    assertTarget(
+      '',
+      'b: ',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: ({a: int, b: String}) → Foo',
+      expectedParameter: 'b: String',
+    );
   }
 
-  Future<void> assertTarget(entityText, nodeText,
-      {int argIndex: null,
-      bool isFunctionalArgument: false,
-      String droppedToken}) async {
-    void assertCommon() {
-      expect(target.entity.toString(), entityText, reason: 'entity');
-      expect(target.containingNode.toString(), nodeText,
-          reason: 'containingNode');
-      expect(target.argIndex, argIndex, reason: 'argIndex');
-      expect(target.droppedToken?.toString(), droppedToken ?? isNull,
-          reason: 'droppedToken');
-    }
+  test_Annotation_positional() async {
+    await createTarget('''
+class Foo {
+  const Foo(int a);
+}
 
-    // Assert with parsed unit
-    assertCommon();
-    ResolvedUnitResult result = await driver.getResult(testSource.fullName);
-    target = new CompletionTarget.forOffset(result.unit, completionOffset);
-    // Assert more with resolved unit
-    assertCommon();
-    expect(target.isFunctionalArgument(), isFunctionalArgument);
+@Foo(^)
+main() {}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedParameter: 'a: int',
+    );
   }
 
-  test_ArgumentList_InstanceCreationExpression() async {
-    // ArgumentList  InstanceCreationExpression  Block
-    await addTestSource('main() {new Foo(^)}');
-    await assertTarget(')', '()', argIndex: 0);
+  test_InstanceCreationExpression_explicitNew_unresolved() async {
+    await createTarget('''
+main() {
+  new Foo(^)
+}
+''');
+    assertTarget(')', '()', argIndex: 0);
   }
 
-  test_ArgumentList_InstanceCreationExpression2() async {
-    // ArgumentList  InstanceCreationExpression  Block
-    await addTestSource('main() {new Foo(a,^)}');
-    await assertTarget(')', '(a)', argIndex: 1);
+  test_InstanceCreationExpression_generic_explicitTypeArgument() async {
+    await createTarget('''
+class Foo<T> {
+  Foo(T a, T b);
+}
+
+main() {
+  Foo<int>(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: (int, int) → Foo<int>',
+      expectedParameter: 'a: int',
+    );
   }
 
-  test_ArgumentList_InstanceCreationExpression_functionArg2() async {
-    // ArgumentList  InstanceCreationExpression  Block
-    await addTestSource('main() {new B(^)} class B{B(f()){}}');
-    await assertTarget(')', '()', argIndex: 0, isFunctionalArgument: true);
+  test_InstanceCreationExpression_generic_inferredTypeArgument() async {
+    await createTarget('''
+class Foo<T> {
+  Foo(T a, T b);
+}
+
+main() {
+  Foo(false, ^)
+}
+''');
+    assertTarget(
+      ')',
+      '(false)',
+      argIndex: 1,
+      expectedExecutable: 'Foo.<init>: (bool, bool) → Foo<bool>',
+      expectedParameter: 'b: bool',
+    );
   }
 
-  test_ArgumentList_InstanceCreationExpression_functionArg3() async {
-    // ArgumentList  InstanceCreationExpression  Block
-    await addTestSource('main() {new B(1, f: ^)} class B{B(int i, {f()}){}}');
-    await assertTarget('', 'f: ', argIndex: 1, isFunctionalArgument: true);
+  test_InstanceCreationExpression_named() async {
+    await createTarget('''
+class Foo {
+  Foo({int a, String b, double c});
+}
+
+main() {
+  Foo(b: ^)
+}
+''');
+    assertTarget(
+      '',
+      'b: ',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: ({a: int, b: String, c: double}) → Foo',
+      expectedParameter: 'b: String',
+    );
   }
 
-  test_ArgumentList_MethodInvocation() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(^)}');
-    await assertTarget(')', '()', argIndex: 0);
+  test_InstanceCreationExpression_named_unresolved() async {
+    await createTarget('''
+class Foo {
+  Foo({int a});
+}
+
+main() {
+  Foo(b: ^)
+}
+''');
+    assertTarget(
+      '',
+      'b: ',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: ({a: int}) → Foo',
+    );
   }
 
-  test_ArgumentList_MethodInvocation2() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(^n)}');
-    await assertTarget('n', '(n)', argIndex: 0);
+  test_InstanceCreationExpression_namedConstructor() async {
+    await createTarget('''
+class Foo {
+  Foo.named(int a, String b, double c);
+}
+
+main() {
+  Foo.named(0, ^)
+}
+''');
+    assertTarget(
+      ')',
+      '(0)',
+      argIndex: 1,
+      expectedExecutable: 'Foo.named: (int, String, double) → Foo',
+      expectedParameter: 'b: String',
+    );
   }
 
-  test_ArgumentList_MethodInvocation3() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(n^)}');
-    await assertTarget('n', '(n)', argIndex: 0);
+  test_InstanceCreationExpression_positional() async {
+    await createTarget('''
+class Foo {
+  Foo(int a);
+}
+
+main() {
+  Foo(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: (int) → Foo',
+      expectedParameter: 'a: int',
+    );
   }
 
-  test_ArgumentList_MethodInvocation3a() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo((n)^)}');
-    await assertTarget(')', '((n))', argIndex: 0);
+  test_InstanceCreationExpression_positional_isFunctional() async {
+    await createTarget('''
+class Foo {
+  Foo(int Function(String) f);
+}
+
+main() {
+  Foo(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: ((String) → int) → Foo',
+      expectedParameter: 'f: (String) → int',
+      isFunctionalArgument: true,
+    );
   }
 
-  test_ArgumentList_MethodInvocation4() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(n,^)}');
-    await assertTarget(')', '(n)', argIndex: 1);
+  test_InstanceCreationExpression_positional_noParameter0() async {
+    await createTarget('''
+class Foo {}
+
+main() {
+  Foo(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'Foo.<init>: () → Foo',
+    );
   }
 
-  test_ArgumentList_MethodInvocation_functionArg() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(^)} foo(f()) {}');
-    await assertTarget(')', '()', argIndex: 0, isFunctionalArgument: true);
+  test_InstanceCreationExpression_positional_noParameter1() async {
+    await createTarget('''
+class Foo {}
+
+main() {
+  Foo(a, ^)
+}
+''');
+    assertTarget(
+      ')',
+      '(a)',
+      argIndex: 1,
+      expectedExecutable: 'Foo.<init>: () → Foo',
+    );
   }
 
-  test_ArgumentList_MethodInvocation_functionArg2() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {new B().boo(^)} class B{boo(f()){}}');
-    await assertTarget(')', '()', argIndex: 0, isFunctionalArgument: true);
+  test_MethodInvocation_named() async {
+    await createTarget('''
+int foo({int a, String b, double c}) {}
+
+main() {
+  foo(b: ^)
+}
+''');
+    assertTarget(
+      '',
+      'b: ',
+      argIndex: 0,
+      expectedExecutable: 'foo: ({a: int, b: String, c: double}) → int',
+      expectedParameter: 'b: String',
+    );
   }
 
-  test_ArgumentList_MethodInvocation_functionArg3() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {foo(f: ^)} foo({f()}) {}');
-    await assertTarget('', 'f: ', argIndex: 0, isFunctionalArgument: true);
+  test_MethodInvocation_named_isFunctional() async {
+    await createTarget('''
+int foo({int Function(String) f}) {}
+
+main() {
+  foo(f: ^)
+}
+''');
+    assertTarget(
+      '',
+      'f: ',
+      argIndex: 0,
+      expectedExecutable: 'foo: ({f: (String) → int}) → int',
+      expectedParameter: 'f: (String) → int',
+      isFunctionalArgument: true,
+    );
   }
 
-  test_ArgumentList_MethodInvocation_functionArg4() async {
-    // ArgumentList  MethodInvocation  Block
-    await addTestSource('main() {new B().boo(f: ^)} class B{boo({f()}){}}');
-    await assertTarget('', 'f: ', argIndex: 0, isFunctionalArgument: true);
+  test_MethodInvocation_named_unresolved() async {
+    await createTarget('''
+int foo({int a}) {}
+
+main() {
+  foo(b: ^)
+}
+''');
+    assertTarget(
+      '',
+      'b: ',
+      argIndex: 0,
+      expectedExecutable: 'foo: ({a: int}) → int',
+    );
   }
 
+  test_MethodInvocation_positional2() async {
+    await createTarget('''
+int foo(int a, String b) {}
+
+main() {
+  foo(0, ^)
+}
+''');
+    assertTarget(
+      ')',
+      '(0)',
+      argIndex: 1,
+      expectedExecutable: 'foo: (int, String) → int',
+      expectedParameter: 'b: String',
+    );
+  }
+
+  test_MethodInvocation_positional_isFunctional() async {
+    await createTarget('''
+int foo(int Function(String) f) {}
+
+main() {
+  foo(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'foo: ((String) → int) → int',
+      expectedParameter: 'f: (String) → int',
+      isFunctionalArgument: true,
+    );
+  }
+
+  test_MethodInvocation_positional_isFunctional2() async {
+    await createTarget('''
+class C {
+  int foo(int Function(String) f) {}
+}
+
+main(C c) {
+  c.foo(^)
+}
+''');
+    assertTarget(
+      ')',
+      '()',
+      argIndex: 0,
+      expectedExecutable: 'C.foo: ((String) → int) → int',
+      expectedParameter: 'f: (String) → int',
+      isFunctionalArgument: true,
+    );
+  }
+
+  test_MethodInvocation_positional_withPrefix() async {
+    await createTarget('''
+int foo(int a, String b) {}
+
+main() {
+  foo(n^)
+}
+''');
+    assertTarget(
+      'n',
+      '(n)',
+      argIndex: 0,
+      expectedExecutable: 'foo: (int, String) → int',
+      expectedParameter: 'a: int',
+    );
+  }
+
+  test_MethodInvocation_positional_withPrefix2() async {
+    await createTarget('''
+int foo(int a, String b) {}
+
+main() {
+  foo((n)^)
+}
+''');
+    assertTarget(
+      ')',
+      '((n))',
+      argIndex: 0,
+      expectedExecutable: 'foo: (int, String) → int',
+      expectedParameter: 'a: int',
+    );
+  }
+
+  test_MethodInvocation_positional_withSuffix() async {
+    await createTarget('''
+int foo(int a, String b) {}
+
+main() {
+  foo(^n)
+}
+''');
+    assertTarget(
+      'n',
+      '(n)',
+      argIndex: 0,
+      expectedExecutable: 'foo: (int, String) → int',
+      expectedParameter: 'a: int',
+    );
+  }
+
+  test_MethodInvocation_unresolved() async {
+    await createTarget('''
+main() {
+  foo(^)
+}
+''');
+    assertTarget(')', '()', argIndex: 0);
+  }
+
+  test_not_ListLiteral() async {
+    await createTarget('''
+main() {
+  print([^]);
+}
+''');
+    expect(target.argIndex, isNull);
+    expect(target.executableElement, isNull);
+    expect(target.parameterElement, isNull);
+  }
+}
+
+@reflectiveTest
+class CompletionTargetTest extends _Base {
   test_AsExpression_identifier() async {
     // SimpleIdentifier  TypeName  AsExpression
-    await addTestSource(
+    await createTarget(
         'class A {var b; X _c; foo() {var a; (a^ as String).foo();}');
-    await assertTarget('a as String', '(a as String)');
+    assertTarget('a as String', '(a as String)');
   }
 
   test_AsExpression_keyword() async {
     // SimpleIdentifier  TypeName  AsExpression
-    await addTestSource(
+    await createTarget(
         'class A {var b; X _c; foo() {var a; (a ^as String).foo();}');
-    await assertTarget('as', 'a as String');
+    assertTarget('as', 'a as String');
   }
 
   test_AsExpression_keyword2() async {
     // SimpleIdentifier  TypeName  AsExpression
-    await addTestSource(
+    await createTarget(
         'class A {var b; X _c; foo() {var a; (a a^s String).foo();}');
-    await assertTarget('as', 'a as String');
+    assertTarget('as', 'a as String');
   }
 
   test_AsExpression_keyword3() async {
     // SimpleIdentifier  TypeName  AsExpression
-    await addTestSource(
+    await createTarget(
         'class A {var b; X _c; foo() {var a; (a as^ String).foo();}');
-    await assertTarget('as', 'a as String');
+    assertTarget('as', 'a as String');
   }
 
   test_AsExpression_type() async {
     // SimpleIdentifier  TypeName  AsExpression
-    await addTestSource(
+    await createTarget(
         'class A {var b; X _c; foo() {var a; (a as ^String).foo();}');
-    await assertTarget('String', 'a as String');
+    assertTarget('String', 'a as String');
   }
 
   test_Block() async {
     // Block
-    await addTestSource('main() {^}');
-    await assertTarget('}', '{}');
+    await createTarget('main() {^}');
+    assertTarget('}', '{}');
   }
 
   test_Block_keyword() async {
-    await addTestSource(
+    await createTarget(
         'class C { static C get instance => null; } main() {C.in^}');
-    await assertTarget('in', 'C.in');
+    assertTarget('in', 'C.in');
   }
 
   test_Block_keyword2() async {
-    await addTestSource(
+    await createTarget(
         'class C { static C get instance => null; } main() {C.i^n}');
-    await assertTarget('in', 'C.in');
+    assertTarget('in', 'C.in');
   }
 
   test_FormalParameter_partialType() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName
-    await addTestSource('foo(b.^ f) { }');
-    await assertTarget('f', 'b.f');
+    await createTarget('foo(b.^ f) { }');
+    assertTarget('f', 'b.f');
   }
 
   test_FormalParameter_partialType2() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName
-    await addTestSource('foo(b.z^ f) { }');
-    await assertTarget('z', 'b.z');
+    await createTarget('foo(b.z^ f) { }');
+    assertTarget('z', 'b.z');
   }
 
   test_FormalParameter_partialType3() async {
     // SimpleIdentifier  PrefixedIdentifier  TypeName
-    await addTestSource('foo(b.^) { }');
-    await assertTarget('', 'b.');
+    await createTarget('foo(b.^) { }');
+    assertTarget('', 'b.');
   }
 
   test_FormalParameterList() async {
     // Token  FormalParameterList  FunctionExpression
-    await addTestSource('foo(^) { }');
-    await assertTarget(')', '()');
+    await createTarget('foo(^) { }');
+    assertTarget(')', '()');
   }
 
   test_FunctionDeclaration_inLineComment() async {
     // Comment  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       // normal comment ^
       zoo(z) { } String name;''');
-    await assertTarget('// normal comment ', 'zoo(z) {} String name;');
+    assertTarget('// normal comment ', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inLineComment2() async {
     // Comment  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       // normal ^comment
       zoo(z) { } String name;''');
-    await assertTarget('// normal comment', 'zoo(z) {} String name;');
+    assertTarget('// normal comment', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inLineComment3() async {
     // Comment  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       // normal comment ^
       // normal comment 2
       zoo(z) { } String name;''');
-    await assertTarget('// normal comment ', 'zoo(z) {} String name;');
+    assertTarget('// normal comment ', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inLineComment4() async {
     // Comment  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       // normal comment
       // normal comment 2^
       zoo(z) { } String name;''');
-    await assertTarget('// normal comment 2', 'zoo(z) {} String name;');
+    assertTarget('// normal comment 2', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inLineDocComment() async {
     // Comment  FunctionDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       /// some dartdoc ^
       zoo(z) { } String name;''');
-    await assertTarget('/// some dartdoc ', '');
+    assertTarget('/// some dartdoc ', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_inLineDocComment2() async {
     // Comment  FunctionDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       /// some ^dartdoc
       zoo(z) { } String name;''');
-    await assertTarget('/// some dartdoc', '');
+    assertTarget('/// some dartdoc', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_inStarComment() async {
     // Comment  CompilationUnit
-    await addTestSource('/* ^ */ zoo(z) {} String name;');
-    await assertTarget('/*  */', 'zoo(z) {} String name;');
+    await createTarget('/* ^ */ zoo(z) {} String name;');
+    assertTarget('/*  */', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inStarComment2() async {
     // Comment  CompilationUnit
-    await addTestSource('/*  *^/ zoo(z) {} String name;');
-    await assertTarget('/*  */', 'zoo(z) {} String name;');
+    await createTarget('/*  *^/ zoo(z) {} String name;');
+    assertTarget('/*  */', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_inStarDocComment() async {
     // Comment  FunctionDeclaration  CompilationUnit
-    await addTestSource('/** ^ */ zoo(z) { } String name;');
-    await assertTarget('/**  */', '');
+    await createTarget('/** ^ */ zoo(z) { } String name;');
+    assertTarget('/**  */', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_inStarDocComment2() async {
     // Comment  FunctionDeclaration  CompilationUnit
-    await addTestSource('/**  *^/ zoo(z) { } String name;');
-    await assertTarget('/**  */', '');
+    await createTarget('/**  *^/ zoo(z) { } String name;');
+    assertTarget('/**  */', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_returnType() async {
     // CompilationUnit
-    await addTestSource('^ zoo(z) { } String name;');
-    await assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
+    await createTarget('^ zoo(z) { } String name;');
+    assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_returnType_afterLineComment() async {
     // FunctionDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       // normal comment
       ^ zoo(z) {} String name;''');
-    await assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
+    assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_returnType_afterLineComment2() async {
     // FunctionDeclaration  CompilationUnit
     // TOD(danrubel) left align all test source
-    await addTestSource('''
+    await createTarget('''
 // normal comment
 ^ zoo(z) {} String name;''');
-    await assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
+    assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_returnType_afterLineDocComment() async {
     // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       /// some dartdoc
       ^ zoo(z) { } String name; ''');
-    await assertTarget('zoo', 'zoo(z) {}');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_returnType_afterLineDocComment2() async {
     // SimpleIdentifier  FunctionDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
 /// some dartdoc
 ^ zoo(z) { } String name;''');
-    await assertTarget('zoo', 'zoo(z) {}');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_returnType_afterStarComment() async {
     // CompilationUnit
-    await addTestSource('/* */ ^ zoo(z) { } String name;');
-    await assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
+    await createTarget('/* */ ^ zoo(z) { } String name;');
+    assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_returnType_afterStarComment2() async {
     // CompilationUnit
-    await addTestSource('/* */^ zoo(z) { } String name;');
-    await assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
+    await createTarget('/* */^ zoo(z) { } String name;');
+    assertTarget('zoo(z) {}', 'zoo(z) {} String name;');
   }
 
   test_FunctionDeclaration_returnType_afterStarDocComment() async {
     // FunctionDeclaration  CompilationUnit
-    await addTestSource('/** */ ^ zoo(z) { } String name;');
-    await assertTarget('zoo', 'zoo(z) {}');
+    await createTarget('/** */ ^ zoo(z) { } String name;');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_FunctionDeclaration_returnType_afterStarDocComment2() async {
     // FunctionDeclaration  CompilationUnit
-    await addTestSource('/** */^ zoo(z) { } String name;');
-    await assertTarget('zoo', 'zoo(z) {}');
+    await createTarget('/** */^ zoo(z) { } String name;');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_IfStatement_droppedToken() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('main() { if (v i^) }');
+    await createTarget('main() { if (v i^) }');
     if (usingFastaParser) {
-      await assertTarget(')', 'if (v) ;', droppedToken: 'i');
+      assertTarget(')', 'if (v) ;', droppedToken: 'i');
     } else {
-      await assertTarget('i;', 'if (v) i;');
+      assertTarget('i;', 'if (v) i;');
     }
   }
 
   test_InstanceCreationExpression_identifier() async {
     // InstanceCreationExpression  ExpressionStatement  Block
-    await addTestSource('class C {foo(){var f; {var x;} new ^C();}}');
-    await assertTarget('C', 'new C()');
+    await createTarget('class C {foo(){var f; {var x;} new ^C();}}');
+    assertTarget('C', 'new C()');
   }
 
   test_InstanceCreationExpression_keyword() async {
     // InstanceCreationExpression  ExpressionStatement  Block
-    await addTestSource('class C {foo(){var f; {var x;} new^ }}');
-    await assertTarget('new ();', '{var f; {var x;} new ();}');
+    await createTarget('class C {foo(){var f; {var x;} new^ }}');
+    assertTarget('new ();', '{var f; {var x;} new ();}');
   }
 
   test_InstanceCreationExpression_keyword2() async {
     // InstanceCreationExpression  ExpressionStatement  Block
-    await addTestSource('class C {foo(){var f; {var x;} new^ C();}}');
-    await assertTarget('new C();', '{var f; {var x;} new C();}');
+    await createTarget('class C {foo(){var f; {var x;} new^ C();}}');
+    assertTarget('new C();', '{var f; {var x;} new C();}');
   }
 
   test_MapLiteralEntry() async {
     // MapLiteralEntry  MapLiteral  VariableDeclaration
-    await addTestSource('foo = {^');
+    await createTarget('foo = {^');
     // fasta scanner inserts synthetic closing '}'
-    await assertTarget('}', '{}');
+    assertTarget('}', '{}');
   }
 
   test_MapLiteralEntry1() async {
     // MapLiteralEntry  MapLiteral  VariableDeclaration
-    await addTestSource('foo = {T^');
-    await assertTarget('T : ', '{T : }');
+    await createTarget('foo = {1: 2, T^');
+    assertTarget('T : ', '{1 : 2, T : }');
   }
 
   test_MapLiteralEntry2() async {
     // SimpleIdentifier  MapLiteralEntry  MapLiteral  VariableDeclaration
-    await addTestSource('foo = {7:T^};');
-    await assertTarget('T', '7 : T');
+    await createTarget('foo = {7:T^};');
+    assertTarget('T', '7 : T');
   }
 
   test_MethodDeclaration_inLineComment() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         // normal comment ^
         zoo(z) { } String name; }''');
-    await assertTarget(
-        '// normal comment ', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('// normal comment ', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inLineComment2() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         // normal ^comment
         zoo(z) { } String name; }''');
-    await assertTarget(
-        '// normal comment', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('// normal comment', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inLineComment3() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         // normal comment ^
         // normal comment 2
         zoo(z) { } String name; }''');
-    await assertTarget(
-        '// normal comment ', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('// normal comment ', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inLineComment4() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         // normal comment
         // normal comment 2^
         zoo(z) { } String name; }''');
-    await assertTarget(
-        '// normal comment 2', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('// normal comment 2', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inLineDocComment() async {
     // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         /// some dartdoc ^
         zoo(z) { } String name; }''');
-    await assertTarget('/// some dartdoc ', '');
+    assertTarget('/// some dartdoc ', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_MethodDeclaration_inLineDocComment2() async {
     // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         /// some ^dartdoc
         zoo(z) { } String name; }''');
-    await assertTarget('/// some dartdoc', '');
+    assertTarget('/// some dartdoc', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_MethodDeclaration_inStarComment() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/* ^ */ zoo(z) {} String name;}');
-    await assertTarget('/*  */', 'class C2 {zoo(z) {} String name;}');
+    await createTarget('class C2 {/* ^ */ zoo(z) {} String name;}');
+    assertTarget('/*  */', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inStarComment2() async {
     // Comment  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/*  *^/ zoo(z) {} String name;}');
-    await assertTarget('/*  */', 'class C2 {zoo(z) {} String name;}');
+    await createTarget('class C2 {/*  *^/ zoo(z) {} String name;}');
+    assertTarget('/*  */', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_inStarDocComment() async {
     // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/** ^ */ zoo(z) { } String name; }');
-    await assertTarget('/**  */', '');
+    await createTarget('class C2 {/** ^ */ zoo(z) { } String name; }');
+    assertTarget('/**  */', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_MethodDeclaration_inStarDocComment2() async {
     // Comment  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/**  *^/ zoo(z) { } String name; }');
-    await assertTarget('/**  */', '');
+    await createTarget('class C2 {/**  *^/ zoo(z) { } String name; }');
+    assertTarget('/**  */', '');
     expect(target.containingNode is Comment, isTrue);
     expect(target.containingNode.parent.toSource(), 'zoo(z) {}');
   }
 
   test_MethodDeclaration_returnType() async {
     // ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {^ zoo(z) { } String name; }');
-    await assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
+    await createTarget('class C2 {^ zoo(z) { } String name; }');
+    assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_returnType_afterLineComment() async {
     // MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         // normal comment
         ^ zoo(z) {} String name;}''');
-    await assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_returnType_afterLineComment2() async {
     // MethodDeclaration  ClassDeclaration  CompilationUnit
     // TOD(danrubel) left align all test source
-    await addTestSource('''
+    await createTarget('''
 class C2 {
   // normal comment
 ^ zoo(z) {} String name;}''');
-    await assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
+    assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_returnType_afterLineDocComment() async {
     // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
       class C2 {
         /// some dartdoc
         ^ zoo(z) { } String name; }''');
-    await assertTarget('zoo', 'zoo(z) {}');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_MethodDeclaration_returnType_afterLineDocComment2() async {
     // SimpleIdentifier  MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('''
+    await createTarget('''
 class C2 {
   /// some dartdoc
 ^ zoo(z) { } String name; }''');
-    await assertTarget('zoo', 'zoo(z) {}');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_MethodDeclaration_returnType_afterStarComment() async {
     // ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/* */ ^ zoo(z) { } String name; }');
-    await assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
+    await createTarget('class C2 {/* */ ^ zoo(z) { } String name; }');
+    assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_returnType_afterStarComment2() async {
     // ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/* */^ zoo(z) { } String name; }');
-    await assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
+    await createTarget('class C2 {/* */^ zoo(z) { } String name; }');
+    assertTarget('zoo(z) {}', 'class C2 {zoo(z) {} String name;}');
   }
 
   test_MethodDeclaration_returnType_afterStarDocComment() async {
     // MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/** */ ^ zoo(z) { } String name; }');
-    await assertTarget('zoo', 'zoo(z) {}');
+    await createTarget('class C2 {/** */ ^ zoo(z) { } String name; }');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_MethodDeclaration_returnType_afterStarDocComment2() async {
     // MethodDeclaration  ClassDeclaration  CompilationUnit
-    await addTestSource('class C2 {/** */^ zoo(z) { } String name; }');
-    await assertTarget('zoo', 'zoo(z) {}');
+    await createTarget('class C2 {/** */^ zoo(z) { } String name; }');
+    assertTarget('zoo', 'zoo(z) {}');
   }
 
   test_SwitchStatement_c() async {
     // Token('c') SwitchStatement
-    await addTestSource('main() { switch(x) {c^} }');
-    await assertTarget('}', 'switch (x) {}', droppedToken: 'c');
+    await createTarget('main() { switch(x) {c^} }');
+    assertTarget('}', 'switch (x) {}', droppedToken: 'c');
   }
 
   test_SwitchStatement_c2() async {
     // Token('c') SwitchStatement
-    await addTestSource('main() { switch(x) { c^ } }');
-    await assertTarget('}', 'switch (x) {}', droppedToken: 'c');
+    await createTarget('main() { switch(x) { c^ } }');
+    assertTarget('}', 'switch (x) {}', droppedToken: 'c');
   }
 
   test_SwitchStatement_empty() async {
     // SwitchStatement
-    await addTestSource('main() { switch(x) {^} }');
-    await assertTarget('}', 'switch (x) {}');
+    await createTarget('main() { switch(x) {^} }');
+    assertTarget('}', 'switch (x) {}');
   }
 
   test_SwitchStatement_empty2() async {
     // SwitchStatement
-    await addTestSource('main() { switch(x) { ^ } }');
-    await assertTarget('}', 'switch (x) {}');
+    await createTarget('main() { switch(x) { ^ } }');
+    assertTarget('}', 'switch (x) {}');
   }
 
   test_TypeArgumentList() async {
     // TypeName  TypeArgumentList  TypeName
-    await addTestSource('main() { C<^> c; }');
-    await assertTarget('', '<>');
+    await createTarget('main() { C<^> c; }');
+    assertTarget('', '<>');
   }
 
   test_TypeArgumentList2() async {
     // TypeName  TypeArgumentList  TypeName
-    await addTestSource('main() { C<C^> c; }');
-    await assertTarget('C', '<C>');
+    await createTarget('main() { C<C^> c; }');
+    assertTarget('C', '<C>');
   }
 
   test_VariableDeclaration_lhs_identifier_after() async {
     // VariableDeclaration  VariableDeclarationList
-    await addTestSource('main() {int b^ = 1;}');
-    await assertTarget('b = 1', 'int b = 1');
+    await createTarget('main() {int b^ = 1;}');
+    assertTarget('b = 1', 'int b = 1');
   }
 
   test_VariableDeclaration_lhs_identifier_before() async {
     // VariableDeclaration  VariableDeclarationList
-    await addTestSource('main() {int ^b = 1;}');
-    await assertTarget('b = 1', 'int b = 1');
+    await createTarget('main() {int ^b = 1;}');
+    assertTarget('b = 1', 'int b = 1');
+  }
+}
+
+class _Base extends AbstractContextTest {
+  int offset;
+  CompletionTarget target;
+  FindElement findElement;
+
+  bool get usingFastaParser => analyzer.Parser.useFasta;
+
+  void assertTarget(
+    String entityText,
+    String nodeText, {
+    int argIndex: null,
+    String droppedToken,
+    bool isFunctionalArgument: false,
+    String expectedExecutable,
+    String expectedParameter,
+  }) {
+    expect(
+      target.entity.toString(),
+      entityText,
+      reason: 'entity',
+    );
+
+    expect(
+      target.containingNode.toString(),
+      nodeText,
+      reason: 'containingNode',
+    );
+
+    expect(
+      target.argIndex,
+      argIndex,
+      reason: 'argIndex',
+    );
+
+    expect(
+      target.droppedToken?.toString(),
+      droppedToken ?? isNull,
+      reason: 'droppedToken',
+    );
+
+    var actualExecutable = target.executableElement;
+    if (expectedExecutable == null) {
+      expect(actualExecutable, isNull);
+    } else {
+      expect(_executableStr(actualExecutable), expectedExecutable);
+    }
+
+    var actualParameter = target.parameterElement;
+    if (expectedParameter == null) {
+      expect(actualParameter, isNull);
+    } else {
+      expect(_parameterStr(actualParameter), expectedParameter);
+    }
+
+    expect(target.isFunctionalArgument(), isFunctionalArgument);
+  }
+
+  Future<void> createTarget(String content) async {
+    expect(offset, isNull, reason: 'Call createTarget exactly once');
+
+    offset = content.indexOf('^');
+    expect(offset, isNot(equals(-1)), reason: 'missing ^');
+
+    int nextOffset = content.indexOf('^', offset + 1);
+    expect(nextOffset, equals(-1), reason: 'too many ^');
+
+    content = content.substring(0, offset) + content.substring(offset + 1);
+
+    var path = convertPath('/home/test/lib/test.dart');
+    newFile(path, content: content);
+
+    var result = await driver.getResult(path);
+    findElement = FindElement(result.unit);
+
+    target = new CompletionTarget.forOffset(result.unit, offset);
+  }
+
+  static String _executableNameStr(ExecutableElement executable) {
+    var executableEnclosing = executable.enclosingElement;
+    if (executableEnclosing is CompilationUnitElement) {
+      return executable.name;
+    } else if (executable is ConstructorElement) {
+      if (executable.name == '') {
+        return '${executableEnclosing.name}.<init>';
+      } else {
+        return '${executableEnclosing.name}.${executable.name}';
+      }
+    } else if (executable is MethodElement) {
+      return '${executableEnclosing.name}.${executable.name}';
+    }
+    fail('Unexpected element: $executable');
+  }
+
+  static String _executableStr(ExecutableElement element) {
+    var executableStr = _executableNameStr(element);
+
+    return '$executableStr: ${element.type}';
+  }
+
+  static String _parameterStr(ParameterElement element) {
+    return '${element.name}: ${element.type}';
   }
 }
diff --git a/pkg/analyzer_plugin/test/support/abstract_context.dart b/pkg/analyzer_plugin/test/support/abstract_context.dart
index f06e837..10d21a7 100644
--- a/pkg/analyzer_plugin/test/support/abstract_context.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_context.dart
@@ -44,6 +44,10 @@
 class AbstractContextTest with ResourceProviderMixin {
   AnalysisDriver _driver;
 
+  /// The file system specific `/home/test/analysis_options.yaml` path.
+  String get analysisOptionsPath =>
+      convertPath('/home/test/analysis_options.yaml');
+
   AnalysisDriver get driver => _driver;
 
   AnalysisSession get session => driver.currentSession;
@@ -81,6 +85,25 @@
     return source;
   }
 
+  /// Create an analysis options file based on the given arguments.
+  void createAnalysisOptionsFile({List<String> experiments}) {
+    var buffer = new StringBuffer();
+    buffer.writeln('analyzer:');
+
+    if (experiments != null) {
+      buffer.writeln('  enable-experiment:');
+      for (var experiment in experiments) {
+        buffer.writeln('    - $experiment');
+      }
+    }
+
+    newFile(analysisOptionsPath, content: buffer.toString());
+
+    if (_driver != null) {
+      _createDriver();
+    }
+  }
+
   Element findElementInUnit(CompilationUnit unit, String name,
       [ElementKind kind]) {
     return findElementsByName(unit, name)
diff --git a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
index 0b14065..923d7b0 100644
--- a/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
+++ b/pkg/analyzer_plugin/test/support/abstract_single_unit.dart
@@ -7,6 +7,7 @@
 import 'package:analyzer/dart/ast/ast.dart';
 import 'package:analyzer/dart/element/element.dart';
 import 'package:analyzer/error/error.dart';
+import 'package:analyzer/src/dart/ast/element_locator.dart';
 import 'package:analyzer/src/dart/ast/utilities.dart';
 import 'package:analyzer/src/dart/error/hint_codes.dart';
 import 'package:analyzer/src/generated/java_engine.dart';
diff --git a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
index 5611381..08ba2a4 100644
--- a/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
+++ b/pkg/analyzer_plugin/test/utilities/completion/type_member_contributor_test.dart
@@ -126,7 +126,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -152,7 +151,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -179,7 +177,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -208,7 +205,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -235,7 +231,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -261,7 +256,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -288,7 +282,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('bar');
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
@@ -315,7 +308,6 @@
     await computeSuggestions();
     expect(replacementOffset, completionOffset);
     expect(replacementLength, 0);
-    assertNoSuggestions(kind: CompletionSuggestionKind.ARGUMENT_LIST);
     assertNotSuggested('hasLength');
     assertNotSuggested('identical');
     assertNotSuggested('B');
diff --git a/pkg/analyzer_plugin/tool/spec/check_all_test.dart b/pkg/analyzer_plugin/tool/spec/check_all_test.dart
index 33f1cca..82806db 100644
--- a/pkg/analyzer_plugin/tool/spec/check_all_test.dart
+++ b/pkg/analyzer_plugin/tool/spec/check_all_test.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart';
 
 import 'generate_all.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart b/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart
index 0669bef..f4e92dd 100644
--- a/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart
+++ b/pkg/analyzer_plugin/tool/spec/codegen_dart_protocol.dart
@@ -4,7 +4,7 @@
 
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 import 'package:path/path.dart' as path;
 
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart b/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
index 8fec4fa..924e5c3 100644
--- a/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
+++ b/pkg/analyzer_plugin/tool/spec/codegen_inttest_methods.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart' as path;
 
 import 'api.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart b/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
index 226c707..bd6c7e1 100644
--- a/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
+++ b/pkg/analyzer_plugin/tool/spec/codegen_matchers.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 import 'from_html.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart b/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart
index 4f81c83..0798d31 100644
--- a/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart
+++ b/pkg/analyzer_plugin/tool/spec/codegen_protocol_common.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart' as path;
 
 import 'api.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/codegen_protocol_constants.dart b/pkg/analyzer_plugin/tool/spec/codegen_protocol_constants.dart
index 755f586..7ff2570 100644
--- a/pkg/analyzer_plugin/tool/spec/codegen_protocol_constants.dart
+++ b/pkg/analyzer_plugin/tool/spec/codegen_protocol_constants.dart
@@ -2,7 +2,7 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 import 'codegen_dart.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/from_html.dart b/pkg/analyzer_plugin/tool/spec/from_html.dart
index 34f8a62..fe9cf69 100644
--- a/pkg/analyzer_plugin/tool/spec/from_html.dart
+++ b/pkg/analyzer_plugin/tool/spec/from_html.dart
@@ -7,7 +7,7 @@
  */
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/html.dart';
+import 'package:analysis_tool/html.dart';
 import 'package:html/dom.dart' as dom;
 import 'package:html/parser.dart' as parser;
 import 'package:path/path.dart';
diff --git a/pkg/analyzer_plugin/tool/spec/generate_all.dart b/pkg/analyzer_plugin/tool/spec/generate_all.dart
index f60d83a..f959c85 100644
--- a/pkg/analyzer_plugin/tool/spec/generate_all.dart
+++ b/pkg/analyzer_plugin/tool/spec/generate_all.dart
@@ -4,7 +4,7 @@
 
 import 'dart:io';
 
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:path/path.dart';
 
 import 'codegen_dart_protocol.dart' as codegen_dart_protocol;
diff --git a/pkg/analyzer_plugin/tool/spec/implied_types.dart b/pkg/analyzer_plugin/tool/spec/implied_types.dart
index 856b2a4..2cf1c8b 100644
--- a/pkg/analyzer_plugin/tool/spec/implied_types.dart
+++ b/pkg/analyzer_plugin/tool/spec/implied_types.dart
@@ -5,7 +5,7 @@
 /**
  * Code for enumerating the set of types implied by the API.
  */
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/tools.dart';
 
 import 'api.dart';
 
diff --git a/pkg/analyzer_plugin/tool/spec/to_html.dart b/pkg/analyzer_plugin/tool/spec/to_html.dart
index 0956e6f..5a519e0 100644
--- a/pkg/analyzer_plugin/tool/spec/to_html.dart
+++ b/pkg/analyzer_plugin/tool/spec/to_html.dart
@@ -9,8 +9,8 @@
  */
 import 'dart:convert';
 
-import 'package:analyzer/src/codegen/html.dart';
-import 'package:analyzer/src/codegen/tools.dart';
+import 'package:analysis_tool/html.dart';
+import 'package:analysis_tool/tools.dart';
 import 'package:html/dom.dart' as dom;
 
 import 'api.dart';
diff --git a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
index dbb43d6..6322222 100644
--- a/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
+++ b/pkg/compiler/lib/src/inferrer/abstract_value_domain.dart
@@ -44,6 +44,9 @@
   static AbstractBool trueOrFalse(bool value) => value ? True : False;
 
   static AbstractBool maybeOrFalse(bool value) => value ? Maybe : False;
+
+  String toString() =>
+      'AbstractBool.${_value == null ? 'Maybe' : (_value ? 'True' : 'False')}';
 }
 
 /// Strategy for the abstraction of runtime values used by the global type
diff --git a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
index 60ea7a3..2eedb7b 100644
--- a/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
+++ b/pkg/compiler/lib/src/inferrer/inferrer_engine.dart
@@ -1242,7 +1242,7 @@
 
   @override
   bool assumeDynamic(MemberEntity member) {
-    return closedWorld.annotationsData.assumeDynamicMembers.contains(member);
+    return closedWorld.annotationsData.hasAssumeDynamic(member);
   }
 }
 
@@ -1272,8 +1272,11 @@
 
   @override
   void forEachParameter(FunctionEntity function, void f(Local parameter)) {
-    forEachOrderedParameter(
-        _closedWorld.globalLocalsMap, _closedWorld.elementMap, function, f);
+    forEachOrderedParameterAsLocal(
+        _closedWorld.globalLocalsMap, _closedWorld.elementMap, function,
+        (Local parameter, {bool isElided}) {
+      f(parameter);
+    });
   }
 
   @override
diff --git a/pkg/compiler/lib/src/io/kernel_source_information.dart b/pkg/compiler/lib/src/io/kernel_source_information.dart
index eb71af5..3e63370 100644
--- a/pkg/compiler/lib/src/io/kernel_source_information.dart
+++ b/pkg/compiler/lib/src/io/kernel_source_information.dart
@@ -24,7 +24,10 @@
   @override
   SourceInformationBuilder createBuilderForContext(MemberEntity member) {
     return new KernelSourceInformationBuilder(
-        _backendStrategy.elementMap, member);
+        _backendStrategy
+            // ignore:deprecated_member_use_from_same_package
+            .elementMap,
+        member);
   }
 }
 
diff --git a/pkg/compiler/lib/src/ir/impact.dart b/pkg/compiler/lib/src/ir/impact.dart
index 570fa82..f7118bd 100644
--- a/pkg/compiler/lib/src/ir/impact.dart
+++ b/pkg/compiler/lib/src/ir/impact.dart
@@ -10,15 +10,185 @@
 import 'package:kernel/type_environment.dart' as ir;
 
 import '../common.dart';
+import 'impact_data.dart';
+import 'runtime_type_analysis.dart';
 import 'scope.dart';
 import 'static_type.dart';
 import 'static_type_base.dart';
 import 'util.dart';
 
-abstract class ImpactBuilder extends StaticTypeVisitor {
+/// Interface for collecting world impact data.
+///
+/// This is used both for direct world impact computation through the
+/// [KernelImpactBuilder] and for serialization through the [ImpactBuilder]
+/// and [ImpactLoader].
+abstract class ImpactRegistry {
+  void registerIntLiteral(int value);
+
+  void registerDoubleLiteral(double value);
+
+  void registerBoolLiteral(bool value);
+
+  void registerStringLiteral(String value);
+
+  void registerSymbolLiteral(String value);
+
+  void registerNullLiteral();
+
+  void registerListLiteral(ir.DartType elementType,
+      {bool isConst, bool isEmpty});
+
+  void registerSetLiteral(ir.DartType elementType,
+      {bool isConst, bool isEmpty});
+
+  void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
+      {bool isConst, bool isEmpty});
+
+  void registerStaticTearOff(
+      ir.Procedure procedure, ir.LibraryDependency import);
+
+  void registerStaticGet(ir.Member member, ir.LibraryDependency import);
+
+  void registerStaticSet(ir.Member member, ir.LibraryDependency import);
+
+  void registerAssert({bool withMessage});
+
+  void registerGenericInstantiation(
+      ir.FunctionType expressionType, List<ir.DartType> typeArguments);
+
+  void registerSyncStar(ir.DartType elementType);
+
+  void registerAsync(ir.DartType elementType);
+
+  void registerAsyncStar(ir.DartType elementType);
+
+  void registerStringConcatenation();
+
+  void registerLocalFunction(ir.TreeNode node);
+
+  void registerLocalWithoutInitializer();
+
+  void registerIsCheck(ir.DartType type);
+
+  void registerImplicitCast(ir.DartType type);
+
+  void registerAsCast(ir.DartType type);
+
+  void registerThrow();
+
+  void registerSyncForIn(ir.DartType iterableType);
+
+  void registerAsyncForIn(ir.DartType iterableType);
+
+  void registerCatch();
+
+  void registerStackTrace();
+
+  void registerCatchType(ir.DartType type);
+
+  void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import);
+
+  void registerFieldInitializer(ir.Field node);
+
+  void registerLoadLibrary();
+
+  void registerRedirectingInitializer(
+      ir.Constructor constructor,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerParameterCheck(ir.DartType type);
+
+  void registerLazyField();
+
+  void registerNew(
+      ir.Member constructor,
+      ir.InterfaceType type,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
+      ir.LibraryDependency import,
+      {bool isConst});
+
+  void registerStaticInvocation(
+      ir.Procedure target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
+      ir.LibraryDependency import);
+
+  void registerLocalFunctionInvocation(
+      ir.FunctionDeclaration localFunction,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerDynamicInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Name name,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerInstanceInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Member target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerFunctionInvocation(
+      ir.DartType receiverType,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerDynamicGet(
+      ir.DartType receiverType, ClassRelation relation, ir.Name name);
+
+  void registerInstanceGet(
+      ir.DartType receiverType, ClassRelation relation, ir.Member target);
+
+  void registerDynamicSet(
+      ir.DartType receiverType, ClassRelation relation, ir.Name name);
+
+  void registerInstanceSet(
+      ir.DartType receiverType, ClassRelation relation, ir.Member target);
+
+  void registerSuperInvocation(ir.Name name, int positionalArguments,
+      List<String> namedArguments, List<ir.DartType> typeArguments);
+
+  void registerSuperGet(ir.Name name);
+
+  void registerSuperSet(ir.Name name);
+
+  void registerSuperInitializer(
+      ir.Constructor source,
+      ir.Constructor target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments);
+
+  void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+      ir.DartType receiverType, ir.DartType argumentType);
+
+  // TODO(johnniwinther): Remove these when CFE provides constants.
+  void registerConstructorNode(ir.Constructor node);
+  void registerFieldNode(ir.Field node);
+  void registerProcedureNode(ir.Procedure node);
+  void registerStaticInvocationNode(ir.StaticInvocation node);
+  void registerSwitchStatementNode(ir.SwitchStatement node);
+  void registerConstConstructorInvocationNode(ir.ConstructorInvocation node);
+}
+
+abstract class ImpactBuilderBase extends StaticTypeVisitor
+    implements ImpactRegistry {
   final VariableScopeModel variableScopeModel;
 
-  ImpactBuilder(ir.TypeEnvironment typeEnvironment,
+  ImpactBuilderBase(ir.TypeEnvironment typeEnvironment,
       ir.ClassHierarchy classHierarchy, this.variableScopeModel)
       : super(typeEnvironment, classHierarchy);
 
@@ -32,71 +202,54 @@
     }
   }
 
-  void registerIntLiteral(int value);
-
   @override
   void handleIntLiteral(ir.IntLiteral node) {
     registerIntLiteral(node.value);
   }
 
-  void registerDoubleLiteral(double value);
-
   @override
   void handleDoubleLiteral(ir.DoubleLiteral node) {
     registerDoubleLiteral(node.value);
   }
 
-  void registerBoolLiteral(bool value);
-
   @override
   void handleBoolLiteral(ir.BoolLiteral node) {
     registerBoolLiteral(node.value);
   }
 
-  void registerStringLiteral(String value);
-
   @override
   void handleStringLiteral(ir.StringLiteral node) {
     registerStringLiteral(node.value);
   }
 
-  void registerSymbolLiteral(String value);
-
   @override
   void handleSymbolLiteral(ir.SymbolLiteral node) {
     registerSymbolLiteral(node.value);
   }
 
-  void registerNullLiteral();
-
   @override
   void handleNullLiteral(ir.NullLiteral node) {
     registerNullLiteral();
   }
 
-  void registerListLiteral(ir.DartType elementType,
-      {bool isConstant, bool isEmpty});
-
   @override
   void handleListLiteral(ir.ListLiteral node) {
     registerListLiteral(node.typeArgument,
-        isConstant: node.isConst, isEmpty: node.expressions.isEmpty);
+        isConst: node.isConst, isEmpty: node.expressions.isEmpty);
   }
 
-  void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
-      {bool isConstant, bool isEmpty});
+  @override
+  void handleSetLiteral(ir.SetLiteral node) {
+    registerSetLiteral(node.typeArgument,
+        isConst: node.isConst, isEmpty: node.expressions.isEmpty);
+  }
 
   @override
   void handleMapLiteral(ir.MapLiteral node) {
     registerMapLiteral(node.keyType, node.valueType,
-        isConstant: node.isConst, isEmpty: node.entries.isEmpty);
+        isConst: node.isConst, isEmpty: node.entries.isEmpty);
   }
 
-  void registerStaticTearOff(
-      ir.Procedure procedure, ir.LibraryDependency import);
-
-  void registerStaticGet(ir.Member member, ir.LibraryDependency import);
-
   @override
   void handleStaticGet(ir.StaticGet node, ir.DartType resultType) {
     ir.Member target = node.target;
@@ -107,35 +260,22 @@
     }
   }
 
-  void registerStaticSet(ir.Member member, ir.LibraryDependency import);
-
   @override
   void handleStaticSet(ir.StaticSet node, ir.DartType valueType) {
     registerStaticSet(node.target, getDeferredImport(node));
   }
 
-  void registerAssert({bool withMessage});
-
   @override
   void handleAssertStatement(ir.AssertStatement node) {
     registerAssert(withMessage: node.message != null);
   }
 
-  void registerGenericInstantiation(
-      ir.FunctionType expressionType, List<ir.DartType> typeArguments);
-
   @override
   void handleInstantiation(ir.Instantiation node,
       ir.FunctionType expressionType, ir.DartType resultType) {
     registerGenericInstantiation(expressionType, node.typeArguments);
   }
 
-  void registerSyncStar(ir.DartType elementType);
-
-  void registerAsync(ir.DartType elementType);
-
-  void registerAsyncStar(ir.DartType elementType);
-
   void handleAsyncMarker(ir.FunctionNode function) {
     ir.AsyncMarker asyncMarker = function.asyncMarker;
     ir.DartType returnType = function.returnType;
@@ -182,15 +322,11 @@
     }
   }
 
-  void registerStringConcatenation();
-
   @override
   void handleStringConcatenation(ir.StringConcatenation node) {
     registerStringConcatenation();
   }
 
-  void registerLocalFunction(ir.TreeNode node);
-
   @override
   Null handleFunctionDeclaration(ir.FunctionDeclaration node) {
     registerLocalFunction(node);
@@ -203,8 +339,6 @@
     handleAsyncMarker(node.function);
   }
 
-  void registerLocalWithoutInitializer();
-
   @override
   void handleVariableDeclaration(ir.VariableDeclaration node) {
     if (node.initializer == null) {
@@ -212,17 +346,11 @@
     }
   }
 
-  void registerIsCheck(ir.DartType type);
-
   @override
   void handleIsExpression(ir.IsExpression node) {
     registerIsCheck(node.type);
   }
 
-  void registerImplicitCast(ir.DartType type);
-
-  void registerAsCast(ir.DartType type);
-
   @override
   void handleAsExpression(ir.AsExpression node, ir.DartType operandType) {
     if (typeEnvironment.isSubtypeOf(operandType, node.type)) {
@@ -236,17 +364,11 @@
     }
   }
 
-  void registerThrow();
-
   @override
   void handleThrow(ir.Throw node) {
     registerThrow();
   }
 
-  void registerSyncForIn(ir.DartType iterableType);
-
-  void registerAsyncForIn(ir.DartType iterableType);
-
   @override
   void handleForInStatement(ir.ForInStatement node, ir.DartType iterableType) {
     if (node.isAsync) {
@@ -256,12 +378,6 @@
     }
   }
 
-  void registerCatch();
-
-  void registerStackTrace();
-
-  void registerCatchType(ir.DartType type);
-
   @override
   void handleCatch(ir.Catch node) {
     registerCatch();
@@ -273,37 +389,30 @@
     }
   }
 
-  void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import);
-
   @override
   void handleTypeLiteral(ir.TypeLiteral node) {
     registerTypeLiteral(node.type, getDeferredImport(node));
   }
 
-  void registerFieldInitializer(ir.Field node);
-
   @override
   void handleFieldInitializer(ir.FieldInitializer node) {
     registerFieldInitializer(node.field);
   }
 
-  void registerLoadLibrary();
-
   @override
   void handleLoadLibrary(ir.LoadLibrary node) {
     registerLoadLibrary();
   }
 
-  void registerRedirectingInitializer(
-      ir.Constructor constructor, ir.Arguments arguments);
-
   void handleRedirectingInitializer(
       ir.RedirectingInitializer node, ArgumentTypes argumentTypes) {
-    registerRedirectingInitializer(node.target, node.arguments);
+    registerRedirectingInitializer(
+        node.target,
+        node.arguments.positional.length,
+        _getNamedArguments(node.arguments),
+        node.arguments.types);
   }
 
-  void registerParameterCheck(ir.DartType type);
-
   @override
   void handleParameter(ir.VariableDeclaration parameter) {
     registerParameterCheck(parameter.type);
@@ -316,7 +425,10 @@
     }
   }
 
-  void registerLazyField();
+  @override
+  void handleConstructor(ir.Constructor node) {
+    registerConstructorNode(node);
+  }
 
   @override
   void handleField(ir.Field field) {
@@ -330,31 +442,37 @@
     } else {
       registerNullLiteral();
     }
+    registerFieldNode(field);
   }
 
   @override
   void handleProcedure(ir.Procedure procedure) {
     handleAsyncMarker(procedure.function);
+    registerProcedureNode(procedure);
   }
 
-  void registerNew(ir.Member constructor, ir.InterfaceType type,
-      ir.Arguments arguments, ir.LibraryDependency import,
-      {bool isConst});
-
   @override
   void handleConstructorInvocation(ir.ConstructorInvocation node,
       ArgumentTypes argumentTypes, ir.DartType resultType) {
-    registerNew(node.target, node.constructedType, node.arguments,
+    registerNew(
+        node.target,
+        node.constructedType,
+        node.arguments.positional.length,
+        _getNamedArguments(node.arguments),
+        node.arguments.types,
         getDeferredImport(node),
         isConst: node.isConst);
+    if (node.isConst) {
+      registerConstConstructorInvocationNode(node);
+    }
   }
 
-  void registerStaticInvocation(
-      ir.Procedure target, ir.Arguments arguments, ir.LibraryDependency import);
-
   @override
   void handleStaticInvocation(ir.StaticInvocation node,
       ArgumentTypes argumentTypes, ir.DartType returnType) {
+    int positionArguments = node.arguments.positional.length;
+    List<String> namedArguments = _getNamedArguments(node.arguments);
+    List<ir.DartType> typeArguments = node.arguments.types;
     if (node.target.kind == ir.ProcedureKind.Factory) {
       // TODO(johnniwinther): We should not mark the type as instantiated but
       // rather follow the type arguments directly.
@@ -380,65 +498,60 @@
       // instantiated as int and String.
       registerNew(
           node.target,
-          new ir.InterfaceType(
-              node.target.enclosingClass, node.arguments.types),
-          node.arguments,
+          new ir.InterfaceType(node.target.enclosingClass, typeArguments),
+          positionArguments,
+          namedArguments,
+          node.arguments.types,
           getDeferredImport(node),
           isConst: node.isConst);
     } else {
-      registerStaticInvocation(
-          node.target, node.arguments, getDeferredImport(node));
+      registerStaticInvocation(node.target, positionArguments, namedArguments,
+          typeArguments, getDeferredImport(node));
     }
+    registerStaticInvocationNode(node);
   }
 
-  void registerLocalFunctionInvocation(
-      ir.FunctionDeclaration localFunction, ir.Arguments arguments);
-
-  void registerDynamicInvocation(ir.DartType receiverType,
-      ClassRelation relation, ir.Name name, ir.Arguments arguments);
-
-  void registerInstanceInvocation(ir.DartType receiverType,
-      ClassRelation relation, ir.Member target, ir.Arguments arguments);
-
-  void registerFunctionInvocation(
-      ir.DartType receiverType, ir.Arguments arguments);
-
   @override
   void handleMethodInvocation(
       ir.MethodInvocation node,
       ir.DartType receiverType,
       ArgumentTypes argumentTypes,
       ir.DartType returnType) {
+    int positionArguments = node.arguments.positional.length;
+    List<String> namedArguments = _getNamedArguments(node.arguments);
+    List<ir.DartType> typeArguments = node.arguments.types;
     ir.Expression receiver = node.receiver;
     if (receiver is ir.VariableGet &&
         receiver.variable.isFinal &&
         receiver.variable.parent is ir.FunctionDeclaration) {
-      registerLocalFunctionInvocation(receiver.variable.parent, node.arguments);
+      registerLocalFunctionInvocation(receiver.variable.parent,
+          positionArguments, namedArguments, typeArguments);
     } else {
       ClassRelation relation = _computeClassRelationFromType(receiverType);
 
       ir.Member interfaceTarget = node.interfaceTarget;
       if (interfaceTarget == null) {
-        registerDynamicInvocation(
-            receiverType, relation, node.name, node.arguments);
+        registerDynamicInvocation(receiverType, relation, node.name,
+            positionArguments, namedArguments, typeArguments);
         // TODO(johnniwinther): Avoid treating a known function call as a
         // dynamic call when CFE provides a way to distinguish the two.
         if (operatorFromString(node.name.name) == null &&
             receiverType is ir.DynamicType) {
           // We might implicitly call a getter that returns a function.
-          registerFunctionInvocation(const ir.DynamicType(), node.arguments);
+          registerFunctionInvocation(const ir.DynamicType(), positionArguments,
+              namedArguments, typeArguments);
         }
       } else {
         if (interfaceTarget is ir.Field ||
             interfaceTarget is ir.Procedure &&
                 interfaceTarget.kind == ir.ProcedureKind.Getter) {
-          registerInstanceInvocation(
-              receiverType, relation, interfaceTarget, node.arguments);
-          registerFunctionInvocation(
-              interfaceTarget.getterType, node.arguments);
+          registerInstanceInvocation(receiverType, relation, interfaceTarget,
+              positionArguments, namedArguments, typeArguments);
+          registerFunctionInvocation(interfaceTarget.getterType,
+              positionArguments, namedArguments, typeArguments);
         } else {
-          registerInstanceInvocation(
-              receiverType, relation, interfaceTarget, node.arguments);
+          registerInstanceInvocation(receiverType, relation, interfaceTarget,
+              positionArguments, namedArguments, typeArguments);
         }
       }
     }
@@ -451,15 +564,14 @@
       ArgumentTypes argumentTypes,
       ir.DartType returnType) {
     registerInstanceInvocation(
-        receiverType, ClassRelation.exact, node.target, node.arguments);
+        receiverType,
+        ClassRelation.exact,
+        node.target,
+        node.arguments.positional.length,
+        _getNamedArguments(node.arguments),
+        node.arguments.types);
   }
 
-  void registerDynamicGet(
-      ir.DartType receiverType, ClassRelation relation, ir.Name name);
-
-  void registerInstanceGet(
-      ir.DartType receiverType, ClassRelation relation, ir.Member target);
-
   @override
   void handlePropertyGet(
       ir.PropertyGet node, ir.DartType receiverType, ir.DartType resultType) {
@@ -477,12 +589,6 @@
     registerInstanceGet(receiverType, ClassRelation.exact, node.target);
   }
 
-  void registerDynamicSet(
-      ir.DartType receiverType, ClassRelation relation, ir.Name name);
-
-  void registerInstanceSet(
-      ir.DartType receiverType, ClassRelation relation, ir.Member target);
-
   @override
   void handlePropertySet(
       ir.PropertySet node, ir.DartType receiverType, ir.DartType valueType) {
@@ -500,35 +606,59 @@
     registerInstanceSet(receiverType, ClassRelation.exact, node.target);
   }
 
-  void registerSuperInvocation(ir.Name name, ir.Arguments arguments);
-
   @override
   void handleSuperMethodInvocation(ir.SuperMethodInvocation node,
       ArgumentTypes argumentTypes, ir.DartType returnType) {
-    registerSuperInvocation(node.name, node.arguments);
+    registerSuperInvocation(node.name, node.arguments.positional.length,
+        _getNamedArguments(node.arguments), node.arguments.types);
   }
 
-  void registerSuperGet(ir.Name name);
-
   @override
   void handleSuperPropertyGet(
       ir.SuperPropertyGet node, ir.DartType resultType) {
     registerSuperGet(node.name);
   }
 
-  void registerSuperSet(ir.Name name);
-
   @override
   void handleSuperPropertySet(ir.SuperPropertySet node, ir.DartType valueType) {
     registerSuperSet(node.name);
   }
 
-  void registerSuperInitializer(
-      ir.Constructor source, ir.Constructor target, ir.Arguments arguments);
-
   @override
   void handleSuperInitializer(
       ir.SuperInitializer node, ArgumentTypes argumentTypes) {
-    registerSuperInitializer(node.parent, node.target, node.arguments);
+    registerSuperInitializer(
+        node.parent,
+        node.target,
+        node.arguments.positional.length,
+        _getNamedArguments(node.arguments),
+        node.arguments.types);
+  }
+
+  @override
+  Null visitSwitchStatement(ir.SwitchStatement node) {
+    registerSwitchStatementNode(node);
+    return super.visitSwitchStatement(node);
+  }
+
+  void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+      ir.DartType receiverType, ir.DartType argumentType) {
+    registerRuntimeTypeUse(node, kind, receiverType, argumentType);
   }
 }
+
+/// Visitor that builds an [ImpactData] object for the world impact.
+class ImpactBuilder extends ImpactBuilderBase with ImpactRegistryMixin {
+  final bool useAsserts;
+
+  final inferEffectivelyFinalVariableTypes;
+
+  ImpactBuilder(ir.TypeEnvironment typeEnvironment,
+      ir.ClassHierarchy classHierarchy, VariableScopeModel variableScopeModel,
+      {this.useAsserts: false, this.inferEffectivelyFinalVariableTypes: true})
+      : super(typeEnvironment, classHierarchy, variableScopeModel);
+}
+
+/// Return the named arguments names as a list of strings.
+List<String> _getNamedArguments(ir.Arguments arguments) =>
+    arguments.named.map((n) => n.name).toList();
diff --git a/pkg/compiler/lib/src/ir/impact_data.dart b/pkg/compiler/lib/src/ir/impact_data.dart
new file mode 100644
index 0000000..20bd480
--- /dev/null
+++ b/pkg/compiler/lib/src/ir/impact_data.dart
@@ -0,0 +1,1545 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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/type_environment.dart' as ir;
+
+import '../serialization/serialization.dart';
+import '../util/enumset.dart';
+import 'impact.dart';
+import 'runtime_type_analysis.dart';
+import 'static_type.dart';
+
+/// [ImpactRegistry] that stores registered impact in an [ImpactData] object.
+abstract class ImpactRegistryMixin implements ImpactRegistry {
+  final ImpactDataImpl _data = new ImpactDataImpl();
+
+  ImpactData get impactData => _data;
+
+  void _registerFeature(_Feature feature) {
+    _data._features ??= new EnumSet<_Feature>();
+    _data._features.add(feature);
+  }
+
+  void _registerTypeUse(ir.DartType type, _TypeUseKind kind) {
+    _data._typeUses ??= [];
+    _data._typeUses.add(new _TypeUse(type, kind));
+  }
+
+  @override
+  void registerSuperInitializer(
+      ir.Constructor source,
+      ir.Constructor target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._superInitializers ??= [];
+    _data._superInitializers.add(new _SuperInitializer(
+        source,
+        target,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerSuperSet(ir.Name name) {
+    _data._superSets ??= [];
+    _data._superSets.add(name);
+  }
+
+  @override
+  void registerSuperGet(ir.Name name) {
+    _data._superGets ??= [];
+    _data._superGets.add(name);
+  }
+
+  @override
+  void registerSuperInvocation(ir.Name name, int positionalArguments,
+      List<String> namedArguments, List<ir.DartType> typeArguments) {
+    _data._superInvocations ??= [];
+    _data._superInvocations.add(new _SuperInvocation(
+        name,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerInstanceSet(
+      ir.DartType receiverType, ClassRelation relation, ir.Member target) {
+    _data._instanceSets ??= [];
+    _data._instanceSets
+        .add(new _InstanceAccess(receiverType, relation, target));
+  }
+
+  @override
+  void registerDynamicSet(
+      ir.DartType receiverType, ClassRelation relation, ir.Name name) {
+    _data._dynamicSets ??= [];
+    _data._dynamicSets.add(new _DynamicAccess(receiverType, relation, name));
+  }
+
+  @override
+  void registerInstanceGet(
+      ir.DartType receiverType, ClassRelation relation, ir.Member target) {
+    _data._instanceGets ??= [];
+    _data._instanceGets
+        .add(new _InstanceAccess(receiverType, relation, target));
+  }
+
+  @override
+  void registerDynamicGet(
+      ir.DartType receiverType, ClassRelation relation, ir.Name name) {
+    _data._dynamicGets ??= [];
+    _data._dynamicGets.add(new _DynamicAccess(receiverType, relation, name));
+  }
+
+  @override
+  void registerFunctionInvocation(
+      ir.DartType receiverType,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._functionInvocations ??= [];
+    _data._functionInvocations.add(new _FunctionInvocation(
+        receiverType,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerInstanceInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Member target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._instanceInvocations ??= [];
+    _data._instanceInvocations.add(new _InstanceInvocation(
+        receiverType,
+        relation,
+        target,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerDynamicInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Name name,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._dynamicInvocations ??= [];
+    _data._dynamicInvocations.add(new _DynamicInvocation(
+        receiverType,
+        relation,
+        name,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerLocalFunctionInvocation(
+      ir.FunctionDeclaration localFunction,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._localFunctionInvocations ??= [];
+    _data._localFunctionInvocations.add(new _LocalFunctionInvocation(
+        localFunction,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerStaticInvocation(
+      ir.Procedure target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
+      ir.LibraryDependency import) {
+    _data._staticInvocations ??= [];
+    _data._staticInvocations.add(new _StaticInvocation(
+        target,
+        new _CallStructure(positionalArguments, namedArguments, typeArguments),
+        import));
+  }
+
+  @override
+  void registerNew(
+      ir.Member constructor,
+      ir.InterfaceType type,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
+      ir.LibraryDependency import,
+      {bool isConst}) {
+    _data._constructorInvocations ??= [];
+    _data._constructorInvocations.add(new _ConstructorInvocation(
+        constructor,
+        type,
+        new _CallStructure(positionalArguments, namedArguments, typeArguments),
+        import,
+        isConst: isConst));
+  }
+
+  @override
+  void registerLazyField() {
+    _registerFeature(_Feature.lazyField);
+  }
+
+  @override
+  void registerParameterCheck(ir.DartType type) {
+    _registerTypeUse(type, _TypeUseKind.parameterCheck);
+  }
+
+  @override
+  void registerRedirectingInitializer(
+      ir.Constructor constructor,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    _data._redirectingInitializers ??= [];
+    _data._redirectingInitializers.add(new _RedirectingInitializer(
+        constructor,
+        new _CallStructure(
+            positionalArguments, namedArguments, typeArguments)));
+  }
+
+  @override
+  void registerLoadLibrary() {
+    _registerFeature(_Feature.loadLibrary);
+  }
+
+  @override
+  void registerFieldInitializer(ir.Field node) {
+    _data._fieldInitializers ??= [];
+    _data._fieldInitializers.add(node);
+  }
+
+  @override
+  void registerTypeLiteral(ir.DartType type, ir.LibraryDependency import) {
+    _data._typeLiterals ??= [];
+    _data._typeLiterals.add(new _TypeLiteral(type, import));
+  }
+
+  @override
+  void registerCatchType(ir.DartType type) {
+    _registerTypeUse(type, _TypeUseKind.catchType);
+  }
+
+  @override
+  void registerStackTrace() {
+    _registerFeature(_Feature.stackTrace);
+  }
+
+  @override
+  void registerCatch() {
+    _registerFeature(_Feature.catchClause);
+  }
+
+  @override
+  void registerAsyncForIn(ir.DartType iterableType) {
+    _registerTypeUse(iterableType, _TypeUseKind.asyncForIn);
+  }
+
+  @override
+  void registerSyncForIn(ir.DartType iterableType) {
+    _registerTypeUse(iterableType, _TypeUseKind.syncForIn);
+  }
+
+  @override
+  void registerThrow() {
+    _registerFeature(_Feature.throwExpression);
+  }
+
+  @override
+  void registerAsCast(ir.DartType type) {
+    _registerTypeUse(type, _TypeUseKind.asCast);
+  }
+
+  @override
+  void registerImplicitCast(ir.DartType type) {
+    _registerTypeUse(type, _TypeUseKind.implicitCast);
+  }
+
+  @override
+  void registerIsCheck(ir.DartType type) {
+    _registerTypeUse(type, _TypeUseKind.isCheck);
+  }
+
+  @override
+  void registerLocalWithoutInitializer() {
+    _registerFeature(_Feature.localWithoutInitializer);
+  }
+
+  @override
+  void registerLocalFunction(ir.TreeNode node) {
+    _data._localFunctions ??= [];
+    _data._localFunctions.add(node);
+  }
+
+  @override
+  void registerStringConcatenation() {
+    _registerFeature(_Feature.stringConcatenation);
+  }
+
+  @override
+  void registerAsyncStar(ir.DartType elementType) {
+    _registerTypeUse(elementType, _TypeUseKind.asyncStarMarker);
+  }
+
+  @override
+  void registerAsync(ir.DartType elementType) {
+    _registerTypeUse(elementType, _TypeUseKind.asyncMarker);
+  }
+
+  @override
+  void registerSyncStar(ir.DartType elementType) {
+    _registerTypeUse(elementType, _TypeUseKind.syncStarMarker);
+  }
+
+  @override
+  void registerGenericInstantiation(
+      ir.FunctionType expressionType, List<ir.DartType> typeArguments) {
+    _data._genericInstantiations ??= [];
+    _data._genericInstantiations
+        .add(new _GenericInstantiation(expressionType, typeArguments));
+  }
+
+  @override
+  void registerAssert({bool withMessage}) {
+    _registerFeature(withMessage
+        ? _Feature.assertWithMessage
+        : _Feature.assertWithoutMessage);
+  }
+
+  @override
+  void registerStaticSet(ir.Member member, ir.LibraryDependency import) {
+    _data._staticSets ??= [];
+    _data._staticSets.add(new _StaticAccess(member, import));
+  }
+
+  @override
+  void registerStaticGet(ir.Member member, ir.LibraryDependency import) {
+    _data._staticGets ??= [];
+    _data._staticGets.add(new _StaticAccess(member, import));
+  }
+
+  @override
+  void registerStaticTearOff(
+      ir.Procedure procedure, ir.LibraryDependency import) {
+    _data._staticTearOffs ??= [];
+    _data._staticTearOffs.add(new _StaticAccess(procedure, import));
+  }
+
+  @override
+  void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
+      {bool isConst, bool isEmpty}) {
+    _data._mapLiterals ??= [];
+    _data._mapLiterals.add(new _MapLiteral(keyType, valueType,
+        isConst: isConst, isEmpty: isEmpty));
+  }
+
+  @override
+  void registerListLiteral(ir.DartType elementType,
+      {bool isConst, bool isEmpty}) {
+    _data._listLiterals ??= [];
+    _data._listLiterals.add(
+        new _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty));
+  }
+
+  @override
+  void registerSetLiteral(ir.DartType elementType,
+      {bool isConst, bool isEmpty}) {
+    _data._setLiterals ??= [];
+    _data._setLiterals.add(
+        new _ContainerLiteral(elementType, isConst: isConst, isEmpty: isEmpty));
+  }
+
+  @override
+  void registerNullLiteral() {
+    _registerFeature(_Feature.nullLiteral);
+  }
+
+  @override
+  void registerSymbolLiteral(String value) {
+    _data._symbolLiterals ??= [];
+    _data._symbolLiterals.add(value);
+  }
+
+  @override
+  void registerStringLiteral(String value) {
+    _data._stringLiterals ??= [];
+    _data._stringLiterals.add(value);
+  }
+
+  @override
+  void registerBoolLiteral(bool value) {
+    _data._boolLiterals ??= [];
+    _data._boolLiterals.add(value);
+  }
+
+  @override
+  void registerDoubleLiteral(double value) {
+    _data._doubleLiterals ??= [];
+    _data._doubleLiterals.add(value);
+  }
+
+  @override
+  void registerIntLiteral(int value) {
+    _data._intLiterals ??= [];
+    _data._intLiterals.add(value);
+  }
+
+  @override
+  void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+      ir.DartType receiverType, ir.DartType argumentType) {
+    _data._runtimeTypeUses ??= [];
+    _data._runtimeTypeUses
+        .add(new _RuntimeTypeUse(node, kind, receiverType, argumentType));
+  }
+
+  @override
+  void registerConstructorNode(ir.Constructor node) {
+    _data._constructorNodes ??= [];
+    _data._constructorNodes.add(node);
+  }
+
+  @override
+  void registerFieldNode(ir.Field node) {
+    _data._fieldNodes ??= [];
+    _data._fieldNodes.add(node);
+  }
+
+  @override
+  void registerProcedureNode(ir.Procedure node) {
+    _data._procedureNodes ??= [];
+    _data._procedureNodes.add(node);
+  }
+
+  @override
+  void registerStaticInvocationNode(ir.StaticInvocation node) {
+    _data._staticInvocationNodes ??= [];
+    _data._staticInvocationNodes.add(node);
+  }
+
+  @override
+  void registerSwitchStatementNode(ir.SwitchStatement node) {
+    _data._switchStatementNodes ??= [];
+    _data._switchStatementNodes.add(node);
+  }
+
+  @override
+  void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
+    _data._constConstructorInvocationNodes ??= [];
+    _data._constConstructorInvocationNodes.add(node);
+  }
+}
+
+/// Data object that contains the world impact data derived purely from kernel.
+abstract class ImpactData {
+  factory ImpactData.fromDataSource(DataSource source) =
+      ImpactDataImpl.fromDataSource;
+
+  void toDataSink(DataSink sink);
+
+  /// Registers the impact data with [registry].
+  void apply(ImpactRegistry registry);
+}
+
+class ImpactDataImpl implements ImpactData {
+  static const String tag = 'ImpactData';
+
+  List<_SuperInitializer> _superInitializers;
+  List<ir.Name> _superSets;
+  List<ir.Name> _superGets;
+  List<_SuperInvocation> _superInvocations;
+  List<_InstanceAccess> _instanceSets;
+  List<_DynamicAccess> _dynamicSets;
+  List<_InstanceAccess> _instanceGets;
+  List<_DynamicAccess> _dynamicGets;
+  List<_FunctionInvocation> _functionInvocations;
+  List<_InstanceInvocation> _instanceInvocations;
+  List<_DynamicInvocation> _dynamicInvocations;
+  List<_LocalFunctionInvocation> _localFunctionInvocations;
+  List<_StaticInvocation> _staticInvocations;
+  List<_ConstructorInvocation> _constructorInvocations;
+  EnumSet<_Feature> _features;
+  List<_TypeUse> _typeUses;
+  List<_RedirectingInitializer> _redirectingInitializers;
+  List<ir.Field> _fieldInitializers;
+  List<_TypeLiteral> _typeLiterals;
+  List<ir.TreeNode> _localFunctions;
+  List<_GenericInstantiation> _genericInstantiations;
+  List<_StaticAccess> _staticSets;
+  List<_StaticAccess> _staticGets;
+  List<_StaticAccess> _staticTearOffs;
+  List<_MapLiteral> _mapLiterals;
+  List<_ContainerLiteral> _listLiterals;
+  List<_ContainerLiteral> _setLiterals;
+  List<String> _symbolLiterals;
+  List<String> _stringLiterals;
+  List<bool> _boolLiterals;
+  List<double> _doubleLiterals;
+  List<int> _intLiterals;
+  List<_RuntimeTypeUse> _runtimeTypeUses;
+
+  // TODO(johnniwinther): Remove these when CFE provides constants.
+  List<ir.Constructor> _constructorNodes;
+  List<ir.Field> _fieldNodes;
+  List<ir.Procedure> _procedureNodes;
+  List<ir.SwitchStatement> _switchStatementNodes;
+  List<ir.StaticInvocation> _staticInvocationNodes;
+  List<ir.ConstructorInvocation> _constConstructorInvocationNodes;
+
+  ImpactDataImpl();
+
+  ImpactDataImpl.fromDataSource(DataSource source) {
+    source.begin(tag);
+    _superInitializers = source.readList(
+        () => new _SuperInitializer.fromDataSource(source),
+        emptyAsNull: true);
+    _superSets = source.readList(() => source.readName(), emptyAsNull: true);
+    _superGets = source.readList(() => source.readName(), emptyAsNull: true);
+    _superInvocations = source.readList(
+        () => new _SuperInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _instanceSets = source.readList(
+        () => new _InstanceAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _dynamicSets = source.readList(
+        () => new _DynamicAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _instanceGets = source.readList(
+        () => new _InstanceAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _dynamicGets = source.readList(
+        () => new _DynamicAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _functionInvocations = source.readList(
+        () => new _FunctionInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _instanceInvocations = source.readList(
+        () => new _InstanceInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _dynamicInvocations = source.readList(
+        () => new _DynamicInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _localFunctionInvocations = source.readList(
+        () => new _LocalFunctionInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _staticInvocations = source.readList(
+        () => new _StaticInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _constructorInvocations = source.readList(
+        () => new _ConstructorInvocation.fromDataSource(source),
+        emptyAsNull: true);
+    _features = new EnumSet<_Feature>.fromValue(source.readInt());
+    _typeUses = source.readList(() => new _TypeUse.fromDataSource(source),
+        emptyAsNull: true);
+    _redirectingInitializers = source.readList(
+        () => new _RedirectingInitializer.fromDataSource(source),
+        emptyAsNull: true);
+    _fieldInitializers = source.readMemberNodes(emptyAsNull: true);
+    _typeLiterals = source.readList(
+        () => new _TypeLiteral.fromDataSource(source),
+        emptyAsNull: true);
+    _localFunctions = source.readTreeNodes(emptyAsNull: true);
+    _genericInstantiations = source.readList(
+        () => new _GenericInstantiation.fromDataSource(source),
+        emptyAsNull: true);
+    _staticSets = source.readList(
+        () => new _StaticAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _staticGets = source.readList(
+        () => new _StaticAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _staticTearOffs = source.readList(
+        () => new _StaticAccess.fromDataSource(source),
+        emptyAsNull: true);
+    _mapLiterals = source.readList(() => new _MapLiteral.fromDataSource(source),
+        emptyAsNull: true);
+    _listLiterals = source.readList(
+        () => new _ContainerLiteral.fromDataSource(source),
+        emptyAsNull: true);
+    _setLiterals = source.readList(
+        () => new _ContainerLiteral.fromDataSource(source),
+        emptyAsNull: true);
+    _symbolLiterals = source.readStrings(emptyAsNull: true);
+    _stringLiterals = source.readStrings(emptyAsNull: true);
+    _boolLiterals = source.readList(() => source.readBool(), emptyAsNull: true);
+    _doubleLiterals =
+        source.readList(() => source.readDoubleValue(), emptyAsNull: true);
+    _intLiterals =
+        source.readList(() => source.readIntegerValue(), emptyAsNull: true);
+    _runtimeTypeUses = source.readList(
+        () => new _RuntimeTypeUse.fromDataSource(source),
+        emptyAsNull: true);
+
+    // TODO(johnniwinther): Remove these when CFE provides constants.
+    _constructorNodes =
+        source.readMemberNodes<ir.Constructor>(emptyAsNull: true);
+    _fieldNodes = source.readMemberNodes<ir.Field>(emptyAsNull: true);
+    _procedureNodes = source.readMemberNodes<ir.Procedure>(emptyAsNull: true);
+    _switchStatementNodes =
+        source.readTreeNodes<ir.SwitchStatement>(emptyAsNull: true);
+    _staticInvocationNodes =
+        source.readTreeNodes<ir.StaticInvocation>(emptyAsNull: true);
+    _constConstructorInvocationNodes =
+        source.readTreeNodes<ir.ConstructorInvocation>(emptyAsNull: true);
+    source.end(tag);
+  }
+
+  @override
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+
+    sink.writeList(
+        _superInitializers, (_SuperInitializer o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_superSets, sink.writeName, allowNull: true);
+    sink.writeList(_superGets, sink.writeName, allowNull: true);
+    sink.writeList(
+        _superInvocations, (_SuperInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_instanceSets, (_InstanceAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_dynamicSets, (_DynamicAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_instanceGets, (_InstanceAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_dynamicGets, (_DynamicAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(
+        _functionInvocations, (_FunctionInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(
+        _instanceInvocations, (_InstanceInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(
+        _dynamicInvocations, (_DynamicInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_localFunctionInvocations,
+        (_LocalFunctionInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(
+        _staticInvocations, (_StaticInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_constructorInvocations,
+        (_ConstructorInvocation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeInt(_features?.value ?? 0);
+    sink.writeList(_typeUses, (_TypeUse o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_redirectingInitializers,
+        (_RedirectingInitializer o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeMemberNodes(_fieldInitializers, allowNull: true);
+    sink.writeList(_typeLiterals, (_TypeLiteral o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeTreeNodes(_localFunctions, allowNull: true);
+    sink.writeList(
+        _genericInstantiations, (_GenericInstantiation o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_staticSets, (_StaticAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_staticGets, (_StaticAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_staticTearOffs, (_StaticAccess o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_mapLiterals, (_MapLiteral o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_listLiterals, (_ContainerLiteral o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeList(_setLiterals, (_ContainerLiteral o) => o.toDataSink(sink),
+        allowNull: true);
+    sink.writeStrings(_symbolLiterals, allowNull: true);
+    sink.writeStrings(_stringLiterals, allowNull: true);
+    sink.writeList(_boolLiterals, sink.writeBool, allowNull: true);
+    sink.writeList(_doubleLiterals, sink.writeDoubleValue, allowNull: true);
+    sink.writeList(_intLiterals, sink.writeIntegerValue, allowNull: true);
+    sink.writeList(_runtimeTypeUses, (_RuntimeTypeUse o) => o.toDataSink(sink),
+        allowNull: true);
+
+    // TODO(johnniwinther): Remove these when CFE provides constants.
+    sink.writeMemberNodes(_constructorNodes, allowNull: true);
+    sink.writeMemberNodes(_fieldNodes, allowNull: true);
+    sink.writeMemberNodes(_procedureNodes, allowNull: true);
+    sink.writeTreeNodes(_switchStatementNodes, allowNull: true);
+    sink.writeTreeNodes(_staticInvocationNodes, allowNull: true);
+    sink.writeTreeNodes(_constConstructorInvocationNodes, allowNull: true);
+
+    sink.end(tag);
+  }
+
+  @override
+  void apply(ImpactRegistry registry) {
+    if (_superInitializers != null) {
+      for (_SuperInitializer data in _superInitializers) {
+        registry.registerSuperInitializer(
+            data.source,
+            data.target,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_superSets != null) {
+      for (ir.Name data in _superSets) {
+        registry.registerSuperSet(data);
+      }
+    }
+    if (_superGets != null) {
+      for (ir.Name data in _superGets) {
+        registry.registerSuperGet(data);
+      }
+    }
+    if (_superInvocations != null) {
+      for (_SuperInvocation data in _superInvocations) {
+        registry.registerSuperInvocation(
+            data.name,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_instanceSets != null) {
+      for (_InstanceAccess data in _instanceSets) {
+        registry.registerInstanceSet(
+            data.receiverType, data.classRelation, data.target);
+      }
+    }
+    if (_dynamicSets != null) {
+      for (_DynamicAccess data in _dynamicSets) {
+        registry.registerDynamicSet(
+            data.receiverType, data.classRelation, data.name);
+      }
+    }
+    if (_instanceGets != null) {
+      for (_InstanceAccess data in _instanceGets) {
+        registry.registerInstanceGet(
+            data.receiverType, data.classRelation, data.target);
+      }
+    }
+    if (_dynamicGets != null) {
+      for (_DynamicAccess data in _dynamicGets) {
+        registry.registerDynamicGet(
+            data.receiverType, data.classRelation, data.name);
+      }
+    }
+    if (_functionInvocations != null) {
+      for (_FunctionInvocation data in _functionInvocations) {
+        registry.registerFunctionInvocation(
+            data.receiverType,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_instanceInvocations != null) {
+      for (_InstanceInvocation data in _instanceInvocations) {
+        registry.registerInstanceInvocation(
+            data.receiverType,
+            data.classRelation,
+            data.target,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_dynamicInvocations != null) {
+      for (_DynamicInvocation data in _dynamicInvocations) {
+        registry.registerDynamicInvocation(
+            data.receiverType,
+            data.classRelation,
+            data.name,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_localFunctionInvocations != null) {
+      for (_LocalFunctionInvocation data in _localFunctionInvocations) {
+        registry.registerLocalFunctionInvocation(
+            data.localFunction,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_staticInvocations != null) {
+      for (_StaticInvocation data in _staticInvocations) {
+        registry.registerStaticInvocation(
+            data.target,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments,
+            data.import);
+        ;
+      }
+    }
+    if (_constructorInvocations != null) {
+      for (_ConstructorInvocation data in _constructorInvocations) {
+        registry.registerNew(
+            data.constructor,
+            data.type,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments,
+            data.import,
+            isConst: data.isConst);
+      }
+    }
+    if (_features != null) {
+      for (_Feature data in _features.iterable(_Feature.values)) {
+        switch (data) {
+          case _Feature.lazyField:
+            registry.registerLazyField();
+            break;
+          case _Feature.loadLibrary:
+            registry.registerLoadLibrary();
+            break;
+          case _Feature.stackTrace:
+            registry.registerStackTrace();
+            break;
+          case _Feature.catchClause:
+            registry.registerCatch();
+            break;
+          case _Feature.throwExpression:
+            registry.registerThrow();
+            break;
+          case _Feature.localWithoutInitializer:
+            registry.registerLocalWithoutInitializer();
+            break;
+          case _Feature.stringConcatenation:
+            registry.registerStringConcatenation();
+            break;
+          case _Feature.assertWithMessage:
+            registry.registerAssert(withMessage: true);
+            break;
+          case _Feature.assertWithoutMessage:
+            registry.registerAssert(withMessage: false);
+            break;
+          case _Feature.nullLiteral:
+            registry.registerNullLiteral();
+            break;
+        }
+      }
+    }
+    if (_typeUses != null) {
+      for (_TypeUse data in _typeUses) {
+        switch (data.kind) {
+          case _TypeUseKind.parameterCheck:
+            registry.registerParameterCheck(data.type);
+            break;
+          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;
+          case _TypeUseKind.implicitCast:
+            registry.registerImplicitCast(data.type);
+            break;
+          case _TypeUseKind.isCheck:
+            registry.registerIsCheck(data.type);
+            break;
+          case _TypeUseKind.asyncStarMarker:
+            registry.registerAsyncStar(data.type);
+            break;
+          case _TypeUseKind.asyncMarker:
+            registry.registerAsync(data.type);
+            break;
+          case _TypeUseKind.syncStarMarker:
+            registry.registerSyncStar(data.type);
+            break;
+        }
+      }
+    }
+    if (_redirectingInitializers != null) {
+      for (_RedirectingInitializer data in _redirectingInitializers) {
+        registry.registerRedirectingInitializer(
+            data.constructor,
+            data.callStructure.positionalArguments,
+            data.callStructure.namedArguments,
+            data.callStructure.typeArguments);
+      }
+    }
+    if (_fieldInitializers != null) {
+      for (ir.Field data in _fieldInitializers) {
+        registry.registerFieldInitializer(data);
+      }
+    }
+    if (_typeLiterals != null) {
+      for (_TypeLiteral data in _typeLiterals) {
+        registry.registerTypeLiteral(data.type, data.import);
+      }
+    }
+    if (_localFunctions != null) {
+      for (ir.TreeNode data in _localFunctions) {
+        registry.registerLocalFunction(data);
+      }
+    }
+    if (_genericInstantiations != null) {
+      for (_GenericInstantiation data in _genericInstantiations) {
+        registry.registerGenericInstantiation(
+            data.expressionType, data.typeArguments);
+      }
+    }
+    if (_staticSets != null) {
+      for (_StaticAccess data in _staticSets) {
+        registry.registerStaticSet(data.target, data.import);
+      }
+    }
+    if (_staticGets != null) {
+      for (_StaticAccess data in _staticGets) {
+        registry.registerStaticGet(data.target, data.import);
+      }
+    }
+    if (_staticTearOffs != null) {
+      for (_StaticAccess data in _staticTearOffs) {
+        registry.registerStaticTearOff(data.target, data.import);
+      }
+    }
+    if (_mapLiterals != null) {
+      for (_MapLiteral data in _mapLiterals) {
+        registry.registerMapLiteral(data.keyType, data.valueType,
+            isConst: data.isConst, isEmpty: data.isEmpty);
+      }
+    }
+    if (_listLiterals != null) {
+      for (_ContainerLiteral data in _listLiterals) {
+        registry.registerListLiteral(data.elementType,
+            isConst: data.isConst, isEmpty: data.isEmpty);
+      }
+    }
+    if (_setLiterals != null) {
+      for (_ContainerLiteral data in _setLiterals) {
+        registry.registerSetLiteral(data.elementType,
+            isConst: data.isConst, isEmpty: data.isEmpty);
+      }
+    }
+    if (_symbolLiterals != null) {
+      for (String data in _symbolLiterals) {
+        registry.registerSymbolLiteral(data);
+      }
+    }
+    if (_stringLiterals != null) {
+      for (String data in _stringLiterals) {
+        registry.registerStringLiteral(data);
+      }
+    }
+    if (_boolLiterals != null) {
+      for (bool data in _boolLiterals) {
+        registry.registerBoolLiteral(data);
+      }
+    }
+    if (_doubleLiterals != null) {
+      for (double data in _doubleLiterals) {
+        registry.registerDoubleLiteral(data);
+      }
+    }
+    if (_intLiterals != null) {
+      for (int data in _intLiterals) {
+        registry.registerIntLiteral(data);
+      }
+    }
+    if (_runtimeTypeUses != null) {
+      for (_RuntimeTypeUse data in _runtimeTypeUses) {
+        registry.registerRuntimeTypeUse(
+            data.node, data.kind, data.receiverType, data.argumentType);
+      }
+    }
+
+    // TODO(johnniwinther): Remove these when CFE provides constants.
+    if (_constructorNodes != null) {
+      for (ir.Constructor data in _constructorNodes) {
+        registry.registerConstructorNode(data);
+      }
+    }
+    if (_fieldNodes != null) {
+      for (ir.Field data in _fieldNodes) {
+        registry.registerFieldNode(data);
+      }
+    }
+    if (_procedureNodes != null) {
+      for (ir.Procedure data in _procedureNodes) {
+        registry.registerProcedureNode(data);
+      }
+    }
+    if (_switchStatementNodes != null) {
+      for (ir.SwitchStatement data in _switchStatementNodes) {
+        registry.registerSwitchStatementNode(data);
+      }
+    }
+    if (_staticInvocationNodes != null) {
+      for (ir.StaticInvocation data in _staticInvocationNodes) {
+        registry.registerStaticInvocationNode(data);
+      }
+    }
+    if (_constConstructorInvocationNodes != null) {
+      for (ir.ConstructorInvocation data in _constConstructorInvocationNodes) {
+        registry.registerConstConstructorInvocationNode(data);
+      }
+    }
+  }
+}
+
+class _CallStructure {
+  static const String tag = '_CallStructure';
+
+  final List<ir.DartType> typeArguments;
+  final int positionalArguments;
+  final List<String> namedArguments;
+
+  _CallStructure.internal(
+      this.typeArguments, this.positionalArguments, this.namedArguments);
+
+  factory _CallStructure(int positionalArguments, List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    return new _CallStructure.internal(
+        typeArguments, positionalArguments, namedArguments);
+  }
+
+  factory _CallStructure.fromDataSource(DataSource source) {
+    source.begin(tag);
+    List<ir.DartType> typeArguments = source.readDartTypeNodes();
+    int positionalArguments = source.readInt();
+    List<String> namedArguments = source.readStrings();
+    source.end(tag);
+    return new _CallStructure.internal(
+        typeArguments, positionalArguments, namedArguments);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNodes(typeArguments);
+    sink.writeInt(positionalArguments);
+    sink.writeStrings(namedArguments);
+    sink.end(tag);
+  }
+}
+
+class _SuperInitializer {
+  static const String tag = '_SuperInitializer';
+
+  final ir.Constructor source;
+  final ir.Constructor target;
+  final _CallStructure callStructure;
+
+  _SuperInitializer(this.source, this.target, this.callStructure);
+
+  factory _SuperInitializer.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Constructor sourceConstructor = source.readMemberNode();
+    ir.Constructor targetConstructor = source.readMemberNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _SuperInitializer(
+        sourceConstructor, targetConstructor, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeMemberNode(source);
+    sink.writeMemberNode(target);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _SuperInvocation {
+  static const String tag = '_SuperInvocation';
+
+  final ir.Name name;
+  final _CallStructure callStructure;
+
+  _SuperInvocation(this.name, this.callStructure);
+
+  factory _SuperInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Name name = source.readName();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _SuperInvocation(name, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeName(name);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _InstanceAccess {
+  static const String tag = '_InstanceAccess';
+
+  final ir.DartType receiverType;
+  final ClassRelation classRelation;
+  final ir.Member target;
+
+  _InstanceAccess(this.receiverType, this.classRelation, this.target);
+
+  factory _InstanceAccess.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType receiverType = source.readDartTypeNode();
+    ClassRelation classRelation = source.readEnum(ClassRelation.values);
+    ir.Member target = source.readMemberNode();
+    source.end(tag);
+    return new _InstanceAccess(receiverType, classRelation, target);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(receiverType);
+    sink.writeEnum(classRelation);
+    sink.writeMemberNode(target);
+    sink.end(tag);
+  }
+}
+
+class _DynamicAccess {
+  static const String tag = '_DynamicAccess';
+
+  final ir.DartType receiverType;
+  final ClassRelation classRelation;
+  final ir.Name name;
+
+  _DynamicAccess(this.receiverType, this.classRelation, this.name);
+
+  factory _DynamicAccess.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType receiverType = source.readDartTypeNode();
+    ClassRelation classRelation = source.readEnum(ClassRelation.values);
+    ir.Name name = source.readName();
+    source.end(tag);
+    return new _DynamicAccess(receiverType, classRelation, name);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(receiverType);
+    sink.writeEnum(classRelation);
+    sink.writeName(name);
+    sink.end(tag);
+  }
+}
+
+class _FunctionInvocation {
+  static const String tag = '_FunctionInvocation';
+
+  final ir.DartType receiverType;
+  final _CallStructure callStructure;
+
+  _FunctionInvocation(this.receiverType, this.callStructure);
+
+  factory _FunctionInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType receiverType = source.readDartTypeNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _FunctionInvocation(receiverType, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(receiverType);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _InstanceInvocation {
+  static const String tag = '_InstanceInvocation';
+
+  final ir.DartType receiverType;
+  final ClassRelation classRelation;
+  final ir.Member target;
+  final _CallStructure callStructure;
+
+  _InstanceInvocation(
+      this.receiverType, this.classRelation, this.target, this.callStructure);
+
+  factory _InstanceInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType receiverType = source.readDartTypeNode();
+    ClassRelation classRelation = source.readEnum(ClassRelation.values);
+    ir.Member target = source.readMemberNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _InstanceInvocation(
+        receiverType, classRelation, target, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(receiverType);
+    sink.writeEnum(classRelation);
+    sink.writeMemberNode(target);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _DynamicInvocation {
+  static const String tag = '_DynamicInvocation';
+
+  final ir.DartType receiverType;
+  final ClassRelation classRelation;
+  final ir.Name name;
+  final _CallStructure callStructure;
+
+  _DynamicInvocation(
+      this.receiverType, this.classRelation, this.name, this.callStructure);
+
+  factory _DynamicInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType receiverType = source.readDartTypeNode();
+    ClassRelation classRelation = source.readEnum(ClassRelation.values);
+    ir.Name name = source.readName();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _DynamicInvocation(
+        receiverType, classRelation, name, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(receiverType);
+    sink.writeEnum(classRelation);
+    sink.writeName(name);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _LocalFunctionInvocation {
+  static const String tag = '_LocalFunctionInvocation';
+
+  final ir.FunctionDeclaration localFunction;
+  final _CallStructure callStructure;
+
+  _LocalFunctionInvocation(this.localFunction, this.callStructure);
+
+  factory _LocalFunctionInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.FunctionDeclaration localFunction = source.readTreeNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _LocalFunctionInvocation(localFunction, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeTreeNode(localFunction);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _StaticInvocation {
+  static const String tag = '_StaticInvocation';
+
+  final ir.Procedure target;
+  final _CallStructure callStructure;
+  final ir.LibraryDependency import;
+
+  _StaticInvocation(this.target, this.callStructure, this.import);
+
+  factory _StaticInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Procedure target = source.readMemberNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull();
+    source.end(tag);
+    return new _StaticInvocation(target, callStructure, import);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeMemberNode(target);
+    callStructure.toDataSink(sink);
+    sink.writeLibraryDependencyNodeOrNull(import);
+    sink.end(tag);
+  }
+}
+
+class _ConstructorInvocation {
+  static const String tag = '_ConstructorInvocation';
+
+  final ir.Member constructor;
+  final ir.InterfaceType type;
+  final _CallStructure callStructure;
+  final ir.LibraryDependency import;
+  final bool isConst;
+
+  _ConstructorInvocation(
+      this.constructor, this.type, this.callStructure, this.import,
+      {this.isConst});
+
+  factory _ConstructorInvocation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Member constructor = source.readMemberNode();
+    ir.InterfaceType type = source.readDartTypeNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull();
+    bool isConst = source.readBool();
+    source.end(tag);
+    return new _ConstructorInvocation(constructor, type, callStructure, import,
+        isConst: isConst);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeMemberNode(constructor);
+    sink.writeDartTypeNode(type);
+    callStructure.toDataSink(sink);
+    sink.writeLibraryDependencyNodeOrNull(import);
+    sink.writeBool(isConst);
+    sink.end(tag);
+  }
+}
+
+enum _Feature {
+  lazyField,
+  loadLibrary,
+  stackTrace,
+  catchClause,
+  throwExpression,
+  localWithoutInitializer,
+  stringConcatenation,
+  assertWithMessage,
+  assertWithoutMessage,
+  nullLiteral,
+}
+
+class _TypeUse {
+  static const String tag = '_TypeUse';
+
+  final ir.DartType type;
+  final _TypeUseKind kind;
+
+  _TypeUse(this.type, this.kind);
+
+  factory _TypeUse.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType type = source.readDartTypeNode();
+    _TypeUseKind kind = source.readEnum(_TypeUseKind.values);
+    source.end(tag);
+    return new _TypeUse(type, kind);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(type);
+    sink.writeEnum(kind);
+    sink.end(tag);
+  }
+}
+
+enum _TypeUseKind {
+  parameterCheck,
+  catchType,
+  asyncForIn,
+  syncForIn,
+  asCast,
+  implicitCast,
+  isCheck,
+  asyncStarMarker,
+  asyncMarker,
+  syncStarMarker,
+}
+
+class _RedirectingInitializer {
+  static const String tag = '_RedirectingInitializer';
+
+  final ir.Constructor constructor;
+  final _CallStructure callStructure;
+
+  _RedirectingInitializer(this.constructor, this.callStructure);
+
+  factory _RedirectingInitializer.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Constructor constructor = source.readMemberNode();
+    _CallStructure callStructure = new _CallStructure.fromDataSource(source);
+    source.end(tag);
+    return new _RedirectingInitializer(constructor, callStructure);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeMemberNode(constructor);
+    callStructure.toDataSink(sink);
+    sink.end(tag);
+  }
+}
+
+class _TypeLiteral {
+  static const String tag = '_TypeLiteral';
+
+  final ir.DartType type;
+  final ir.LibraryDependency import;
+
+  _TypeLiteral(this.type, this.import);
+
+  factory _TypeLiteral.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType type = source.readDartTypeNode();
+    ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull();
+    source.end(tag);
+    return new _TypeLiteral(type, import);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(type);
+    sink.writeLibraryDependencyNodeOrNull(import);
+    sink.end(tag);
+  }
+}
+
+class _GenericInstantiation {
+  static const String tag = '_GenericInstantiation';
+
+  final ir.FunctionType expressionType;
+  final List<ir.DartType> typeArguments;
+
+  _GenericInstantiation(this.expressionType, this.typeArguments);
+
+  factory _GenericInstantiation.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.FunctionType expressionType = source.readDartTypeNode();
+    List<ir.DartType> typeArguments = source.readDartTypeNodes();
+    source.end(tag);
+    return new _GenericInstantiation(expressionType, typeArguments);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(expressionType);
+    sink.writeDartTypeNodes(typeArguments);
+    sink.end(tag);
+  }
+}
+
+class _StaticAccess {
+  static const String tag = '_StaticAccess';
+
+  final ir.Member target;
+  final ir.LibraryDependency import;
+
+  _StaticAccess(this.target, this.import);
+
+  factory _StaticAccess.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.Member target = source.readMemberNode();
+    ir.LibraryDependency import = source.readLibraryDependencyNodeOrNull();
+    source.end(tag);
+    return new _StaticAccess(target, import);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeMemberNode(target);
+    sink.writeLibraryDependencyNodeOrNull(import);
+    sink.end(tag);
+  }
+}
+
+class _MapLiteral {
+  static const String tag = '_MapLiteral';
+
+  final ir.DartType keyType;
+  final ir.DartType valueType;
+  final bool isConst;
+  final bool isEmpty;
+
+  _MapLiteral(this.keyType, this.valueType, {this.isConst, this.isEmpty});
+
+  factory _MapLiteral.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType keyType = source.readDartTypeNode();
+    ir.DartType valueType = source.readDartTypeNode();
+    bool isConst = source.readBool();
+    bool isEmpty = source.readBool();
+    source.end(tag);
+    return _MapLiteral(keyType, valueType, isConst: isConst, isEmpty: isEmpty);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(keyType);
+    sink.writeDartTypeNode(valueType);
+    sink.writeBool(isConst);
+    sink.writeBool(isEmpty);
+    sink.end(tag);
+  }
+}
+
+class _ContainerLiteral {
+  static const String tag = '_ContainerLiteral';
+
+  final ir.DartType elementType;
+  final bool isConst;
+  final bool isEmpty;
+
+  _ContainerLiteral(this.elementType, {this.isConst, this.isEmpty});
+
+  factory _ContainerLiteral.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.DartType elementType = source.readDartTypeNode();
+    bool isConst = source.readBool();
+    bool isEmpty = source.readBool();
+    return new _ContainerLiteral(elementType,
+        isConst: isConst, isEmpty: isEmpty);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeDartTypeNode(elementType);
+    sink.writeBool(isConst);
+    sink.writeBool(isEmpty);
+    sink.end(tag);
+  }
+}
+
+class _RuntimeTypeUse {
+  static const String tag = '_RuntimeTypeUse';
+
+  final ir.PropertyGet node;
+  final RuntimeTypeUseKind kind;
+  final ir.DartType receiverType;
+  final ir.DartType argumentType;
+
+  _RuntimeTypeUse(this.node, this.kind, this.receiverType, this.argumentType);
+
+  factory _RuntimeTypeUse.fromDataSource(DataSource source) {
+    source.begin(tag);
+    ir.TreeNode node = source.readTreeNode();
+    RuntimeTypeUseKind kind = source.readEnum(RuntimeTypeUseKind.values);
+    ir.DartType receiverType = source.readDartTypeNode();
+    ir.DartType argumentType = source.readDartTypeNode(allowNull: true);
+    return new _RuntimeTypeUse(node, kind, receiverType, argumentType);
+  }
+
+  void toDataSink(DataSink sink) {
+    sink.begin(tag);
+    sink.writeTreeNode(node);
+    sink.writeEnum(kind);
+    sink.writeDartTypeNode(receiverType);
+    sink.writeDartTypeNode(argumentType, allowNull: true);
+    sink.end(tag);
+  }
+}
diff --git a/pkg/compiler/lib/src/ir/static_type.dart b/pkg/compiler/lib/src/ir/static_type.dart
index 9ddc390..8ec8bad 100644
--- a/pkg/compiler/lib/src/ir/static_type.dart
+++ b/pkg/compiler/lib/src/ir/static_type.dart
@@ -903,6 +903,15 @@
     return super.visitListLiteral(node);
   }
 
+  void handleSetLiteral(ir.SetLiteral node) {}
+
+  @override
+  ir.DartType visitSetLiteral(ir.SetLiteral node) {
+    visitNodes(node.expressions);
+    handleSetLiteral(node);
+    return super.visitSetLiteral(node);
+  }
+
   void handleMapLiteral(ir.MapLiteral node) {}
 
   @override
diff --git a/pkg/compiler/lib/src/ir/static_type_base.dart b/pkg/compiler/lib/src/ir/static_type_base.dart
index 20cf00c..5cd8001 100644
--- a/pkg/compiler/lib/src/ir/static_type_base.dart
+++ b/pkg/compiler/lib/src/ir/static_type_base.dart
@@ -129,6 +129,11 @@
   }
 
   @override
+  ir.DartType visitSetLiteral(ir.SetLiteral node) {
+    return typeEnvironment.literalSetType(node.typeArgument);
+  }
+
+  @override
   ir.DartType visitMapLiteral(ir.MapLiteral node) {
     return typeEnvironment.literalMapType(node.keyType, node.valueType);
   }
diff --git a/pkg/compiler/lib/src/ir/util.dart b/pkg/compiler/lib/src/ir/util.dart
index f286702..0a749db 100644
--- a/pkg/compiler/lib/src/ir/util.dart
+++ b/pkg/compiler/lib/src/ir/util.dart
@@ -20,12 +20,17 @@
   return '(${node.runtimeType}:${node.hashCode})${blockText}';
 }
 
-/// Comparator for the canonical order or named arguments.
+/// Comparator for the canonical order or named parameters.
 // TODO(johnniwinther): Remove this when named parameters are sorted in dill.
 int namedOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
   return a.name.compareTo(b.name);
 }
 
+/// Comparator for the declaration order of parameters.
+int nativeOrdering(ir.VariableDeclaration a, ir.VariableDeclaration b) {
+  return a.fileOffset.compareTo(b.fileOffset);
+}
+
 SourceSpan computeSourceSpanFromTreeNode(ir.TreeNode node) {
   // TODO(johnniwinther): Use [ir.Location] directly as a [SourceSpan].
   Uri uri;
diff --git a/pkg/compiler/lib/src/js_backend/allocator_analysis.dart b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
index 787e64c..123f627 100644
--- a/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
+++ b/pkg/compiler/lib/src/js_backend/allocator_analysis.dart
@@ -5,7 +5,8 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../constants/values.dart';
-import '../js_model/elements.dart' show JsToFrontendMap, JField;
+import '../js_model/elements.dart' show JField;
+import '../js_model/js_world_builder.dart';
 import '../kernel/element_map.dart';
 import '../kernel/kernel_strategy.dart';
 import '../kernel/kelements.dart' show KClass, KField;
@@ -77,6 +78,9 @@
       _fixedInitializers[_elementMap.getField(fieldNode)] = value;
     });
   }
+
+  ConstantValue getFixedInitializerForTesting(KField field) =>
+      _fixedInitializers[field];
 }
 
 class JAllocatorAnalysis implements AllocatorAnalysis {
diff --git a/pkg/compiler/lib/src/js_backend/annotations.dart b/pkg/compiler/lib/src/js_backend/annotations.dart
index 15db202..5290143 100644
--- a/pkg/compiler/lib/src/js_backend/annotations.dart
+++ b/pkg/compiler/lib/src/js_backend/annotations.dart
@@ -11,6 +11,7 @@
 import '../elements/entities.dart';
 import '../kernel/dart2js_target.dart';
 import '../serialization/serialization.dart';
+import '../util/enumset.dart';
 
 /// Returns `true` if inference of parameter types is disabled for [element].
 bool _assumeDynamic(KElementEnvironment elementEnvironment,
@@ -34,14 +35,63 @@
   return false;
 }
 
-enum PragmaAnnotation {
-  noInline,
-  tryInline,
-  disableFinal,
-  noThrows,
-  noSideEffects,
-  trustTypeAnnotations,
-  assumeDynamic,
+class PragmaAnnotation {
+  final int _index;
+  final String name;
+  final bool forFunctionsOnly;
+  final bool forFieldsOnly;
+  final bool internalOnly;
+
+  const PragmaAnnotation(this._index, this.name,
+      {this.forFunctionsOnly: false,
+      this.forFieldsOnly: false,
+      this.internalOnly: false});
+
+  int get index {
+    assert(_index == values.indexOf(this));
+    return _index;
+  }
+
+  static const PragmaAnnotation noInline =
+      const PragmaAnnotation(0, 'noInline', forFunctionsOnly: true);
+
+  static const PragmaAnnotation tryInline =
+      const PragmaAnnotation(1, 'tryInline', forFunctionsOnly: true);
+
+  static const PragmaAnnotation disableFinal = const PragmaAnnotation(
+      2, 'disableFinal',
+      forFunctionsOnly: true, internalOnly: true);
+
+  static const PragmaAnnotation noElision = const PragmaAnnotation(
+      3, 'noElision',
+      forFieldsOnly: true, internalOnly: true);
+
+  static const PragmaAnnotation noThrows = const PragmaAnnotation(4, 'noThrows',
+      forFunctionsOnly: true, internalOnly: true);
+
+  static const PragmaAnnotation noSideEffects = const PragmaAnnotation(
+      5, 'noSideEffects',
+      forFunctionsOnly: true, internalOnly: true);
+
+  // TODO(johnniwinther): Remove this.
+  static const PragmaAnnotation trustTypeAnnotations = const PragmaAnnotation(
+      6, 'trustTypeAnnotations',
+      forFunctionsOnly: true, internalOnly: true);
+
+  static const PragmaAnnotation assumeDynamic = const PragmaAnnotation(
+      7, 'assumeDynamic',
+      forFunctionsOnly: true, internalOnly: true);
+
+  static const List<PragmaAnnotation> values = [
+    noInline,
+    tryInline,
+    disableFinal,
+    noElision,
+    noThrows,
+    noSideEffects,
+    trustTypeAnnotations,
+    assumeDynamic,
+  ];
 }
 
 Set<PragmaAnnotation> processMemberAnnotations(
@@ -50,31 +100,18 @@
     KElementEnvironment elementEnvironment,
     AnnotationsDataBuilder annotationsDataBuilder,
     MemberEntity element) {
-  Set<PragmaAnnotation> values = new Set<PragmaAnnotation>();
-  bool hasNoInline = false;
-  bool hasTryInline = false;
-  bool disableFinal = false;
+  EnumSet<PragmaAnnotation> values = new EnumSet<PragmaAnnotation>();
 
   if (_assumeDynamic(elementEnvironment, commonElements, element)) {
     values.add(PragmaAnnotation.assumeDynamic);
-    annotationsDataBuilder.registerAssumeDynamic(element);
   }
 
-  // TODO(sra): Check for inappropriate annotations on fields.
-  if (element.isField) {
-    return values;
-  }
-
-  FunctionEntity method = element;
   LibraryEntity library = element.library;
   bool platformAnnotationsAllowed = library.canonicalUri.scheme == 'dart' ||
       maybeEnableNative(library.canonicalUri);
 
-  bool hasNoThrows = false;
-  bool hasNoSideEffects = false;
-
   for (ConstantValue constantValue
-      in elementEnvironment.getMemberMetadata(method)) {
+      in elementEnvironment.getMemberMetadata(element)) {
     if (!constantValue.isConstructedObject) continue;
     ConstructedConstantValue value = constantValue;
     ClassEntity cls = value.type.element;
@@ -82,38 +119,65 @@
 
     if (platformAnnotationsAllowed) {
       if (cls == commonElements.forceInlineClass) {
-        hasTryInline = true;
+        values.add(PragmaAnnotation.tryInline);
+        if (element is! FunctionEntity) {
+          reporter.internalError(element,
+              "@TryInline() is only allowed in methods and constructors.");
+        }
       } else if (cls == commonElements.noInlineClass) {
-        hasNoInline = true;
+        values.add(PragmaAnnotation.noInline);
+        if (element is! FunctionEntity) {
+          reporter.internalError(element,
+              "@NoInline() is only allowed in methods and constructors.");
+        }
       } else if (cls == commonElements.noThrowsClass) {
-        hasNoThrows = true;
+        values.add(PragmaAnnotation.noThrows);
         bool isValid = true;
-        if (method.isTopLevel) {
-          isValid = true;
-        } else if (method.isStatic) {
-          isValid = true;
-        } else if (method is ConstructorEntity && method.isFactoryConstructor) {
-          isValid = true;
+        if (element is FunctionEntity) {
+          if (element.isTopLevel) {
+            isValid = true;
+          } else if (element.isStatic) {
+            isValid = true;
+          } else if (element is ConstructorEntity &&
+              element.isFactoryConstructor) {
+            isValid = true;
+          }
+        } else {
+          isValid = false;
         }
         if (!isValid) {
           reporter.internalError(
-              method,
+              element,
               "@NoThrows() is currently limited to top-level"
               " or static functions and factory constructors.");
         }
-        annotationsDataBuilder.registerCannotThrow(method);
       } else if (cls == commonElements.noSideEffectsClass) {
-        hasNoSideEffects = true;
-        annotationsDataBuilder.registerSideEffectsFree(method);
+        values.add(PragmaAnnotation.noSideEffects);
+        if (element is! FunctionEntity) {
+          reporter.internalError(element,
+              "@NoSideEffects() is only allowed in methods and constructors.");
+        }
       }
     }
 
     if (cls == commonElements.expectNoInlineClass) {
-      hasNoInline = true;
+      values.add(PragmaAnnotation.noInline);
+      if (element is! FunctionEntity) {
+        reporter.internalError(element,
+            "@NoInline() is only allowed in methods and constructors.");
+      }
     } else if (cls == commonElements.metaNoInlineClass) {
-      hasNoInline = true;
+      values.add(PragmaAnnotation.noInline);
+      if (element is! FunctionEntity) {
+        reporter.internalError(
+            element, "@noInline is only allowed in methods and constructors.");
+      }
     } else if (cls == commonElements.metaTryInlineClass) {
-      hasTryInline = true;
+      values.add(PragmaAnnotation.tryInline);
+      if (element is! FunctionEntity) {
+        reporter.internalError(
+            element, "@tryInline is only allowed in methods and constructors.");
+      }
     } else if (cls == commonElements.pragmaClass) {
       // Recognize:
       //
@@ -124,64 +188,71 @@
           value.fields[commonElements.pragmaClassNameField];
       if (nameValue == null || !nameValue.isString) continue;
       String name = (nameValue as StringConstantValue).stringValue;
-      if (!name.startsWith('dart2js:')) continue;
+      String prefix = 'dart2js:';
+      if (!name.startsWith(prefix)) continue;
+      String suffix = name.substring(prefix.length);
 
       ConstantValue optionsValue =
           value.fields[commonElements.pragmaClassOptionsField];
-      if (name == 'dart2js:noInline') {
-        if (!optionsValue.isNull) {
-          reporter.reportErrorMessage(element, MessageKind.GENERIC,
-              {'text': "@pragma('$name') annotation does not take options"});
-        }
-        hasNoInline = true;
-      } else if (name == 'dart2js:tryInline') {
-        if (!optionsValue.isNull) {
-          reporter.reportErrorMessage(element, MessageKind.GENERIC,
-              {'text': "@pragma('$name') annotation does not take options"});
-        }
-        hasTryInline = true;
-      } else if (!platformAnnotationsAllowed) {
-        reporter.reportErrorMessage(element, MessageKind.GENERIC,
-            {'text': "Unknown dart2js pragma @pragma('$name')"});
-      } else {
-        // Handle platform-only `@pragma` annotations.
-        if (name == 'dart2js:disableFinal') {
+      bool found = false;
+      for (PragmaAnnotation annotation in PragmaAnnotation.values) {
+        if (annotation.name == suffix) {
+          found = true;
+          values.add(annotation);
+
           if (!optionsValue.isNull) {
             reporter.reportErrorMessage(element, MessageKind.GENERIC,
                 {'text': "@pragma('$name') annotation does not take options"});
           }
-          disableFinal = true;
+          if (annotation.forFunctionsOnly) {
+            if (element is! FunctionEntity) {
+              reporter.reportErrorMessage(element, MessageKind.GENERIC, {
+                'text': "@pragma('$name') annotation is only supported "
+                    "for methods and constructors."
+              });
+            }
+          }
+          if (annotation.forFieldsOnly) {
+            if (element is! FieldEntity) {
+              reporter.reportErrorMessage(element, MessageKind.GENERIC, {
+                'text': "@pragma('$name') annotation is only supported "
+                    "for fields."
+              });
+            }
+          }
+          if (annotation.internalOnly && !platformAnnotationsAllowed) {
+            reporter.reportErrorMessage(element, MessageKind.GENERIC,
+                {'text': "Unrecognized dart2js pragma @pragma('$name')"});
+          }
+          break;
         }
       }
+      if (!found) {
+        reporter.reportErrorMessage(element, MessageKind.GENERIC,
+            {'text': "Unknown dart2js pragma @pragma('$name')"});
+      }
     }
   }
 
-  if (hasTryInline && hasNoInline) {
+  if (values.contains(PragmaAnnotation.tryInline) &&
+      values.contains(PragmaAnnotation.noInline)) {
     reporter.reportErrorMessage(element, MessageKind.GENERIC,
         {'text': '@tryInline must not be used with @noInline.'});
-    hasTryInline = false;
+    values.remove(PragmaAnnotation.tryInline);
   }
-  if (hasNoInline) {
-    values.add(PragmaAnnotation.noInline);
-    annotationsDataBuilder.markAsNonInlinable(method);
-  }
-  if (hasTryInline) {
-    values.add(PragmaAnnotation.tryInline);
-    annotationsDataBuilder.markAsTryInline(method);
-  }
-  if (disableFinal) {
-    values.add(PragmaAnnotation.disableFinal);
-    annotationsDataBuilder.markAsDisableFinal(method);
-  }
-  if (hasNoThrows && !hasNoInline) {
+  if (values.contains(PragmaAnnotation.noThrows) &&
+      !values.contains(PragmaAnnotation.noInline)) {
     reporter.internalError(
-        method, "@NoThrows() should always be combined with @noInline.");
+        element, "@NoThrows() should always be combined with @noInline.");
   }
-  if (hasNoSideEffects && !hasNoInline) {
+  if (values.contains(PragmaAnnotation.noSideEffects) &&
+      !values.contains(PragmaAnnotation.noInline)) {
     reporter.internalError(
-        method, "@NoSideEffects() should always be combined with @noInline.");
+        element, "@NoSideEffects() should always be combined with @noInline.");
   }
-  return values;
+  annotationsDataBuilder.registerPragmaAnnotations(element, values);
+  return new Set<PragmaAnnotation>.from(
+      values.iterable(PragmaAnnotation.values));
 }
 
 abstract class AnnotationsData {
@@ -192,25 +263,43 @@
   /// Serializes this [AnnotationsData] to [sink].
   void writeToDataSink(DataSink sink);
 
-  /// Functions with a `@NoInline()`, `@noInline`, or
+  /// Returns `true` if [member] has an `@AssumeDynamic()` annotation.
+  bool hasAssumeDynamic(MemberEntity member);
+
+  /// Returns `true` if [member] has a `@NoInline()`, `@noInline`, or
   /// `@pragma('dart2js:noInline')` annotation.
-  Iterable<FunctionEntity> get nonInlinableFunctions;
+  bool hasNoInline(MemberEntity member);
 
-  /// Functions with a `@ForceInline()`, `@tryInline`, or
+  /// Returns `true` if [member] has a `@ForceInline()`, `@tryInline`, or
   /// `@pragma('dart2js:tryInline')` annotation.
-  Iterable<FunctionEntity> get tryInlineFunctions;
+  bool hasTryInline(MemberEntity member);
 
-  /// Functions with a `@pragma('dart2js:disable-final')` annotation.
-  Iterable<FunctionEntity> get disableFinalFunctions;
+  /// Returns `true` if [member] has a `@pragma('dart2js:disableFinal')`
+  /// annotation.
+  bool hasDisableFinal(MemberEntity member);
 
-  /// Functions with a `@NoThrows()` annotation.
-  Iterable<FunctionEntity> get cannotThrowFunctions;
+  /// Returns `true` if [member] has a `@pragma('dart2js:noElision')` annotation.
+  bool hasNoElision(MemberEntity member);
 
-  /// Functions with a `@NoSideEffects()` annotation.
-  Iterable<FunctionEntity> get sideEffectFreeFunctions;
+  /// Returns `true` if [member] has a `@NoThrows()` annotation.
+  bool hasNoThrows(MemberEntity member);
 
-  /// Members with a `@AssumeDynamic()` annotation.
-  Iterable<MemberEntity> get assumeDynamicMembers;
+  /// Returns `true` if [member] has a `@NoSideEffects()` annotation.
+  bool hasNoSideEffects(MemberEntity member);
+
+  /// Calls [f] for all functions with a `@NoInline()`, `@noInline`, or
+  /// `@pragma('dart2js:noInline')` annotation.
+  void forEachNoInline(void f(FunctionEntity function));
+
+  /// Calls [f] for all functions with a `@ForceInline()`, `@tryInline`, or
+  /// `@pragma('dart2js:tryInline')` annotation.
+  void forEachTryInline(void f(FunctionEntity function));
+
+  /// Calls [f] for all functions with a `@NoThrows()` annotation.
+  void forEachNoThrows(void f(FunctionEntity function));
+
+  /// Calls [f] for all functions with a `@NoSideEffects()` annotation.
+  void forEachNoSideEffects(void f(FunctionEntity function));
 }
 
 class AnnotationsDataImpl implements AnnotationsData {
@@ -218,118 +307,100 @@
   /// debugging data stream.
   static const String tag = 'annotations-data';
 
-  final Iterable<FunctionEntity> nonInlinableFunctions;
-  final Iterable<FunctionEntity> tryInlineFunctions;
-  final Iterable<FunctionEntity> disableFinalFunctions;
-  final Iterable<FunctionEntity> cannotThrowFunctions;
-  final Iterable<FunctionEntity> sideEffectFreeFunctions;
-  final Iterable<MemberEntity> assumeDynamicMembers;
+  final Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations;
 
-  AnnotationsDataImpl(
-      this.nonInlinableFunctions,
-      this.tryInlineFunctions,
-      this.disableFinalFunctions,
-      this.cannotThrowFunctions,
-      this.sideEffectFreeFunctions,
-      this.assumeDynamicMembers);
+  AnnotationsDataImpl(this.pragmaAnnotations);
 
   factory AnnotationsDataImpl.readFromDataSource(DataSource source) {
     source.begin(tag);
-    Iterable<FunctionEntity> nonInlinableFunctions =
-        source.readMembers<FunctionEntity>(emptyAsNull: true) ??
-            const <FunctionEntity>[];
-    Iterable<FunctionEntity> tryInlineFunctions =
-        source.readMembers<FunctionEntity>(emptyAsNull: true) ??
-            const <FunctionEntity>[];
-    Iterable<FunctionEntity> disableFinalFunctions =
-        source.readMembers<FunctionEntity>(emptyAsNull: true) ??
-            const <FunctionEntity>[];
-    Iterable<FunctionEntity> cannotThrowFunctions =
-        source.readMembers<FunctionEntity>(emptyAsNull: true) ??
-            const <FunctionEntity>[];
-    Iterable<FunctionEntity> sideEffectFreeFunctions =
-        source.readMembers<FunctionEntity>(emptyAsNull: true) ??
-            const <FunctionEntity>[];
-    Iterable<MemberEntity> assumeDynamicMembers =
-        source.readMembers<MemberEntity>(emptyAsNull: true) ??
-            const <MemberEntity>[];
+    Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations =
+        source.readMemberMap(() => new EnumSet.fromValue(source.readInt()));
     source.end(tag);
-    return new AnnotationsDataImpl(
-        nonInlinableFunctions,
-        tryInlineFunctions,
-        disableFinalFunctions,
-        cannotThrowFunctions,
-        sideEffectFreeFunctions,
-        assumeDynamicMembers);
+    return new AnnotationsDataImpl(pragmaAnnotations);
   }
 
   void writeToDataSink(DataSink sink) {
     sink.begin(tag);
-    sink.writeMembers(nonInlinableFunctions);
-    sink.writeMembers(tryInlineFunctions);
-    sink.writeMembers(disableFinalFunctions);
-    sink.writeMembers(cannotThrowFunctions);
-    sink.writeMembers(sideEffectFreeFunctions);
-    sink.writeMembers(assumeDynamicMembers);
+    sink.writeMemberMap(pragmaAnnotations, (EnumSet<PragmaAnnotation> set) {
+      sink.writeInt(set.value);
+    });
     sink.end(tag);
   }
+
+  bool _hasPragma(MemberEntity member, PragmaAnnotation annotation) {
+    EnumSet<PragmaAnnotation> set = pragmaAnnotations[member];
+    return set != null && set.contains(annotation);
+  }
+
+  bool hasAssumeDynamic(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.assumeDynamic);
+
+  bool hasNoInline(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.noInline);
+
+  bool hasTryInline(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.tryInline);
+
+  bool hasDisableFinal(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.disableFinal);
+
+  bool hasNoElision(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.noElision);
+
+  bool hasNoThrows(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.noThrows);
+
+  bool hasNoSideEffects(MemberEntity member) =>
+      _hasPragma(member, PragmaAnnotation.noSideEffects);
+
+  void forEachNoInline(void f(FunctionEntity function)) {
+    pragmaAnnotations
+        .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
+      if (set.contains(PragmaAnnotation.noInline)) {
+        f(member);
+      }
+    });
+  }
+
+  void forEachTryInline(void f(FunctionEntity function)) {
+    pragmaAnnotations
+        .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
+      if (set.contains(PragmaAnnotation.tryInline)) {
+        f(member);
+      }
+    });
+  }
+
+  void forEachNoThrows(void f(FunctionEntity function)) {
+    pragmaAnnotations
+        .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
+      if (set.contains(PragmaAnnotation.noThrows)) {
+        f(member);
+      }
+    });
+  }
+
+  void forEachNoSideEffects(void f(FunctionEntity function)) {
+    pragmaAnnotations
+        .forEach((MemberEntity member, EnumSet<PragmaAnnotation> set) {
+      if (set.contains(PragmaAnnotation.noSideEffects)) {
+        f(member);
+      }
+    });
+  }
 }
 
-class AnnotationsDataBuilder implements AnnotationsData {
-  List<FunctionEntity> _nonInlinableFunctions;
-  List<FunctionEntity> _tryInlinableFunctions;
-  List<FunctionEntity> _disableFinalFunctions;
-  List<FunctionEntity> _cannotThrowFunctions;
-  List<FunctionEntity> _sideEffectFreeFunctions;
-  List<MemberEntity> _trustTypeAnnotationsMembers;
-  List<MemberEntity> _assumeDynamicMembers;
+class AnnotationsDataBuilder {
+  Map<MemberEntity, EnumSet<PragmaAnnotation>> pragmaAnnotations = {};
 
-  void markAsNonInlinable(FunctionEntity function) {
-    _nonInlinableFunctions ??= <FunctionEntity>[];
-    _nonInlinableFunctions.add(function);
+  void registerPragmaAnnotations(
+      MemberEntity member, EnumSet<PragmaAnnotation> annotations) {
+    if (annotations.isNotEmpty) {
+      pragmaAnnotations[member] = annotations;
+    }
   }
 
-  void markAsTryInline(FunctionEntity function) {
-    _tryInlinableFunctions ??= <FunctionEntity>[];
-    _tryInlinableFunctions.add(function);
-  }
-
-  void markAsDisableFinal(FunctionEntity function) {
-    _disableFinalFunctions ??= <FunctionEntity>[];
-    _disableFinalFunctions.add(function);
-  }
-
-  void registerCannotThrow(FunctionEntity function) {
-    _cannotThrowFunctions ??= <FunctionEntity>[];
-    _cannotThrowFunctions.add(function);
-  }
-
-  void registerSideEffectsFree(FunctionEntity function) {
-    _sideEffectFreeFunctions ??= <FunctionEntity>[];
-    _sideEffectFreeFunctions.add(function);
-  }
-
-  void registerAssumeDynamic(MemberEntity member) {
-    _assumeDynamicMembers ??= <MemberEntity>[];
-    _assumeDynamicMembers.add(member);
-  }
-
-  Iterable<FunctionEntity> get nonInlinableFunctions =>
-      _nonInlinableFunctions ?? const <FunctionEntity>[];
-  Iterable<FunctionEntity> get tryInlineFunctions =>
-      _tryInlinableFunctions ?? const <FunctionEntity>[];
-  Iterable<FunctionEntity> get disableFinalFunctions =>
-      _disableFinalFunctions ?? const <FunctionEntity>[];
-  Iterable<FunctionEntity> get cannotThrowFunctions =>
-      _cannotThrowFunctions ?? const <FunctionEntity>[];
-  Iterable<FunctionEntity> get sideEffectFreeFunctions =>
-      _sideEffectFreeFunctions ?? const <FunctionEntity>[];
-  Iterable<MemberEntity> get trustTypeAnnotationsMembers =>
-      _trustTypeAnnotationsMembers ?? const <MemberEntity>[];
-  Iterable<MemberEntity> get assumeDynamicMembers =>
-      _assumeDynamicMembers ?? const <MemberEntity>[];
-
-  void writeToDataSink(DataSink sink) {
-    throw new UnsupportedError('AnnotationsDataBuilder.writeToDataSink');
+  AnnotationsData close() {
+    return new AnnotationsDataImpl(pragmaAnnotations);
   }
 }
diff --git a/pkg/compiler/lib/src/js_backend/backend.dart b/pkg/compiler/lib/src/js_backend/backend.dart
index be118eb..5d868e8 100644
--- a/pkg/compiler/lib/src/js_backend/backend.dart
+++ b/pkg/compiler/lib/src/js_backend/backend.dart
@@ -95,10 +95,10 @@
   final Set<FunctionEntity> _tryInlineFunctions = new Set<FunctionEntity>();
 
   FunctionInlineCache(AnnotationsData annotationsData) {
-    annotationsData.nonInlinableFunctions.forEach((FunctionEntity function) {
+    annotationsData.forEachNoInline((FunctionEntity function) {
       markAsNonInlinable(function);
     });
-    annotationsData.tryInlineFunctions.forEach((FunctionEntity function) {
+    annotationsData.forEachTryInline((FunctionEntity function) {
       markAsTryInline(function);
     });
   }
@@ -408,6 +408,9 @@
 
   ImpactCacheDeleter get impactCacheDeleter => compiler.impactCacheDeleter;
 
+  KAllocatorAnalysis get allocatorResolutionAnalysisForTesting =>
+      _allocatorResolutionAnalysis;
+
   /// Resolution support for generating table of interceptors and
   /// constructors for custom elements.
   CustomElementsResolutionAnalysis get customElementsResolutionAnalysis {
diff --git a/pkg/compiler/lib/src/js_backend/constant_emitter.dart b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
index 3fb4475..e705bb1 100644
--- a/pkg/compiler/lib/src/js_backend/constant_emitter.dart
+++ b/pkg/compiler/lib/src/js_backend/constant_emitter.dart
@@ -224,7 +224,8 @@
     // are in the same order as the members of the class element.
     int emittedArgumentCount = 0;
     _worldBuilder.forEachInstanceField(classElement,
-        (ClassEntity enclosing, FieldEntity field) {
+        (ClassEntity enclosing, FieldEntity field, {bool isElided}) {
+      if (isElided) return;
       if (field.name == JavaScriptMapConstant.LENGTH_NAME) {
         arguments
             .add(new jsAst.LiteralNumber('${constant.keyList.entries.length}'));
@@ -318,7 +319,9 @@
     jsAst.Expression constructor =
         _emitter.constructorAccess(constant.type.element);
     List<jsAst.Expression> fields = <jsAst.Expression>[];
-    _worldBuilder.forEachInstanceField(element, (_, FieldEntity field) {
+    _worldBuilder.forEachInstanceField(element, (_, FieldEntity field,
+        {bool isElided}) {
+      if (isElided) return;
       if (!_allocatorAnalysis.isInitializedInAllocator(field)) {
         fields.add(constantReferenceGenerator(constant.fields[field]));
       }
diff --git a/pkg/compiler/lib/src/js_backend/inferred_data.dart b/pkg/compiler/lib/src/js_backend/inferred_data.dart
index d68b500..ad5be30 100644
--- a/pkg/compiler/lib/src/js_backend/inferred_data.dart
+++ b/pkg/compiler/lib/src/js_backend/inferred_data.dart
@@ -218,8 +218,8 @@
       new Set<FunctionEntity>();
 
   InferredDataBuilderImpl(AnnotationsData annotationsData) {
-    annotationsData.cannotThrowFunctions.forEach(registerCannotThrow);
-    annotationsData.sideEffectFreeFunctions.forEach(registerSideEffectsFree);
+    annotationsData.forEachNoThrows(registerCannotThrow);
+    annotationsData.forEachNoSideEffects(registerSideEffectsFree);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_backend/namer.dart b/pkg/compiler/lib/src/js_backend/namer.dart
index 9e7a95b..51674ab 100644
--- a/pkg/compiler/lib/src/js_backend/namer.dart
+++ b/pkg/compiler/lib/src/js_backend/namer.dart
@@ -2008,8 +2008,9 @@
 
     // TODO(johnniwinther): This should be accessed from a codegen closed world.
     codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldEntity field) {
+        (_, FieldEntity field, {bool isElided}) {
       if (failed) return;
+      if (isElided) return;
       _visit(constant.fields[field]);
     });
   }
@@ -2147,7 +2148,8 @@
   int visitConstructed(ConstructedConstantValue constant, [_]) {
     int hash = _hashString(3, constant.type.element.name);
     codegenWorldBuilder.forEachInstanceField(constant.type.element,
-        (_, FieldEntity field) {
+        (_, FieldEntity field, {bool isElided}) {
+      if (isElided) return;
       hash = _combine(hash, _visit(constant.fields[field]));
     });
     return hash;
diff --git a/pkg/compiler/lib/src/js_backend/runtime_types.dart b/pkg/compiler/lib/src/js_backend/runtime_types.dart
index ec375e0..b9a0d33 100644
--- a/pkg/compiler/lib/src/js_backend/runtime_types.dart
+++ b/pkg/compiler/lib/src/js_backend/runtime_types.dart
@@ -813,7 +813,6 @@
   }
 
   bool methodNeedsTypeArguments(FunctionEntity function) {
-    if (function.parameterStructure.typeParameters == 0) return false;
     return methodsNeedingTypeArguments.contains(function);
   }
 
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 e6fbf87..e44e0a8 100644
--- a/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/instantiation_stub_generator.dart
@@ -139,7 +139,8 @@
     // 2. Find the function field access path.
     FieldEntity functionField;
     _codegenWorldBuilder.forEachInstanceField(instantiationClass,
-        (ClassEntity enclosing, FieldEntity field) {
+        (ClassEntity enclosing, FieldEntity field, {bool isElided}) {
+      if (isElided) return;
       if (field.name == '_genericClosure') functionField = field;
     });
     assert(functionField != null,
diff --git a/pkg/compiler/lib/src/js_emitter/model.dart b/pkg/compiler/lib/src/js_emitter/model.dart
index 7829d79..9fb47bc 100644
--- a/pkg/compiler/lib/src/js_emitter/model.dart
+++ b/pkg/compiler/lib/src/js_emitter/model.dart
@@ -384,9 +384,18 @@
 
   final ConstantValue initializerInAllocator;
 
+  final bool isElided;
+
   // TODO(floitsch): support renamed fields.
-  Field(this.element, this.name, this.accessorName, this.getterFlags,
-      this.setterFlags, this.needsCheckedSetter, this.initializerInAllocator);
+  Field(
+      this.element,
+      this.name,
+      this.accessorName,
+      this.getterFlags,
+      this.setterFlags,
+      this.needsCheckedSetter,
+      this.initializerInAllocator,
+      this.isElided);
 
   bool get needsGetter => getterFlags != 0;
   bool get needsUncheckedSetter => setterFlags != 0;
@@ -545,8 +554,9 @@
   /// If a stub's member can not be torn off, the [callName] is `null`.
   js.Name callName;
 
-  ParameterStubMethod(js.Name name, this.callName, js.Expression code)
-      : super(name, code);
+  ParameterStubMethod(js.Name name, this.callName, js.Expression code,
+      {MemberEntity element})
+      : super(name, code, element: element);
 
   String toString() {
     return 'ParameterStubMethod(name=${name.key}, callName=${callName?.key}'
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 ac44280..dd65523 100644
--- a/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
+++ b/pkg/compiler/lib/src/js_emitter/parameter_stub_generator.dart
@@ -226,7 +226,7 @@
     jsAst.Name name = member.isStatic ? null : _namer.invocationName(selector);
     jsAst.Name callName =
         (callSelector != null) ? _namer.invocationName(callSelector) : null;
-    return new ParameterStubMethod(name, callName, function);
+    return new ParameterStubMethod(name, callName, function, element: member);
   }
 
   // We fill the lists depending on possible/invoked selectors. For example,
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 023faf2..b981d83 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
@@ -1072,8 +1072,15 @@
         initializerInAllocator = _allocatorAnalysis.initializerValue(field);
       }
 
-      fields.add(new Field(field, name, accessorName, getterFlags, setterFlags,
-          needsCheckedSetter, initializerInAllocator));
+      fields.add(new Field(
+          field,
+          name,
+          accessorName,
+          getterFlags,
+          setterFlags,
+          needsCheckedSetter,
+          initializerInAllocator,
+          _closedWorld.elidedFields.contains(field)));
     }
 
     FieldVisitor visitor = new FieldVisitor(_options, _elementEnvironment,
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 8e5224c..965e232 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
@@ -918,8 +918,10 @@
       statements.add(js.js.statement('allocations["$qualifiedName"] = true'));
     }
 
+    List<Field> emittedFields = cls.fields.where((f) => !f.isElided).toList();
+
     // If there are many references to `this`, cache it in a local.
-    if (cls.fields.length + (cls.hasRtiField ? 1 : 0) >= 4) {
+    if (emittedFields.length + (cls.hasRtiField ? 1 : 0) >= 4) {
       // Parameters are named t0, t1, etc, so '_' will not conflict. Forcing '_'
       // in minified mode works because no parameter or local also minifies to
       // '_' (the minifier doesn't know '_' is available).
@@ -945,7 +947,7 @@
       }
     }
 
-    for (Field field in cls.fields) {
+    for (Field field in emittedFields) {
       ConstantValue constant = field.initializerInAllocator;
       if (constant != null) {
         if (constant == previousConstant && chainLength < maxChainLength) {
@@ -1096,17 +1098,22 @@
     assert(field.needsUncheckedSetter);
 
     String template;
-    if (field.needsInterceptedSetterOnReceiver) {
-      template = "function(receiver, val) { return receiver[#] = val; }";
-    } else if (field.needsInterceptedSetterOnThis) {
-      template = "function(receiver, val) { return this[#] = val; }";
+    js.Expression code;
+    if (field.isElided) {
+      code = js.js("function() { }");
     } else {
-      assert(!field.needsInterceptedSetter);
-      template = "function(val) { return this[#] = val; }";
+      if (field.needsInterceptedSetterOnReceiver) {
+        template = "function(receiver, val) { return receiver[#] = val; }";
+      } else if (field.needsInterceptedSetterOnThis) {
+        template = "function(receiver, val) { return this[#] = val; }";
+      } else {
+        assert(!field.needsInterceptedSetter);
+        template = "function(val) { return this[#] = val; }";
+      }
+      js.Expression fieldName = js.quoteName(field.name);
+      code = js.js(template, fieldName);
     }
 
-    js.Expression fieldName = js.quoteName(field.name);
-    js.Expression code = js.js(template, fieldName);
     js.Name setterName = namer.deriveSetterName(field.accessorName);
     return new StubMethod(setterName, code);
   }
diff --git a/pkg/compiler/lib/src/js_model/closure.dart b/pkg/compiler/lib/src/js_model/closure.dart
index 1afc338..5057b6a 100644
--- a/pkg/compiler/lib/src/js_model/closure.dart
+++ b/pkg/compiler/lib/src/js_model/closure.dart
@@ -13,7 +13,6 @@
 import '../elements/types.dart';
 import '../ir/closure.dart';
 import '../ir/element_map.dart';
-import '../ir/util.dart';
 import '../js_model/element_map.dart';
 import '../js_model/env.dart';
 import '../ordered_typeset.dart';
@@ -1032,7 +1031,7 @@
 }
 
 class ClosureFunctionData extends ClosureMemberData
-    with FunctionDataMixin
+    with FunctionDataTypeVariablesMixin, FunctionDataForEachParameterMixin
     implements FunctionData {
   /// Tag used for identifying serialized [ClosureFunctionData] objects in a
   /// debugging data stream.
@@ -1075,31 +1074,6 @@
     sink.end(tag);
   }
 
-  void forEachParameter(JsToElementMap elementMap,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
-    void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
-      DartType type = elementMap.getDartType(node.type);
-      String name = node.name;
-      ConstantValue defaultValue;
-      if (isOptional) {
-        if (node.initializer != null) {
-          defaultValue = elementMap.getConstantValue(node.initializer);
-        } else {
-          defaultValue = new NullConstantValue();
-        }
-      }
-      f(type, name, defaultValue);
-    }
-
-    for (int i = 0; i < functionNode.positionalParameters.length; i++) {
-      handleParameter(functionNode.positionalParameters[i],
-          isOptional: i >= functionNode.requiredParameterCount);
-    }
-    functionNode.namedParameters.toList()
-      ..sort(namedOrdering)
-      ..forEach(handleParameter);
-  }
-
   @override
   FunctionType getFunctionType(IrToElementMap elementMap) {
     return functionType;
diff --git a/pkg/compiler/lib/src/js_model/element_map.dart b/pkg/compiler/lib/src/js_model/element_map.dart
index f0b0efd..b495237 100644
--- a/pkg/compiler/lib/src/js_model/element_map.dart
+++ b/pkg/compiler/lib/src/js_model/element_map.dart
@@ -524,3 +524,83 @@
   }
   return node.initializer;
 }
+
+void forEachOrderedParameterByFunctionNode(
+    ir.FunctionNode node,
+    ParameterStructure parameterStructure,
+    void f(ir.VariableDeclaration parameter, {bool isOptional, bool isElided}),
+    {bool useNativeOrdering: false}) {
+  for (int position = 0;
+      position < node.positionalParameters.length;
+      position++) {
+    ir.VariableDeclaration variable = node.positionalParameters[position];
+    f(variable,
+        isOptional: position >= parameterStructure.requiredParameters,
+        isElided: position >= parameterStructure.positionalParameters);
+  }
+
+  if (node.namedParameters.isEmpty) {
+    return;
+  }
+
+  List<ir.VariableDeclaration> namedParameters = node.namedParameters.toList();
+  if (useNativeOrdering) {
+    namedParameters.sort(nativeOrdering);
+  } else {
+    namedParameters.sort(namedOrdering);
+  }
+  for (ir.VariableDeclaration variable in namedParameters) {
+    f(variable,
+        isOptional: true,
+        isElided: !parameterStructure.namedParameters.contains(variable.name));
+  }
+}
+
+void forEachOrderedParameter(JsToElementMap elementMap, FunctionEntity function,
+    void f(ir.VariableDeclaration parameter, {bool isElided})) {
+  ParameterStructure parameterStructure = function.parameterStructure;
+
+  void handleParameter(ir.VariableDeclaration parameter,
+      {bool isOptional, bool isElided}) {
+    f(parameter, isElided: isElided);
+  }
+
+  MemberDefinition definition = elementMap.getMemberDefinition(function);
+  switch (definition.kind) {
+    case MemberKind.regular:
+      ir.Node node = definition.node;
+      if (node is ir.Procedure) {
+        forEachOrderedParameterByFunctionNode(
+            node.function, parameterStructure, handleParameter);
+        return;
+      }
+      break;
+    case MemberKind.constructor:
+    case MemberKind.constructorBody:
+      ir.Node node = definition.node;
+      if (node is ir.Procedure) {
+        forEachOrderedParameterByFunctionNode(
+            node.function, parameterStructure, handleParameter);
+        return;
+      } else if (node is ir.Constructor) {
+        forEachOrderedParameterByFunctionNode(
+            node.function, parameterStructure, handleParameter);
+        return;
+      }
+      break;
+    case MemberKind.closureCall:
+      ir.Node node = definition.node;
+      if (node is ir.FunctionDeclaration) {
+        forEachOrderedParameterByFunctionNode(
+            node.function, parameterStructure, handleParameter);
+        return;
+      } else if (node is ir.FunctionExpression) {
+        forEachOrderedParameterByFunctionNode(
+            node.function, parameterStructure, handleParameter);
+        return;
+      }
+      break;
+    default:
+  }
+  failedAt(function, "Unexpected function definition $definition.");
+}
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 47433bc..ad03cc0 100644
--- a/pkg/compiler/lib/src/js_model/element_map_impl.dart
+++ b/pkg/compiler/lib/src/js_model/element_map_impl.dart
@@ -50,6 +50,7 @@
 import '../serialization/serialization.dart';
 import '../ssa/type_builder.dart';
 import '../universe/call_structure.dart';
+import '../universe/member_usage.dart';
 import '../universe/selector.dart';
 
 import 'closure.dart';
@@ -69,7 +70,8 @@
   /// 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));
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false});
 }
 
 class JsKernelToElementMap
@@ -143,8 +145,11 @@
 
   Map<IndexedClass, List<IndexedMember>> _injectedClassMembers = {};
 
-  JsKernelToElementMap(this.reporter, Environment environment,
-      KernelToElementMapImpl _elementMap, Iterable<MemberEntity> liveMembers)
+  JsKernelToElementMap(
+      this.reporter,
+      Environment environment,
+      KernelToElementMapImpl _elementMap,
+      Map<MemberEntity, MemberUsage> liveMemberUsage)
       : this.options = _elementMap.options {
     _elementEnvironment = new JsElementEnvironment(this);
     _commonElements = new CommonElementsImpl(_elementEnvironment);
@@ -160,7 +165,7 @@
       KLibraryEnv oldEnv = _elementMap.libraries.getEnv(oldLibrary);
       KLibraryData data = _elementMap.libraries.getData(oldLibrary);
       IndexedLibrary newLibrary = convertLibrary(oldLibrary);
-      JLibraryEnv newEnv = oldEnv.convert(_elementMap, liveMembers);
+      JLibraryEnv newEnv = oldEnv.convert(_elementMap, liveMemberUsage);
       libraryMap[oldEnv.library] =
           libraries.register<IndexedLibrary, JLibraryData, JLibraryEnv>(
               newLibrary, data.convert(), newEnv);
@@ -177,7 +182,7 @@
       IndexedLibrary oldLibrary = oldClass.library;
       LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
       IndexedClass newClass = convertClass(newLibrary, oldClass);
-      JClassEnv newEnv = env.convert(_elementMap, liveMembers);
+      JClassEnv newEnv = env.convert(_elementMap, liveMemberUsage);
       classMap[env.cls] = classes.register(newClass, data.convert(), newEnv);
       assert(newClass.classIndex == oldClass.classIndex);
       libraries.getEnv(newClass.library).registerClass(newClass.name, newEnv);
@@ -205,7 +210,8 @@
         memberIndex < _elementMap.members.length;
         memberIndex++) {
       IndexedMember oldMember = _elementMap.members.getEntity(memberIndex);
-      if (!liveMembers.contains(oldMember)) {
+      MemberUsage memberUsage = liveMemberUsage[oldMember];
+      if (memberUsage == null) {
         members.skipIndex(oldMember.memberIndex);
         continue;
       }
@@ -215,9 +221,14 @@
       LibraryEntity newLibrary = libraries.getEntity(oldLibrary.libraryIndex);
       ClassEntity newClass =
           oldClass != null ? classes.getEntity(oldClass.classIndex) : null;
-      IndexedMember newMember = convertMember(newLibrary, newClass, oldMember);
+      IndexedMember newMember =
+          convertMember(newLibrary, newClass, oldMember, memberUsage);
       members.register(newMember, data.convert());
-      assert(newMember.memberIndex == oldMember.memberIndex);
+      assert(
+          newMember.memberIndex == oldMember.memberIndex,
+          "Member index mismatch: "
+          "Old member $oldMember has index ${oldMember.memberIndex} "
+          "whereas new member $newMember has index ${newMember.memberIndex}");
       if (newMember.isField) {
         fieldMap[data.node] = newMember;
       } else if (newMember.isConstructor) {
@@ -1119,20 +1130,6 @@
         argumentCount, namedArguments, arguments.types.length);
   }
 
-  ParameterStructure getParameterStructure(ir.FunctionNode node,
-      // TODO(johnniwinther): Remove this when type arguments are passed to
-      // constructors like calling a generic method.
-      {bool includeTypeParameters: true}) {
-    // TODO(johnniwinther): Cache the computed function type.
-    int requiredParameters = node.requiredParameterCount;
-    int positionalParameters = node.positionalParameters.length;
-    int typeParameters = node.typeParameters.length;
-    List<String> namedParameters =
-        node.namedParameters.map((p) => p.name).toList()..sort();
-    return new ParameterStructure(requiredParameters, positionalParameters,
-        namedParameters, includeTypeParameters ? typeParameters : 0);
-  }
-
   Selector getSelector(ir.Expression node) {
     // TODO(efortuna): This is screaming for a common interface between
     // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
@@ -1479,8 +1476,9 @@
         isFromEnvironmentConstructor: isFromEnvironmentConstructor);
   }
 
-  JConstructorBody createConstructorBody(ConstructorEntity constructor) {
-    return new JConstructorBody(constructor);
+  JConstructorBody createConstructorBody(
+      ConstructorEntity constructor, ParameterStructure parameterStructure) {
+    return new JConstructorBody(constructor, parameterStructure);
   }
 
   JGeneratorBody createGeneratorBody(
@@ -1535,8 +1533,8 @@
     return createTypedef(library, typedef.name);
   }
 
-  MemberEntity convertMember(
-      LibraryEntity library, ClassEntity cls, IndexedMember member) {
+  MemberEntity convertMember(LibraryEntity library, ClassEntity cls,
+      IndexedMember member, MemberUsage memberUsage) {
     Name memberName = new Name(member.memberName.text, library,
         isSetter: member.memberName.isSetter);
     if (member.isField) {
@@ -1550,14 +1548,14 @@
       if (constructor.isFactoryConstructor) {
         // TODO(redemption): This should be a JFunction.
         return createFactoryConstructor(
-            cls, memberName, constructor.parameterStructure,
+            cls, memberName, memberUsage.invokedParameters,
             isExternal: constructor.isExternal,
             isConst: constructor.isConst,
             isFromEnvironmentConstructor:
                 constructor.isFromEnvironmentConstructor);
       } else {
         return createGenerativeConstructor(
-            cls, memberName, constructor.parameterStructure,
+            cls, memberName, memberUsage.invokedParameters,
             isExternal: constructor.isExternal, isConst: constructor.isConst);
       }
     } else if (member.isGetter) {
@@ -1574,8 +1572,8 @@
           isAbstract: setter.isAbstract);
     } else {
       IndexedFunction function = member;
-      return createMethod(library, cls, memberName, function.parameterStructure,
-          function.asyncMarker,
+      return createMethod(library, cls, memberName,
+          memberUsage.invokedParameters, function.asyncMarker,
           isStatic: function.isStatic,
           isExternal: function.isExternal,
           isAbstract: function.isAbstract);
@@ -1695,7 +1693,14 @@
       ir.Constructor node, covariant IndexedConstructor constructor) {
     JConstructorDataImpl data = members.getData(constructor);
     if (data.constructorBody == null) {
-      JConstructorBody constructorBody = createConstructorBody(constructor);
+      /// The constructor calls the constructor body with all parameters.
+      // TODO(johnniwinther): Remove parameters that are not used in the
+      //  constructor body.
+      ParameterStructure parameterStructure =
+          _getParameterStructureFromFunctionNode(node.function);
+
+      JConstructorBody constructorBody =
+          createConstructorBody(constructor, parameterStructure);
       members.register<IndexedFunction, FunctionData>(
           constructorBody,
           new ConstructorBodyDataImpl(
@@ -1744,9 +1749,11 @@
 
   @override
   void forEachParameter(covariant IndexedFunction function,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false}) {
     FunctionData data = members.getData(function);
-    data.forEachParameter(this, f);
+    data.forEachParameter(this, function.parameterStructure, f,
+        isNative: isNative);
   }
 
   void forEachConstructorBody(
@@ -1818,6 +1825,17 @@
           Local local, Map<Local, JRecordField> recordFieldsVisibleInScope) =>
       recordFieldsVisibleInScope.containsKey(local);
 
+  ParameterStructure _getParameterStructureFromFunctionNode(
+      ir.FunctionNode node) {
+    int requiredParameters = node.requiredParameterCount;
+    int positionalParameters = node.positionalParameters.length;
+    int typeParameters = node.typeParameters.length;
+    List<String> namedParameters =
+        node.namedParameters.map((p) => p.name).toList()..sort();
+    return new ParameterStructure(requiredParameters, positionalParameters,
+        namedParameters, typeParameters);
+  }
+
   KernelClosureClassInfo constructClosureClass(
       MemberEntity member,
       ir.FunctionNode node,
@@ -1861,8 +1879,8 @@
       closureEntity = new AnonymousClosureLocal(classEntity);
     }
 
-    IndexedFunction callMethod = new JClosureCallMethod(
-        classEntity, getParameterStructure(node), getAsyncMarker(node));
+    IndexedFunction callMethod = new JClosureCallMethod(classEntity,
+        _getParameterStructureFromFunctionNode(node), getAsyncMarker(node));
     _nestedClosureMap
         .putIfAbsent(member, () => <IndexedFunction>[])
         .add(callMethod);
@@ -2537,39 +2555,6 @@
   bool get enableAssertions => _elementMap.options.enableUserAssertions;
 }
 
-class JsToFrontendMapImpl extends JsToFrontendMapBase
-    implements JsToFrontendMap {
-  final JsKernelToElementMap _backend;
-
-  JsToFrontendMapImpl(this._backend);
-
-  LibraryEntity toBackendLibrary(covariant IndexedLibrary library) {
-    return _backend.libraries.getEntity(library.libraryIndex);
-  }
-
-  ClassEntity toBackendClass(covariant IndexedClass cls) {
-    return _backend.classes.getEntity(cls.classIndex);
-  }
-
-  MemberEntity toBackendMember(covariant IndexedMember member) {
-    return _backend.members.getEntity(member.memberIndex);
-  }
-
-  TypedefEntity toBackendTypedef(covariant IndexedTypedef typedef) {
-    return _backend.typedefs.getEntity(typedef.typedefIndex);
-  }
-
-  TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable) {
-    if (typeVariable is KLocalTypeVariable) {
-      failedAt(
-          typeVariable, "Local function type variables are not supported.");
-    }
-    IndexedTypeVariable indexedTypeVariable = typeVariable;
-    return _backend.typeVariables
-        .getEntity(indexedTypeVariable.typeVariableIndex);
-  }
-}
-
 /// [EntityLookup] implementation used to deserialize [JsKernelToElementMap].
 ///
 /// Since data objects and environments are registered together with their
diff --git a/pkg/compiler/lib/src/js_model/elements.dart b/pkg/compiler/lib/src/js_model/elements.dart
index cc98750..4afe45a 100644
--- a/pkg/compiler/lib/src/js_model/elements.dart
+++ b/pkg/compiler/lib/src/js_model/elements.dart
@@ -13,170 +13,6 @@
 import '../universe/class_set.dart' show ClassHierarchyNodesMapKey;
 import 'closure.dart';
 
-/// Map from 'frontend' to 'backend' elements.
-///
-/// Frontend elements are what we read in, these typically represents concepts
-/// in Dart. Backend elements are what we generate, these may include elements
-/// that do not correspond to a Dart concept, such as closure classes.
-///
-/// Querying for the frontend element for a backend-only element throws an
-/// exception.
-abstract class JsToFrontendMap {
-  LibraryEntity toBackendLibrary(LibraryEntity library);
-
-  ClassEntity toBackendClass(ClassEntity cls);
-
-  /// Returns the backend member corresponding to [member]. If a member isn't
-  /// live, it doesn't have a corresponding backend member and `null` is
-  /// returned instead.
-  MemberEntity toBackendMember(MemberEntity member);
-
-  DartType toBackendType(DartType type);
-
-  Set<LibraryEntity> toBackendLibrarySet(Iterable<LibraryEntity> set) {
-    return set.map(toBackendLibrary).toSet();
-  }
-
-  Set<ClassEntity> toBackendClassSet(Iterable<ClassEntity> set) {
-    // TODO(johnniwinther): Filter unused classes.
-    return set.map(toBackendClass).toSet();
-  }
-
-  Set<MemberEntity> toBackendMemberSet(Iterable<MemberEntity> set) {
-    return set.map(toBackendMember).where((MemberEntity member) {
-      // Members that are not live don't have a corresponding backend member.
-      return member != null;
-    }).toSet();
-  }
-
-  Set<FunctionEntity> toBackendFunctionSet(Iterable<FunctionEntity> set) {
-    Set<FunctionEntity> newSet = new Set<FunctionEntity>();
-    for (FunctionEntity element in set) {
-      FunctionEntity backendFunction = toBackendMember(element);
-      if (backendFunction != null) {
-        // Members that are not live don't have a corresponding backend member.
-        newSet.add(backendFunction);
-      }
-    }
-    return newSet;
-  }
-
-  Map<LibraryEntity, V> toBackendLibraryMap<V>(
-      Map<LibraryEntity, V> map, V convert(V value)) {
-    return convertMap(map, toBackendLibrary, convert);
-  }
-
-  Map<ClassEntity, V> toBackendClassMap<V>(
-      Map<ClassEntity, V> map, V convert(V value)) {
-    return convertMap(map, toBackendClass, convert);
-  }
-
-  Map<MemberEntity, V> toBackendMemberMap<V>(
-      Map<MemberEntity, V> map, V convert(V 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) {
-    K newKey = convertKey(key);
-    V newValue = convertValue(value);
-    if (newKey != null && newValue != null) {
-      // Entities that are not used don't have a corresponding backend entity.
-      newMap[newKey] = newValue;
-    }
-  });
-  return newMap;
-}
-
-abstract class JsToFrontendMapBase extends JsToFrontendMap {
-  DartType toBackendType(DartType type) =>
-      type == null ? null : const TypeConverter().visit(type, _toBackendEntity);
-
-  Entity _toBackendEntity(Entity entity) {
-    if (entity is ClassEntity) return toBackendClass(entity);
-    assert(entity is TypeVariableEntity);
-    return toBackendTypeVariable(entity);
-  }
-
-  TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable);
-}
-
-typedef Entity EntityConverter(Entity cls);
-
-class TypeConverter implements DartTypeVisitor<DartType, EntityConverter> {
-  const TypeConverter();
-
-  @override
-  DartType visit(DartType type, EntityConverter converter) {
-    return type.accept(this, converter);
-  }
-
-  List<DartType> visitList(List<DartType> types, EntityConverter converter) {
-    List<DartType> list = <DartType>[];
-    for (DartType type in types) {
-      list.add(visit(type, converter));
-    }
-    return list;
-  }
-
-  @override
-  DartType visitDynamicType(DynamicType type, EntityConverter converter) {
-    return const DynamicType();
-  }
-
-  @override
-  DartType visitInterfaceType(InterfaceType type, EntityConverter converter) {
-    return new InterfaceType(
-        converter(type.element), visitList(type.typeArguments, converter));
-  }
-
-  @override
-  DartType visitTypedefType(TypedefType type, EntityConverter converter) {
-    return new TypedefType(
-        converter(type.element),
-        visitList(type.typeArguments, converter),
-        visit(type.unaliased, converter));
-  }
-
-  @override
-  DartType visitFunctionType(FunctionType type, EntityConverter converter) {
-    return new FunctionType(
-        visit(type.returnType, converter),
-        visitList(type.parameterTypes, converter),
-        visitList(type.optionalParameterTypes, converter),
-        type.namedParameters,
-        visitList(type.namedParameterTypes, converter),
-        type.typeVariables);
-  }
-
-  @override
-  DartType visitTypeVariableType(
-      TypeVariableType type, EntityConverter converter) {
-    return new TypeVariableType(converter(type.element));
-  }
-
-  @override
-  DartType visitFunctionTypeVariable(
-      FunctionTypeVariable type, EntityConverter converter) {
-    return type;
-  }
-
-  @override
-  DartType visitVoidType(VoidType type, EntityConverter converter) {
-    return const VoidType();
-  }
-
-  @override
-  DartType visitFutureOrType(FutureOrType type, EntityConverter converter) {
-    return new FutureOrType(visit(type.typeArgument, converter));
-  }
-}
-
 const String jsElementPrefix = 'j:';
 
 class JLibrary extends IndexedLibrary {
@@ -536,21 +372,18 @@
 
   final JConstructor constructor;
 
-  JConstructorBody(this.constructor)
-      : super(
-            constructor.library,
-            constructor.enclosingClass,
-            constructor.memberName,
-            constructor.parameterStructure,
-            AsyncMarker.SYNC,
-            isStatic: false,
-            isExternal: false);
+  JConstructorBody(this.constructor, ParameterStructure parameterStructure)
+      : super(constructor.library, constructor.enclosingClass,
+            constructor.memberName, parameterStructure, AsyncMarker.SYNC,
+            isStatic: false, isExternal: false);
 
   factory JConstructorBody.readFromDataSource(DataSource source) {
     source.begin(tag);
     JConstructor constructor = source.readMember();
+    ParameterStructure parameterStructure =
+        new ParameterStructure.readFromDataSource(source);
     source.end(tag);
-    return new JConstructorBody(constructor);
+    return new JConstructorBody(constructor, parameterStructure);
   }
 
   @override
@@ -558,6 +391,7 @@
     sink.writeEnum(JMemberKind.constructorBody);
     sink.begin(tag);
     sink.writeMember(constructor);
+    parameterStructure.writeToDataSink(sink);
     sink.end(tag);
   }
 
diff --git a/pkg/compiler/lib/src/js_model/env.dart b/pkg/compiler/lib/src/js_model/env.dart
index a22112b..17cc2e9 100644
--- a/pkg/compiler/lib/src/js_model/env.dart
+++ b/pkg/compiler/lib/src/js_model/env.dart
@@ -15,7 +15,6 @@
 import '../elements/types.dart';
 import '../ir/element_map.dart';
 import '../ir/visitors.dart';
-import '../ir/util.dart';
 import '../js_model/element_map.dart';
 import '../ordered_typeset.dart';
 import '../serialization/serialization.dart';
@@ -565,11 +564,14 @@
 
   List<TypeVariableType> getFunctionTypeVariables(IrToElementMap elementMap);
 
-  void forEachParameter(JsToElementMap elementMap,
-      void f(DartType type, String name, ConstantValue defaultValue));
+  void forEachParameter(
+      JsToElementMap elementMap,
+      ParameterStructure parameterStructure,
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false});
 }
 
-abstract class FunctionDataMixin implements FunctionData {
+abstract class FunctionDataTypeVariablesMixin implements FunctionData {
   ir.FunctionNode get functionNode;
   List<TypeVariableType> _typeVariables;
 
@@ -597,8 +599,39 @@
   }
 }
 
+abstract class FunctionDataForEachParameterMixin implements FunctionData {
+  ir.FunctionNode get functionNode;
+
+  void forEachParameter(
+      JsToElementMap elementMap,
+      ParameterStructure parameterStructure,
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false}) {
+    void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
+      DartType type = elementMap.getDartType(node.type);
+      String name = node.name;
+      ConstantValue defaultValue;
+      if (isOptional) {
+        if (node.initializer != null) {
+          defaultValue = elementMap.getConstantValue(node.initializer);
+        } else {
+          defaultValue = new NullConstantValue();
+        }
+      }
+      f(type, name, defaultValue);
+    }
+
+    forEachOrderedParameterByFunctionNode(functionNode, parameterStructure,
+        (ir.VariableDeclaration parameter, {bool isOptional, bool isElided}) {
+      if (!isElided) {
+        handleParameter(parameter, isOptional: isOptional);
+      }
+    }, useNativeOrdering: isNative);
+  }
+}
+
 class FunctionDataImpl extends JMemberDataImpl
-    with FunctionDataMixin
+    with FunctionDataTypeVariablesMixin, FunctionDataForEachParameterMixin
     implements FunctionData {
   /// Tag used for identifying serialized [FunctionDataImpl] objects in a
   /// debugging data stream.
@@ -644,31 +677,6 @@
     return _type ??= elementMap.getFunctionType(functionNode);
   }
 
-  void forEachParameter(JsToElementMap elementMap,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
-    void handleParameter(ir.VariableDeclaration node, {bool isOptional: true}) {
-      DartType type = elementMap.getDartType(node.type);
-      String name = node.name;
-      ConstantValue defaultValue;
-      if (isOptional) {
-        if (node.initializer != null) {
-          defaultValue = elementMap.getConstantValue(node.initializer);
-        } else {
-          defaultValue = new NullConstantValue();
-        }
-      }
-      f(type, name, defaultValue);
-    }
-
-    for (int i = 0; i < functionNode.positionalParameters.length; i++) {
-      handleParameter(functionNode.positionalParameters[i],
-          isOptional: i >= functionNode.requiredParameterCount);
-    }
-    functionNode.namedParameters.toList()
-      ..sort(namedOrdering)
-      ..forEach(handleParameter);
-  }
-
   @override
   ClassTypeVariableAccess get classTypeVariableAccess {
     if (node.isInstanceMember) return ClassTypeVariableAccess.property;
@@ -726,8 +734,11 @@
     }).toList();
   }
 
-  void forEachParameter(JsToElementMap elementMap,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
+  void forEachParameter(
+      JsToElementMap elementMap,
+      ParameterStructure parameterStructure,
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false}) {
     throw new UnimplementedError('SignatureData.forEachParameter');
   }
 
@@ -749,9 +760,13 @@
     return baseData.getFunctionTypeVariables(elementMap);
   }
 
-  void forEachParameter(JsToElementMap elementMap,
-      void f(DartType type, String name, ConstantValue defaultValue)) {
-    return baseData.forEachParameter(elementMap, f);
+  void forEachParameter(
+      JsToElementMap elementMap,
+      ParameterStructure parameterStructure,
+      void f(DartType type, String name, ConstantValue defaultValue),
+      {bool isNative: false}) {
+    return baseData.forEachParameter(elementMap, parameterStructure, f,
+        isNative: isNative);
   }
 
   InterfaceType getMemberThisType(JsToElementMap elementMap) {
diff --git a/pkg/compiler/lib/src/js_model/js_strategy.dart b/pkg/compiler/lib/src/js_model/js_strategy.dart
index 22b6f9d8..8715893 100644
--- a/pkg/compiler/lib/src/js_model/js_strategy.dart
+++ b/pkg/compiler/lib/src/js_model/js_strategy.dart
@@ -64,7 +64,7 @@
         _compiler.reporter,
         _compiler.environment,
         strategy.elementMap,
-        closedWorld.processedMembers);
+        closedWorld.liveMemberUsage);
     GlobalLocalsMap _globalLocalsMap = new GlobalLocalsMap();
     ClosureDataBuilder closureDataBuilder = new ClosureDataBuilder(
         _elementMap, _globalLocalsMap, _compiler.options);
@@ -94,7 +94,11 @@
   @override
   SsaBuilder createSsaBuilder(CompilerTask task, JavaScriptBackend backend,
       SourceInformationStrategy sourceInformationStrategy) {
-    return new KernelSsaBuilder(task, backend.compiler, elementMap);
+    return new KernelSsaBuilder(
+        task,
+        backend.compiler,
+        // ignore:deprecated_member_use_from_same_package
+        elementMap);
   }
 
   @override
diff --git a/pkg/compiler/lib/src/js_model/js_world.dart b/pkg/compiler/lib/src/js_model/js_world.dart
index 39e86a0..3f6ca05 100644
--- a/pkg/compiler/lib/src/js_model/js_world.dart
+++ b/pkg/compiler/lib/src/js_model/js_world.dart
@@ -80,6 +80,7 @@
   final GlobalLocalsMap globalLocalsMap;
   final ClosureData closureDataLookup;
   final OutputUnitData outputUnitData;
+  final Set<FieldEntity> elidedFields;
   Sorter _sorter;
 
   JsClosedWorld(
@@ -102,7 +103,8 @@
       this.annotationsData,
       this.globalLocalsMap,
       this.closureDataLookup,
-      this.outputUnitData) {
+      this.outputUnitData,
+      this.elidedFields) {
     _abstractValueDomain = abstractValueStrategy.createDomain(this);
   }
 
@@ -156,6 +158,8 @@
     OutputUnitData outputUnitData =
         new OutputUnitData.readFromDataSource(source);
 
+    Set<FieldEntity> elidedFields = source.readMembers<FieldEntity>().toSet();
+
     source.end(tag);
 
     return new JsClosedWorld(
@@ -178,7 +182,8 @@
         annotationsData,
         globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        elidedFields);
   }
 
   /// Serializes this [JsClosedWorld] to [sink].
@@ -206,6 +211,7 @@
     annotationsData.writeToDataSink(sink);
     closureDataLookup.writeToDataSink(sink);
     outputUnitData.writeToDataSink(sink);
+    sink.writeMembers(elidedFields);
     sink.end(tag);
   }
 
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 552d014..3b39476 100644
--- a/pkg/compiler/lib/src/js_model/js_world_builder.dart
+++ b/pkg/compiler/lib/src/js_model/js_world_builder.dart
@@ -5,10 +5,12 @@
 import 'package:kernel/ast.dart' as ir;
 
 import '../closure.dart';
+import '../common.dart';
 import '../common_elements.dart';
 import '../constants/values.dart';
 import '../deferred_load.dart';
 import '../elements/entities.dart';
+import '../elements/indexed.dart';
 import '../elements/names.dart';
 import '../elements/types.dart';
 import '../inferrer/abstract_value_domain.dart';
@@ -26,6 +28,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';
@@ -123,7 +126,7 @@
         map.toBackendClassSet(closedWorld.liveNativeClasses);
 
     Set<MemberEntity> processedMembers =
-        map.toBackendMemberSet(closedWorld.processedMembers);
+        map.toBackendMemberSet(closedWorld.liveMemberUsage.keys);
 
     RuntimeTypesNeed rtiNeed;
 
@@ -192,23 +195,26 @@
     JAllocatorAnalysis allocatorAnalysis =
         JAllocatorAnalysis.from(closedWorld.allocatorAnalysis, map, _options);
 
+    AnnotationsDataImpl oldAnnotationsData = closedWorld.annotationsData;
     AnnotationsData annotationsData = new AnnotationsDataImpl(
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.nonInlinableFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.tryInlineFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.disableFinalFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.cannotThrowFunctions),
-        map.toBackendFunctionSet(
-            closedWorld.annotationsData.sideEffectFreeFunctions),
-        map.toBackendMemberSet(
-            closedWorld.annotationsData.assumeDynamicMembers));
+        map.toBackendMemberMap(oldAnnotationsData.pragmaAnnotations, identity));
 
     OutputUnitData outputUnitData =
         _convertOutputUnitData(map, kOutputUnitData, closureData);
 
+    Set<FieldEntity> elidedFields = new Set();
+    closedWorld.liveMemberUsage
+        .forEach((MemberEntity member, MemberUsage memberUsage) {
+      // TODO(johnniwinther): Should elided static fields be removed from the
+      // J model? Static setters might still assign to them.
+      if (member.isField &&
+          !memberUsage.hasRead &&
+          !closedWorld.annotationsData.hasNoElision(member) &&
+          !closedWorld.nativeData.isNativeMember(member)) {
+        elidedFields.add(map.toBackendMember(member));
+      }
+    });
+
     return new JsClosedWorld(
         _elementMap,
         nativeData,
@@ -233,7 +239,8 @@
         annotationsData,
         _globalLocalsMap,
         closureData,
-        outputUnitData);
+        outputUnitData,
+        elidedFields);
   }
 
   BackendUsage _convertBackendUsage(
@@ -298,7 +305,12 @@
   NativeData _convertNativeData(
       JsToFrontendMap map, NativeDataImpl nativeData) {
     convertNativeBehaviorType(type) {
-      if (type is DartType) return map.toBackendType(type);
+      if (type is DartType) {
+        // TODO(johnniwinther): Avoid free variables in types. If the type
+        // pulled from a generic function type it might contain a function
+        // type variable that should probably have been replaced by its bound.
+        return map.toBackendType(type, allowFreeVariables: true);
+      }
       assert(type is SpecialType);
       return type;
     }
@@ -447,18 +459,6 @@
 
   OutputUnitData _convertOutputUnitData(JsToFrontendMapImpl map,
       OutputUnitData data, ClosureData closureDataLookup) {
-    Entity toBackendEntity(Entity entity) {
-      if (entity is ClassEntity) return map.toBackendClass(entity);
-      if (entity is MemberEntity) return map.toBackendMember(entity);
-      if (entity is TypedefEntity) return map.toBackendTypedef(entity);
-      if (entity is TypeVariableEntity) {
-        return map.toBackendTypeVariable(entity);
-      }
-      assert(
-          entity is LibraryEntity, 'unexpected entity ${entity.runtimeType}');
-      return map.toBackendLibrary(entity);
-    }
-
     // Convert front-end maps containing K-class and K-local function keys to a
     // backend map using J-classes as keys.
     Map<ClassEntity, OutputUnit> convertClassMap(
@@ -466,7 +466,7 @@
         Map<Local, OutputUnit> localFunctionMap) {
       var result = <ClassEntity, OutputUnit>{};
       classMap.forEach((ClassEntity entity, OutputUnit unit) {
-        ClassEntity backendEntity = toBackendEntity(entity);
+        ClassEntity backendEntity = map.toBackendClass(entity);
         if (backendEntity != null) {
           // If [entity] isn't used it doesn't have a corresponding backend
           // entity.
@@ -491,7 +491,7 @@
         Map<Local, OutputUnit> localFunctionMap) {
       var result = <MemberEntity, OutputUnit>{};
       memberMap.forEach((MemberEntity entity, OutputUnit unit) {
-        MemberEntity backendEntity = toBackendEntity(entity);
+        MemberEntity backendEntity = map.toBackendMember(entity);
         if (backendEntity != null) {
           // If [entity] isn't used it doesn't have a corresponding backend
           // entity.
@@ -509,17 +509,13 @@
       return result;
     }
 
-    ConstantValue toBackendConstant(ConstantValue constant) {
-      return constant.accept(new ConstantConverter(toBackendEntity), null);
-    }
-
     return new OutputUnitData.from(
         data,
         map.toBackendLibrary,
         convertClassMap,
         convertMemberMap,
         (m) => convertMap<ConstantValue, OutputUnit>(
-            m, toBackendConstant, (v) => v));
+            m, map.toBackendConstant, (v) => v));
   }
 }
 
@@ -592,12 +588,259 @@
       rtiNeed.instantiationNeedsTypeArguments(functionType, typeArgumentCount);
 }
 
-class ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
-  final Entity Function(Entity) toBackendEntity;
-  final TypeConverter typeConverter;
+/// Map from 'frontend' to 'backend' elements.
+///
+/// Frontend elements are what we read in, these typically represents concepts
+/// in Dart. Backend elements are what we generate, these may include elements
+/// that do not correspond to a Dart concept, such as closure classes.
+///
+/// Querying for the frontend element for a backend-only element throws an
+/// exception.
+abstract class JsToFrontendMap {
+  LibraryEntity toBackendLibrary(LibraryEntity library);
 
-  ConstantConverter(this.toBackendEntity)
-      : typeConverter = new TypeConverter(toBackendEntity);
+  ClassEntity toBackendClass(ClassEntity cls);
+
+  /// Returns the backend member corresponding to [member]. If a member isn't
+  /// live, it doesn't have a corresponding backend member and `null` is
+  /// returned instead.
+  MemberEntity toBackendMember(MemberEntity member);
+
+  DartType toBackendType(DartType type, {bool allowFreeVariables: false});
+
+  ConstantValue toBackendConstant(ConstantValue value);
+
+  Set<LibraryEntity> toBackendLibrarySet(Iterable<LibraryEntity> set) {
+    return set.map(toBackendLibrary).toSet();
+  }
+
+  Set<ClassEntity> toBackendClassSet(Iterable<ClassEntity> set) {
+    // TODO(johnniwinther): Filter unused classes.
+    return set.map(toBackendClass).toSet();
+  }
+
+  Set<MemberEntity> toBackendMemberSet(Iterable<MemberEntity> set) {
+    return set.map(toBackendMember).where((MemberEntity member) {
+      // Members that are not live don't have a corresponding backend member.
+      return member != null;
+    }).toSet();
+  }
+
+  Set<FieldEntity> toBackendFieldSet(Iterable<FieldEntity> set) {
+    Set<FieldEntity> newSet = new Set<FieldEntity>();
+    for (FieldEntity element in set) {
+      FieldEntity backendField = toBackendMember(element);
+      if (backendField != null) {
+        // Members that are not live don't have a corresponding backend member.
+        newSet.add(backendField);
+      }
+    }
+    return newSet;
+  }
+
+  Set<FunctionEntity> toBackendFunctionSet(Iterable<FunctionEntity> set) {
+    Set<FunctionEntity> newSet = new Set<FunctionEntity>();
+    for (FunctionEntity element in set) {
+      FunctionEntity backendFunction = toBackendMember(element);
+      if (backendFunction != null) {
+        // Members that are not live don't have a corresponding backend member.
+        newSet.add(backendFunction);
+      }
+    }
+    return newSet;
+  }
+
+  Map<LibraryEntity, V> toBackendLibraryMap<V>(
+      Map<LibraryEntity, V> map, V convert(V value)) {
+    return convertMap(map, toBackendLibrary, convert);
+  }
+
+  Map<ClassEntity, V> toBackendClassMap<V>(
+      Map<ClassEntity, V> map, V convert(V value)) {
+    return convertMap(map, toBackendClass, convert);
+  }
+
+  Map<MemberEntity, V> toBackendMemberMap<V>(
+      Map<MemberEntity, V> map, V convert(V 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) {
+    K newKey = convertKey(key);
+    V newValue = convertValue(value);
+    if (newKey != null && newValue != null) {
+      // Entities that are not used don't have a corresponding backend entity.
+      newMap[newKey] = newValue;
+    }
+  });
+  return newMap;
+}
+
+class JsToFrontendMapImpl extends JsToFrontendMap {
+  final JsKernelToElementMap _backend;
+
+  JsToFrontendMapImpl(this._backend);
+
+  DartType toBackendType(DartType type, {bool allowFreeVariables: false}) =>
+      type == null
+          ? null
+          : new _TypeConverter(allowFreeVariables: allowFreeVariables)
+              .visit(type, toBackendEntity);
+
+  Entity toBackendEntity(Entity entity) {
+    if (entity is ClassEntity) return toBackendClass(entity);
+    if (entity is MemberEntity) return toBackendMember(entity);
+    if (entity is TypedefEntity) return toBackendTypedef(entity);
+    if (entity is TypeVariableEntity) {
+      return toBackendTypeVariable(entity);
+    }
+    assert(entity is LibraryEntity, 'unexpected entity ${entity.runtimeType}');
+    return toBackendLibrary(entity);
+  }
+
+  LibraryEntity toBackendLibrary(covariant IndexedLibrary library) {
+    return _backend.libraries.getEntity(library.libraryIndex);
+  }
+
+  ClassEntity toBackendClass(covariant IndexedClass cls) {
+    return _backend.classes.getEntity(cls.classIndex);
+  }
+
+  MemberEntity toBackendMember(covariant IndexedMember member) {
+    return _backend.members.getEntity(member.memberIndex);
+  }
+
+  TypedefEntity toBackendTypedef(covariant IndexedTypedef typedef) {
+    return _backend.typedefs.getEntity(typedef.typedefIndex);
+  }
+
+  TypeVariableEntity toBackendTypeVariable(TypeVariableEntity typeVariable) {
+    if (typeVariable is KLocalTypeVariable) {
+      failedAt(
+          typeVariable, "Local function type variables are not supported.");
+    }
+    IndexedTypeVariable indexedTypeVariable = typeVariable;
+    return _backend.typeVariables
+        .getEntity(indexedTypeVariable.typeVariableIndex);
+  }
+
+  ConstantValue toBackendConstant(ConstantValue constant) {
+    return constant.accept(new _ConstantConverter(toBackendEntity), null);
+  }
+}
+
+typedef Entity _EntityConverter(Entity cls);
+
+class _TypeConverter implements DartTypeVisitor<DartType, _EntityConverter> {
+  final bool allowFreeVariables;
+
+  Map<FunctionTypeVariable, FunctionTypeVariable> _functionTypeVariables =
+      <FunctionTypeVariable, FunctionTypeVariable>{};
+
+  _TypeConverter({this.allowFreeVariables: false});
+
+  List<DartType> convertTypes(
+          List<DartType> types, _EntityConverter converter) =>
+      visitList(types, converter);
+
+  @override
+  DartType visit(DartType type, _EntityConverter converter) {
+    return type.accept(this, converter);
+  }
+
+  List<DartType> visitList(List<DartType> types, _EntityConverter converter) {
+    List<DartType> list = <DartType>[];
+    for (DartType type in types) {
+      list.add(visit(type, converter));
+    }
+    return list;
+  }
+
+  @override
+  DartType visitDynamicType(DynamicType type, _EntityConverter converter) {
+    return const DynamicType();
+  }
+
+  @override
+  DartType visitInterfaceType(InterfaceType type, _EntityConverter converter) {
+    return new InterfaceType(
+        converter(type.element), visitList(type.typeArguments, converter));
+  }
+
+  @override
+  DartType visitTypedefType(TypedefType type, _EntityConverter converter) {
+    return new TypedefType(
+        converter(type.element),
+        visitList(type.typeArguments, converter),
+        visit(type.unaliased, converter));
+  }
+
+  @override
+  DartType visitTypeVariableType(
+      TypeVariableType type, _EntityConverter converter) {
+    return new TypeVariableType(converter(type.element));
+  }
+
+  @override
+  DartType visitFunctionType(FunctionType type, _EntityConverter converter) {
+    List<FunctionTypeVariable> typeVariables = <FunctionTypeVariable>[];
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      typeVariables.add(_functionTypeVariables[typeVariable] =
+          new FunctionTypeVariable(typeVariable.index));
+    }
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      _functionTypeVariables[typeVariable].bound = typeVariable.bound != null
+          ? visit(typeVariable.bound, converter)
+          : null;
+    }
+    DartType returnType = visit(type.returnType, converter);
+    List<DartType> parameterTypes = visitList(type.parameterTypes, converter);
+    List<DartType> optionalParameterTypes =
+        visitList(type.optionalParameterTypes, converter);
+    List<DartType> namedParameterTypes =
+        visitList(type.namedParameterTypes, converter);
+    for (FunctionTypeVariable typeVariable in type.typeVariables) {
+      _functionTypeVariables.remove(typeVariable);
+    }
+    return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
+        type.namedParameters, namedParameterTypes, typeVariables);
+  }
+
+  @override
+  DartType visitFunctionTypeVariable(
+      FunctionTypeVariable type, _EntityConverter converter) {
+    DartType result = _functionTypeVariables[type];
+    if (result == null && allowFreeVariables) {
+      return type;
+    }
+    assert(result != null,
+        "Function type variable $type not found in $_functionTypeVariables");
+    return result;
+  }
+
+  @override
+  DartType visitVoidType(VoidType type, _EntityConverter converter) {
+    return const VoidType();
+  }
+
+  @override
+  DartType visitFutureOrType(FutureOrType type, _EntityConverter converter) {
+    return new FutureOrType(visit(type.typeArgument, converter));
+  }
+}
+
+class _ConstantConverter implements ConstantValueVisitor<ConstantValue, Null> {
+  final Entity Function(Entity) toBackendEntity;
+  final _TypeConverter typeConverter;
+
+  _ConstantConverter(this.toBackendEntity)
+      : typeConverter = new _TypeConverter();
 
   ConstantValue visitNull(NullConstantValue constant, _) => constant;
   ConstantValue visitInt(IntConstantValue constant, _) => constant;
@@ -608,12 +851,12 @@
   ConstantValue visitNonConstant(NonConstantValue constant, _) => constant;
 
   ConstantValue visitFunction(FunctionConstantValue constant, _) {
-    return new FunctionConstantValue(
-        toBackendEntity(constant.element), typeConverter.visit(constant.type));
+    return new FunctionConstantValue(toBackendEntity(constant.element),
+        typeConverter.visit(constant.type, toBackendEntity));
   }
 
   ConstantValue visitList(ListConstantValue constant, _) {
-    DartType type = typeConverter.visit(constant.type);
+    DartType type = typeConverter.visit(constant.type, toBackendEntity);
     List<ConstantValue> entries = _handleValues(constant.entries);
     if (identical(entries, constant.entries) && type == constant.type) {
       return constant;
@@ -622,7 +865,7 @@
   }
 
   ConstantValue visitMap(MapConstantValue constant, _) {
-    var type = typeConverter.visit(constant.type);
+    var type = typeConverter.visit(constant.type, toBackendEntity);
     List<ConstantValue> keys = _handleValues(constant.keys);
     List<ConstantValue> values = _handleValues(constant.values);
     if (identical(keys, constant.keys) &&
@@ -634,7 +877,7 @@
   }
 
   ConstantValue visitConstructed(ConstructedConstantValue constant, _) {
-    DartType type = typeConverter.visit(constant.type);
+    DartType type = typeConverter.visit(constant.type, toBackendEntity);
     Map<FieldEntity, ConstantValue> fields = {};
     constant.fields.forEach((f, v) {
       FieldEntity backendField = toBackendEntity(f);
@@ -645,8 +888,9 @@
   }
 
   ConstantValue visitType(TypeConstantValue constant, _) {
-    DartType type = typeConverter.visit(constant.type);
-    DartType representedType = typeConverter.visit(constant.representedType);
+    DartType type = typeConverter.visit(constant.type, toBackendEntity);
+    DartType representedType =
+        typeConverter.visit(constant.representedType, toBackendEntity);
     if (type == constant.type && representedType == constant.representedType) {
       return constant;
     }
@@ -668,7 +912,7 @@
   ConstantValue visitInstantiation(InstantiationConstantValue constant, _) {
     ConstantValue function = constant.function.accept(this, null);
     List<DartType> typeArguments =
-        typeConverter.convertTypes(constant.typeArguments);
+        typeConverter.convertTypes(constant.typeArguments, toBackendEntity);
     return new InstantiationConstantValue(typeArguments, function);
   }
 
@@ -685,73 +929,3 @@
     return result ?? values;
   }
 }
-
-class TypeConverter implements DartTypeVisitor<DartType, Null> {
-  final Entity Function(Entity) toBackendEntity;
-
-  TypeConverter(this.toBackendEntity);
-
-  Map<FunctionTypeVariable, FunctionTypeVariable> _functionTypeVariables =
-      <FunctionTypeVariable, FunctionTypeVariable>{};
-
-  DartType visit(DartType type, [_]) => type.accept(this, null);
-
-  List<DartType> convertTypes(List<DartType> types) => _visitList(types);
-
-  DartType visitVoidType(VoidType type, _) => type;
-  DartType visitDynamicType(DynamicType type, _) => type;
-
-  DartType visitTypeVariableType(TypeVariableType type, _) {
-    return new TypeVariableType(toBackendEntity(type.element));
-  }
-
-  DartType visitFunctionTypeVariable(FunctionTypeVariable type, _) {
-    DartType result = _functionTypeVariables[type];
-    assert(result != null,
-        "Function type variable $type not found in $_functionTypeVariables");
-    return result;
-  }
-
-  DartType visitFunctionType(FunctionType type, _) {
-    List<FunctionTypeVariable> typeVariables = <FunctionTypeVariable>[];
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      typeVariables.add(_functionTypeVariables[typeVariable] =
-          new FunctionTypeVariable(typeVariable.index));
-    }
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      _functionTypeVariables[typeVariable].bound =
-          typeVariable.bound?.accept(this, null);
-    }
-    DartType returnType = type.returnType.accept(this, null);
-    List<DartType> parameterTypes = _visitList(type.parameterTypes);
-    List<DartType> optionalParameterTypes =
-        _visitList(type.optionalParameterTypes);
-    List<DartType> namedParameterTypes = _visitList(type.namedParameterTypes);
-    for (FunctionTypeVariable typeVariable in type.typeVariables) {
-      _functionTypeVariables.remove(typeVariable);
-    }
-    return new FunctionType(returnType, parameterTypes, optionalParameterTypes,
-        type.namedParameters, namedParameterTypes, typeVariables);
-  }
-
-  DartType visitInterfaceType(InterfaceType type, _) {
-    ClassEntity element = toBackendEntity(type.element);
-    List<DartType> args = _visitList(type.typeArguments);
-    return new InterfaceType(element, args);
-  }
-
-  DartType visitTypedefType(TypedefType type, _) {
-    TypedefEntity element = toBackendEntity(type.element);
-    List<DartType> args = _visitList(type.typeArguments);
-    DartType unaliased = visit(type.unaliased);
-    return new TypedefType(element, args, unaliased);
-  }
-
-  @override
-  DartType visitFutureOrType(FutureOrType type, _) {
-    return new FutureOrType(visit(type.typeArgument));
-  }
-
-  List<DartType> _visitList(List<DartType> list) =>
-      list.map<DartType>((t) => t.accept(this, null)).toList();
-}
diff --git a/pkg/compiler/lib/src/js_model/locals.dart b/pkg/compiler/lib/src/js_model/locals.dart
index cfeede7..2281cd9 100644
--- a/pkg/compiler/lib/src/js_model/locals.dart
+++ b/pkg/compiler/lib/src/js_model/locals.dart
@@ -12,7 +12,6 @@
 import '../elements/indexed.dart';
 import '../elements/jumps.dart';
 import '../elements/types.dart';
-import '../ir/util.dart';
 import '../serialization/serialization.dart';
 
 import 'element_map.dart';
@@ -617,56 +616,14 @@
 
 /// Calls [f] for each parameter in [function] in the canonical order:
 /// Positional parameters by index, then named parameters lexicographically.
-void forEachOrderedParameter(
+void forEachOrderedParameterAsLocal(
     GlobalLocalsMap globalLocalsMap,
     JsToElementMap elementMap,
     FunctionEntity function,
-    void f(Local parameter)) {
+    void f(Local parameter, {bool isElided})) {
   KernelToLocalsMap localsMap = globalLocalsMap.getLocalsMap(function);
-
-  void processFunctionNode(ir.FunctionNode node) {
-    for (ir.VariableDeclaration variable in node.positionalParameters) {
-      f(localsMap.getLocalVariable(variable));
-    }
-    List<ir.VariableDeclaration> namedParameters =
-        new List<ir.VariableDeclaration>.from(node.namedParameters);
-    namedParameters.sort(namedOrdering);
-    for (ir.VariableDeclaration variable in namedParameters) {
-      f(localsMap.getLocalVariable(variable));
-    }
-  }
-
-  MemberDefinition definition = elementMap.getMemberDefinition(function);
-  switch (definition.kind) {
-    case MemberKind.regular:
-      ir.Node node = definition.node;
-      if (node is ir.Procedure) {
-        processFunctionNode(node.function);
-        return;
-      }
-      break;
-    case MemberKind.constructor:
-    case MemberKind.constructorBody:
-      ir.Node node = definition.node;
-      if (node is ir.Procedure) {
-        processFunctionNode(node.function);
-        return;
-      } else if (node is ir.Constructor) {
-        processFunctionNode(node.function);
-        return;
-      }
-      break;
-    case MemberKind.closureCall:
-      ir.Node node = definition.node;
-      if (node is ir.FunctionDeclaration) {
-        processFunctionNode(node.function);
-        return;
-      } else if (node is ir.FunctionExpression) {
-        processFunctionNode(node.function);
-        return;
-      }
-      break;
-    default:
-  }
-  failedAt(function, "Unexpected function definition $definition.");
+  forEachOrderedParameter(elementMap, function,
+      (ir.VariableDeclaration variable, {bool isElided}) {
+    f(localsMap.getLocalVariable(variable), isElided: isElided);
+  });
 }
diff --git a/pkg/compiler/lib/src/kernel/dart2js_target.dart b/pkg/compiler/lib/src/kernel/dart2js_target.dart
index 7b2863e..a021418 100644
--- a/pkg/compiler/lib/src/kernel/dart2js_target.dart
+++ b/pkg/compiler/lib/src/kernel/dart2js_target.dart
@@ -10,6 +10,7 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart';
+import 'package:kernel/transformations/constants.dart' show ConstantsBackend;
 import 'invocation_mirror_constants.dart';
 
 const Iterable<String> _allowedDartSchemePaths = const <String>[
@@ -138,6 +139,11 @@
     // TODO(sigmund): implement;
     return new ir.InvalidExpression(null);
   }
+
+  // TODO(askesc): Return specialized dart2js constants backend.
+  @override
+  ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
+      new ConstantsBackend();
 }
 
 // TODO(sigmund): this "extraRequiredLibraries" needs to be removed...
diff --git a/pkg/compiler/lib/src/kernel/element_map.dart b/pkg/compiler/lib/src/kernel/element_map.dart
index b6fe609..8fd2d17 100644
--- a/pkg/compiler/lib/src/kernel/element_map.dart
+++ b/pkg/compiler/lib/src/kernel/element_map.dart
@@ -56,13 +56,10 @@
   /// Returns the [CallStructure] corresponding to the [arguments].
   CallStructure getCallStructure(ir.Arguments arguments);
 
-  /// Returns the [Selector] corresponding to the invocation or getter/setter
-  /// access of [node].
-  Selector getSelector(ir.Expression node);
-
   /// Returns the [Selector] corresponding to the invocation of [name] with
   /// [arguments].
-  Selector getInvocationSelector(ir.Name name, ir.Arguments arguments);
+  Selector getInvocationSelector(ir.Name name, int positionalArguments,
+      List<String> namedArguments, int typeArguments);
 
   /// Returns the [MemberEntity] corresponding to the member [node].
   MemberEntity getMember(ir.Member node);
diff --git a/pkg/compiler/lib/src/kernel/element_map_impl.dart b/pkg/compiler/lib/src/kernel/element_map_impl.dart
index 9a8c1d1..343e484 100644
--- a/pkg/compiler/lib/src/kernel/element_map_impl.dart
+++ b/pkg/compiler/lib/src/kernel/element_map_impl.dart
@@ -30,6 +30,8 @@
 import '../frontend_strategy.dart';
 import '../ir/debug.dart';
 import '../ir/element_map.dart';
+import '../ir/impact.dart';
+import '../ir/impact_data.dart';
 import '../ir/static_type.dart';
 import '../ir/scope.dart';
 import '../ir/types.dart';
@@ -60,6 +62,11 @@
 part 'native_basic_data.dart';
 part 'no_such_method_resolver.dart';
 
+/// If `true` kernel impacts are computed as [ImpactData] directly on kernel
+/// and converted to the K model afterwards. This is a pre-step to modularizing
+/// the world impact computation.
+bool useImpactDataForTesting = false;
+
 /// Implementation of [KernelToElementMap] that only supports world
 /// impact computation.
 class KernelToElementMapImpl implements KernelToElementMap, IrToElementMap {
@@ -760,32 +767,8 @@
         namedParameters, includeTypeParameters ? typeParameters : 0);
   }
 
-  Selector getSelector(ir.Expression node) {
-    // TODO(efortuna): This is screaming for a common interface between
-    // PropertyGet and SuperPropertyGet (and same for *Get). Talk to kernel
-    // folks.
-    if (node is ir.PropertyGet) {
-      return getGetterSelector(node.name);
-    }
-    if (node is ir.SuperPropertyGet) {
-      return getGetterSelector(node.name);
-    }
-    if (node is ir.PropertySet) {
-      return getSetterSelector(node.name);
-    }
-    if (node is ir.SuperPropertySet) {
-      return getSetterSelector(node.name);
-    }
-    if (node is ir.InvocationExpression) {
-      return getInvocationSelector(node.name, node.arguments);
-    }
-    throw failedAt(
-        CURRENT_ELEMENT_SPANNABLE,
-        "Can only get the selector for a property get or an invocation: "
-        "${node}");
-  }
-
-  Selector getInvocationSelector(ir.Name irName, ir.Arguments arguments) {
+  Selector getInvocationSelector(ir.Name irName, int positionalArguments,
+      List<String> namedArguments, int typeArguments) {
     Name name = getName(irName);
     SelectorKind kind;
     if (Selector.isOperatorName(name.text)) {
@@ -798,7 +781,10 @@
       kind = SelectorKind.CALL;
     }
 
-    CallStructure callStructure = getCallStructure(arguments);
+    CallStructure callStructure = new CallStructure(
+        positionalArguments + namedArguments.length,
+        namedArguments,
+        typeArguments);
     return new Selector(kind, name, callStructure);
   }
 
@@ -1339,15 +1325,34 @@
       Set<PragmaAnnotation> annotations) {
     KMemberData memberData = members.getData(member);
     ir.Member node = memberData.node;
-    KernelImpactBuilder builder = new KernelImpactBuilder(
-        this, member, reporter, options, variableScopeModel, annotations);
-    if (retainDataForTesting) {
-      typeMapsForTesting ??= {};
-      typeMapsForTesting[member] = builder.typeMapsForTesting = {};
+
+    if (useImpactDataForTesting) {
+      ImpactBuilder builder = new ImpactBuilder(
+          typeEnvironment, classHierarchy, variableScopeModel,
+          useAsserts: options.enableUserAssertions,
+          inferEffectivelyFinalVariableTypes:
+              !annotations.contains(PragmaAnnotation.disableFinal));
+      if (retainDataForTesting) {
+        typeMapsForTesting ??= {};
+        typeMapsForTesting[member] = builder.typeMapsForTesting = {};
+      }
+      node.accept(builder);
+      ImpactData impactData = builder.impactData;
+      memberData.staticTypes = builder.cachedStaticTypes;
+      KernelImpactConverter converter =
+          new KernelImpactConverter(this, member, reporter, options);
+      return converter.convert(impactData);
+    } else {
+      KernelImpactBuilder builder = new KernelImpactBuilder(
+          this, member, reporter, options, variableScopeModel, annotations);
+      if (retainDataForTesting) {
+        typeMapsForTesting ??= {};
+        typeMapsForTesting[member] = builder.typeMapsForTesting = {};
+      }
+      node.accept(builder);
+      memberData.staticTypes = builder.cachedStaticTypes;
+      return builder.impactBuilder;
     }
-    node.accept(builder);
-    memberData.staticTypes = builder.cachedStaticTypes;
-    return builder.impactBuilder;
   }
 
   ScopeModel computeScopeModel(KMember member) {
diff --git a/pkg/compiler/lib/src/kernel/env.dart b/pkg/compiler/lib/src/kernel/env.dart
index f313e3a..7ed64b3 100644
--- a/pkg/compiler/lib/src/kernel/env.dart
+++ b/pkg/compiler/lib/src/kernel/env.dart
@@ -25,6 +25,7 @@
 import '../js_model/env.dart';
 import '../ordered_typeset.dart';
 import '../ssa/type_builder.dart';
+import '../universe/member_usage.dart';
 import 'element_map_impl.dart';
 
 /// Environment for fast lookup of component libraries.
@@ -162,8 +163,8 @@
 
   /// Convert this [KLibraryEnv] to a corresponding [JLibraryEnv] containing
   /// only the members in [liveMembers].
-  JLibraryEnv convert(
-      IrToElementMap elementMap, Iterable<MemberEntity> liveMembers) {
+  JLibraryEnv convert(IrToElementMap elementMap,
+      Map<MemberEntity, MemberUsage> liveMemberUsage) {
     Map<String, ir.Member> memberMap;
     Map<String, ir.Member> setterMap;
     if (_memberMap == null) {
@@ -172,7 +173,7 @@
       memberMap = <String, ir.Member>{};
       _memberMap.forEach((String name, ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           memberMap[name] = node;
         }
       });
@@ -183,7 +184,7 @@
       setterMap = <String, ir.Member>{};
       _setterMap.forEach((String name, ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           setterMap[name] = node;
         }
       });
@@ -268,8 +269,8 @@
 
   /// Convert this [KClassEnv] to the corresponding [JClassEnv] containing only
   /// the members in [liveMembers].
-  JClassEnv convert(
-      IrToElementMap elementMap, Iterable<MemberEntity> liveMembers);
+  JClassEnv convert(IrToElementMap elementMap,
+      Map<MemberEntity, MemberUsage> liveMemberUsage);
 }
 
 int orderByFileOffset(ir.TreeNode a, ir.TreeNode b) {
@@ -544,8 +545,8 @@
     _constructorBodyList?.forEach(f);
   }
 
-  JClassEnv convert(
-      IrToElementMap elementMap, Iterable<MemberEntity> liveMembers) {
+  JClassEnv convert(IrToElementMap elementMap,
+      Map<MemberEntity, MemberUsage> liveMemberUsage) {
     Map<String, ir.Member> constructorMap;
     Map<String, ir.Member> memberMap;
     Map<String, ir.Member> setterMap;
@@ -556,7 +557,7 @@
       constructorMap = <String, ir.Member>{};
       _constructorMap.forEach((String name, ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           constructorMap[name] = node;
         }
       });
@@ -567,7 +568,7 @@
       memberMap = <String, ir.Member>{};
       _memberMap.forEach((String name, ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           memberMap[name] = node;
         }
       });
@@ -578,7 +579,7 @@
       setterMap = <String, ir.Member>{};
       _setterMap.forEach((String name, ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           setterMap[name] = node;
         }
       });
@@ -589,7 +590,7 @@
       members = <ir.Member>[];
       _members.forEach((ir.Member node) {
         MemberEntity member = elementMap.getMember(node);
-        if (liveMembers.contains(member)) {
+        if (liveMemberUsage.containsKey(member)) {
           members.add(node);
         }
       });
diff --git a/pkg/compiler/lib/src/kernel/front_end_adapter.dart b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
index 17b3b15c..169237d 100644
--- a/pkg/compiler/lib/src/kernel/front_end_adapter.dart
+++ b/pkg/compiler/lib/src/kernel/front_end_adapter.dart
@@ -83,32 +83,37 @@
 /// [DiagnosticReporter].
 void reportFrontEndMessage(
     DiagnosticReporter reporter, fe.DiagnosticMessage message) {
-  MessageKind kind = MessageKind.GENERIC;
-  Spannable span;
-  String text;
-  if (message is fe.FormattedMessage) {
-    if (message.uri != null && message.charOffset != -1) {
-      int offset = message.charOffset;
-      span = new SourceSpan(message.uri, offset, offset + message.length);
+  Spannable _getSpannable(fe.DiagnosticMessage message) {
+    Uri uri = fe.getMessageUri(message);
+    int offset = fe.getMessageCharOffset(message);
+    int length = fe.getMessageLength(message);
+    if (uri != null && offset != -1) {
+      return new SourceSpan(uri, offset, offset + length);
     } else {
-      span = NO_LOCATION_SPANNABLE;
+      return NO_LOCATION_SPANNABLE;
     }
-    text = message.message;
-  } else {
-    throw new UnimplementedError(
-        "Unhandled diagnostic message: ${message.runtimeType}");
   }
+
+  DiagnosticMessage _convertMessage(fe.DiagnosticMessage message) {
+    Spannable span = _getSpannable(message);
+    String text = fe.getMessageHeaderText(message);
+    return reporter.createMessage(span, MessageKind.GENERIC, {'text': text});
+  }
+
+  List<fe.DiagnosticMessage> relatedInformation =
+      fe.getMessageRelatedInformation(message);
+  DiagnosticMessage mainMessage = _convertMessage(message);
+  List<DiagnosticMessage> infos = relatedInformation != null
+      ? relatedInformation.map(_convertMessage).toList()
+      : const [];
   switch (message.severity) {
     case fe.Severity.internalProblem:
-      throw text;
+      throw mainMessage.message.computeMessage();
     case fe.Severity.error:
-      reporter.reportErrorMessage(span, kind, {'text': text});
+      reporter.reportError(mainMessage, infos);
       break;
     case fe.Severity.warning:
-      reporter.reportWarningMessage(span, kind, {'text': text});
-      break;
-    case fe.Severity.context:
-      reporter.reportInfo(span, kind, {'text': text});
+      reporter.reportWarning(mainMessage, infos);
       break;
     default:
       throw new UnimplementedError('unhandled severity ${message.severity}');
diff --git a/pkg/compiler/lib/src/kernel/kernel_impact.dart b/pkg/compiler/lib/src/kernel/kernel_impact.dart
index c3b4306..4853aab 100644
--- a/pkg/compiler/lib/src/kernel/kernel_impact.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_impact.dart
@@ -3,9 +3,11 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'package:kernel/ast.dart' as ir;
+import 'package:kernel/type_environment.dart' as ir;
 
 import '../common.dart';
 import '../common/names.dart';
+import '../common/resolution.dart';
 import '../common_elements.dart';
 import '../constants/expressions.dart';
 import '../constants/values.dart';
@@ -15,6 +17,7 @@
 import '../ir/scope.dart';
 import '../ir/static_type.dart';
 import '../ir/impact.dart';
+import '../ir/impact_data.dart';
 import '../ir/util.dart';
 import '../js_backend/annotations.dart';
 import '../js_backend/native_data.dart';
@@ -27,7 +30,9 @@
 import '../universe/world_builder.dart';
 import 'element_map.dart';
 
-class KernelImpactBuilder extends ImpactBuilder {
+/// Visitor that computes the world impact of a member.
+class KernelImpactBuilder extends ImpactBuilderBase
+    with KernelImpactRegistryMixin {
   final ResolutionWorldImpactBuilder impactBuilder;
   final KernelToElementMap elementMap;
   final DiagnosticReporter reporter;
@@ -50,6 +55,47 @@
 
   bool get inferEffectivelyFinalVariableTypes =>
       !_annotations.contains(PragmaAnnotation.disableFinal);
+}
+
+/// Converts a [ImpactData] object based on kernel to the corresponding
+/// [ResolutionImpact] based on the K model.
+class KernelImpactConverter extends KernelImpactRegistryMixin {
+  final ResolutionWorldImpactBuilder impactBuilder;
+  final KernelToElementMap elementMap;
+  final DiagnosticReporter reporter;
+  final CompilerOptions _options;
+  final MemberEntity currentMember;
+
+  KernelImpactConverter(
+      this.elementMap, this.currentMember, this.reporter, this._options)
+      : this.impactBuilder =
+            new ResolutionWorldImpactBuilder('${currentMember}');
+
+  ir.TypeEnvironment get typeEnvironment => elementMap.typeEnvironment;
+
+  CommonElements get commonElements => elementMap.commonElements;
+
+  NativeBasicData get _nativeBasicData => elementMap.nativeBasicData;
+
+  /// Converts a [ImpactData] object based on kernel to the corresponding
+  /// [ResolutionImpact] based on the K model.
+  ResolutionImpact convert(ImpactData impactData) {
+    impactData.apply(this);
+    return impactBuilder;
+  }
+}
+
+/// [ImpactRegistry] that converts kernel based impact data to world impact
+/// object based on the K model.
+abstract class KernelImpactRegistryMixin implements ImpactRegistry {
+  CompilerOptions get _options;
+  DiagnosticReporter get reporter;
+  KernelToElementMap get elementMap;
+  MemberEntity get currentMember;
+  ResolutionWorldImpactBuilder get impactBuilder;
+  ir.TypeEnvironment get typeEnvironment;
+  CommonElements get commonElements;
+  NativeBasicData get _nativeBasicData;
 
   Object _computeReceiverConstraint(
       ir.DartType receiverType, ClassRelation relation) {
@@ -72,9 +118,9 @@
     }
   }
 
-  List<DartType> _getTypeArguments(ir.Arguments arguments) {
-    if (arguments.types.isEmpty) return null;
-    return arguments.types.map(elementMap.getDartType).toList();
+  List<DartType> _getTypeArguments(List<ir.DartType> types) {
+    if (types.isEmpty) return null;
+    return types.map(elementMap.getDartType).toList();
   }
 
   @override
@@ -83,9 +129,7 @@
   }
 
   @override
-  void handleField(ir.Field field) {
-    super.handleField(field);
-
+  void registerFieldNode(ir.Field field) {
     if (field.isInstanceMember &&
         elementMap.isNativeClass(field.enclosingClass)) {
       MemberEntity member = elementMap.getMember(field);
@@ -98,7 +142,7 @@
   }
 
   @override
-  void handleConstructor(ir.Constructor constructor) {
+  void registerConstructorNode(ir.Constructor constructor) {
     MemberEntity member = elementMap.getMember(constructor);
     if (constructor.isExternal && !commonElements.isForeignHelper(member)) {
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
@@ -135,9 +179,7 @@
   }
 
   @override
-  void handleProcedure(ir.Procedure procedure) {
-    super.handleProcedure(procedure);
-
+  void registerProcedureNode(ir.Procedure procedure) {
     MemberEntity member = elementMap.getMember(procedure);
     if (procedure.isExternal && !commonElements.isForeignHelper(member)) {
       bool isJsInterop = _nativeBasicData.isJsInteropMember(member);
@@ -179,29 +221,43 @@
 
   @override
   void registerListLiteral(ir.DartType elementType,
-      {bool isConstant, bool isEmpty}) {
+      {bool isConst, bool isEmpty}) {
     impactBuilder.registerListLiteral(new ListLiteralUse(
         commonElements.listType(elementMap.getDartType(elementType)),
-        isConstant: isConstant,
+        isConstant: isConst,
         isEmpty: isEmpty));
   }
 
   @override
+  void registerSetLiteral(ir.DartType elementType,
+      {bool isConst, bool isEmpty}) {
+    // TODO(johnniwinther,fishythefish): Register set literals.
+  }
+
+  @override
   void registerMapLiteral(ir.DartType keyType, ir.DartType valueType,
-      {bool isConstant, bool isEmpty}) {
+      {bool isConst, bool isEmpty}) {
     impactBuilder.registerMapLiteral(new MapLiteralUse(
         commonElements.mapType(
             elementMap.getDartType(keyType), elementMap.getDartType(valueType)),
-        isConstant: isConstant,
+        isConstant: isConst,
         isEmpty: isEmpty));
   }
 
   @override
-  void registerNew(ir.Member target, ir.InterfaceType type,
-      ir.Arguments arguments, ir.LibraryDependency import,
+  void registerNew(
+      ir.Member target,
+      ir.InterfaceType type,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
+      ir.LibraryDependency import,
       {bool isConst}) {
     ConstructorEntity constructor = elementMap.getConstructor(target);
-    CallStructure callStructure = elementMap.getCallStructure(arguments);
+    CallStructure callStructure = new CallStructure(
+        positionalArguments + namedArguments.length,
+        namedArguments,
+        typeArguments.length);
     ImportEntity deferredImport = elementMap.getImport(import);
     impactBuilder.registerStaticUse(isConst
         ? new StaticUse.constConstructorInvoke(constructor, callStructure,
@@ -223,10 +279,14 @@
       // We need to register the external constructor as live below, so don't
       // return here.
     }
+  }
 
-    if (isConst && commonElements.isSymbolConstructor(constructor)) {
+  void registerConstConstructorInvocationNode(ir.ConstructorInvocation node) {
+    assert(node.isConst);
+    ConstructorEntity constructor = elementMap.getConstructor(node.target);
+    if (commonElements.isSymbolConstructor(constructor)) {
       ConstantValue value =
-          elementMap.getConstantValue(arguments.positional.first);
+          elementMap.getConstantValue(node.arguments.positional.first);
       if (!value.isString) {
         // TODO(het): Get the actual span for the Symbol constructor argument
         reporter.reportErrorMessage(
@@ -242,7 +302,11 @@
 
   @override
   void registerSuperInitializer(
-      ir.Constructor source, ir.Constructor target, ir.Arguments arguments) {
+      ir.Constructor source,
+      ir.Constructor target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
     // TODO(johnniwinther): Maybe rewrite `node.target` to point to a
     // synthesized unnamed mixin constructor when needed. This would require us
     // to consider impact building a required pre-step for inference and
@@ -250,29 +314,36 @@
     ConstructorEntity constructor =
         elementMap.getSuperConstructor(source, target);
     impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
-        constructor, elementMap.getCallStructure(arguments)));
+        constructor,
+        new CallStructure(positionalArguments + namedArguments.length,
+            namedArguments, typeArguments.length)));
   }
 
   @override
-  void registerStaticInvocation(ir.Procedure procedure, ir.Arguments arguments,
+  void registerStaticInvocation(
+      ir.Procedure procedure,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments,
       ir.LibraryDependency import) {
     FunctionEntity target = elementMap.getMethod(procedure);
-    CallStructure callStructure = elementMap.getCallStructure(arguments);
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+    CallStructure callStructure = new CallStructure(
+        positionalArguments + namedArguments.length,
+        namedArguments,
+        typeArguments.length);
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     if (commonElements.isExtractTypeArguments(target)) {
-      _handleExtractTypeArguments(target, typeArguments, callStructure);
+      _handleExtractTypeArguments(target, dartTypeArguments, callStructure);
       return;
     } else {
       ImportEntity deferredImport = elementMap.getImport(import);
       impactBuilder.registerStaticUse(new StaticUse.staticInvoke(
-          target, callStructure, typeArguments, deferredImport));
+          target, callStructure, dartTypeArguments, deferredImport));
     }
   }
 
-  void handleStaticInvocation(ir.StaticInvocation node,
-      ArgumentTypes argumentTypes, ir.DartType returnType) {
-    super.handleStaticInvocation(node, argumentTypes, returnType);
-
+  @override
+  void registerStaticInvocationNode(ir.StaticInvocation node) {
     switch (elementMap.getForeignKind(node)) {
       case ForeignKind.JS:
         impactBuilder
@@ -346,13 +417,17 @@
   }
 
   @override
-  void registerSuperInvocation(ir.Name name, ir.Arguments arguments) {
+  void registerSuperInvocation(ir.Name name, int positionalArguments,
+      List<String> namedArguments, List<ir.DartType> typeArguments) {
     FunctionEntity method =
         elementMap.getSuperMember(currentMember, name, setter: false);
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     if (method != null) {
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
-          method, elementMap.getCallStructure(arguments), typeArguments));
+          method,
+          new CallStructure(positionalArguments + namedArguments.length,
+              namedArguments, typeArguments.length),
+          dartTypeArguments));
     } else {
       impactBuilder.registerStaticUse(new StaticUse.superInvoke(
           elementMap.getSuperNoSuchMethod(currentMember.enclosingClass),
@@ -399,50 +474,74 @@
 
   @override
   void registerLocalFunctionInvocation(
-      ir.FunctionDeclaration localFunction, ir.Arguments arguments) {
-    CallStructure callStructure = elementMap.getCallStructure(arguments);
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+      ir.FunctionDeclaration localFunction,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    CallStructure callStructure = new CallStructure(
+        positionalArguments + namedArguments.length,
+        namedArguments,
+        typeArguments.length);
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     // Invocation of a local function. No need for dynamic use, but
     // we need to track the type arguments.
     impactBuilder.registerStaticUse(new StaticUse.closureCall(
         elementMap.getLocalFunction(localFunction),
         callStructure,
-        typeArguments));
+        dartTypeArguments));
     // TODO(johnniwinther): Yet, alas, we need the dynamic use for now. Remove
     // this when kernel adds an `isFunctionCall` flag to
     // [ir.MethodInvocation].
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
-        callStructure.callSelector, null, typeArguments));
+        callStructure.callSelector, null, dartTypeArguments));
   }
 
   @override
-  void registerDynamicInvocation(ir.DartType receiverType,
-      ClassRelation relation, ir.Name name, ir.Arguments arguments) {
-    Selector selector = elementMap.getInvocationSelector(name, arguments);
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+  void registerDynamicInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Name name,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    Selector selector = elementMap.getInvocationSelector(
+        name, positionalArguments, namedArguments, typeArguments.length);
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(selector,
-        _computeReceiverConstraint(receiverType, relation), typeArguments));
+        _computeReceiverConstraint(receiverType, relation), dartTypeArguments));
   }
 
   @override
   void registerFunctionInvocation(
-      ir.DartType receiverType, ir.Arguments arguments) {
-    CallStructure callStructure = elementMap.getCallStructure(arguments);
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+      ir.DartType receiverType,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    CallStructure callStructure = new CallStructure(
+        positionalArguments + namedArguments.length,
+        namedArguments,
+        typeArguments.length);
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
         callStructure.callSelector,
         _computeReceiverConstraint(receiverType, ClassRelation.subtype),
-        typeArguments));
+        dartTypeArguments));
   }
 
   @override
-  void registerInstanceInvocation(ir.DartType receiverType,
-      ClassRelation relation, ir.Member target, ir.Arguments arguments) {
-    List<DartType> typeArguments = _getTypeArguments(arguments);
+  void registerInstanceInvocation(
+      ir.DartType receiverType,
+      ClassRelation relation,
+      ir.Member target,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
+    List<DartType> dartTypeArguments = _getTypeArguments(typeArguments);
     impactBuilder.registerDynamicUse(new ConstrainedDynamicUse(
-        elementMap.getInvocationSelector(target.name, arguments),
+        elementMap.getInvocationSelector(target.name, positionalArguments,
+            namedArguments, typeArguments.length),
         _computeReceiverConstraint(receiverType, relation),
-        typeArguments));
+        dartTypeArguments));
   }
 
   @override
@@ -481,7 +580,8 @@
         const <DartType>[]));
   }
 
-  void handleRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
+  @override
+  void registerRuntimeTypeUse(ir.PropertyGet node, RuntimeTypeUseKind kind,
       ir.DartType receiverType, ir.DartType argumentType) {
     DartType receiverDartType = elementMap.getDartType(receiverType);
     DartType argumentDartType =
@@ -562,7 +662,6 @@
   }
 
   @override
-  @override
   void registerThrow() {
     impactBuilder.registerFeature(Feature.THROW_EXPRESSION);
   }
@@ -619,10 +718,15 @@
 
   @override
   void registerRedirectingInitializer(
-      ir.Constructor constructor, ir.Arguments arguments) {
+      ir.Constructor constructor,
+      int positionalArguments,
+      List<String> namedArguments,
+      List<ir.DartType> typeArguments) {
     ConstructorEntity target = elementMap.getConstructor(constructor);
     impactBuilder.registerStaticUse(new StaticUse.superConstructorInvoke(
-        target, elementMap.getCallStructure(arguments)));
+        target,
+        new CallStructure(positionalArguments + namedArguments.length,
+            namedArguments, typeArguments.length)));
   }
 
   @override
@@ -633,7 +737,7 @@
   }
 
   @override
-  void handleSwitchStatement(ir.SwitchStatement node) {
+  void registerSwitchStatementNode(ir.SwitchStatement node) {
     // TODO(32557): Remove this when issue 32557 is fixed.
     ir.TreeNode firstCase;
     DartType firstCaseType;
diff --git a/pkg/compiler/lib/src/kernel/kernel_world.dart b/pkg/compiler/lib/src/kernel/kernel_world.dart
index af7cde7..1167b48 100644
--- a/pkg/compiler/lib/src/kernel/kernel_world.dart
+++ b/pkg/compiler/lib/src/kernel/kernel_world.dart
@@ -16,6 +16,7 @@
 import '../js_backend/runtime_types.dart';
 import '../options.dart';
 import '../universe/class_hierarchy.dart';
+import '../universe/member_usage.dart';
 import '../universe/resolution_world_builder.dart';
 import '../world.dart';
 
@@ -46,7 +47,7 @@
 
   final Iterable<ClassEntity> liveNativeClasses;
 
-  final Iterable<MemberEntity> processedMembers;
+  final Map<MemberEntity, MemberUsage> liveMemberUsage;
 
   final ClassHierarchy classHierarchy;
 
@@ -70,7 +71,7 @@
       this.liveNativeClasses,
       this.liveInstanceMembers,
       this.assignedInstanceMembers,
-      this.processedMembers,
+      this.liveMemberUsage,
       this.mixinUses,
       this.typesImplementedBySubclasses,
       this.classHierarchy,
@@ -86,4 +87,7 @@
   bool isImplemented(ClassEntity cls) {
     return _implementedClasses.contains(cls);
   }
+
+  /// Needed for testing.
+  Iterable<MemberEntity> get processedMembers => liveMemberUsage.keys;
 }
diff --git a/pkg/compiler/lib/src/native/resolver.dart b/pkg/compiler/lib/src/native/resolver.dart
index 31936b5..f621d9e 100644
--- a/pkg/compiler/lib/src/native/resolver.dart
+++ b/pkg/compiler/lib/src/native/resolver.dart
@@ -72,6 +72,12 @@
       // using a JS-call.
       _setNativeName(element);
       return true;
+    } else {
+      String name = _findJsNameFromAnnotation(element);
+      if (name != null) {
+        failedAt(element,
+            '@JSName(...) annotation is not supported for static fields.');
+      }
     }
     return false;
   }
diff --git a/pkg/compiler/lib/src/serialization/abstract_sink.dart b/pkg/compiler/lib/src/serialization/abstract_sink.dart
index 07116be..d63db8f 100644
--- a/pkg/compiler/lib/src/serialization/abstract_sink.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_sink.dart
@@ -203,7 +203,7 @@
   void writeInt(int value) {
     assert(value != null);
     assert(value >= 0 && value >> 30 == 0);
-    _writeDataKind(DataKind.int);
+    _writeDataKind(DataKind.uint30);
     _writeIntInternal(value);
   }
 
@@ -338,6 +338,31 @@
     _writeConstant(value);
   }
 
+  @override
+  void writeDoubleValue(double value) {
+    _writeDataKind(DataKind.double);
+    _writeDoubleValue(value);
+  }
+
+  void _writeDoubleValue(double value) {
+    ByteData data = new ByteData(8);
+    data.setFloat64(0, value);
+    writeInt(data.getUint16(0));
+    writeInt(data.getUint16(2));
+    writeInt(data.getUint16(4));
+    writeInt(data.getUint16(6));
+  }
+
+  @override
+  void writeIntegerValue(int value) {
+    _writeDataKind(DataKind.int);
+    _writeBigInt(new BigInt.from(value));
+  }
+
+  void _writeBigInt(BigInt value) {
+    writeString(value.toString());
+  }
+
   void _writeConstant(ConstantValue value) {
     _writeEnumInternal(value.kind);
     switch (value.kind) {
@@ -347,16 +372,11 @@
         break;
       case ConstantValueKind.INT:
         IntConstantValue constant = value;
-        writeString(constant.intValue.toString());
+        _writeBigInt(constant.intValue);
         break;
       case ConstantValueKind.DOUBLE:
         DoubleConstantValue constant = value;
-        ByteData data = new ByteData(8);
-        data.setFloat64(0, constant.doubleValue);
-        writeInt(data.getUint16(0));
-        writeInt(data.getUint16(2));
-        writeInt(data.getUint16(4));
-        writeInt(data.getUint16(6));
+        _writeDoubleValue(constant.doubleValue);
         break;
       case ConstantValueKind.STRING:
         StringConstantValue constant = value;
diff --git a/pkg/compiler/lib/src/serialization/abstract_source.dart b/pkg/compiler/lib/src/serialization/abstract_source.dart
index 28fdf8a..792ae23 100644
--- a/pkg/compiler/lib/src/serialization/abstract_source.dart
+++ b/pkg/compiler/lib/src/serialization/abstract_source.dart
@@ -393,7 +393,7 @@
 
   @override
   int readInt() {
-    _checkDataKind(DataKind.int);
+    _checkDataKind(DataKind.uint30);
     return _readIntInternal();
   }
 
@@ -409,6 +409,29 @@
     return _readConstant();
   }
 
+  double readDoubleValue() {
+    _checkDataKind(DataKind.double);
+    return _readDoubleValue();
+  }
+
+  double _readDoubleValue() {
+    ByteData data = new ByteData(8);
+    data.setUint16(0, readInt());
+    data.setUint16(2, readInt());
+    data.setUint16(4, readInt());
+    data.setUint16(6, readInt());
+    return data.getFloat64(0);
+  }
+
+  int readIntegerValue() {
+    _checkDataKind(DataKind.int);
+    return _readBigInt().toInt();
+  }
+
+  BigInt _readBigInt() {
+    return BigInt.parse(readString());
+  }
+
   ConstantValue _readConstant() {
     ConstantValueKind kind = _readEnumInternal(ConstantValueKind.values);
     switch (kind) {
@@ -416,15 +439,10 @@
         bool value = readBool();
         return new BoolConstantValue(value);
       case ConstantValueKind.INT:
-        BigInt value = BigInt.parse(readString());
+        BigInt value = _readBigInt();
         return new IntConstantValue(value);
       case ConstantValueKind.DOUBLE:
-        ByteData data = new ByteData(8);
-        data.setUint16(0, readInt());
-        data.setUint16(2, readInt());
-        data.setUint16(4, readInt());
-        data.setUint16(6, readInt());
-        double value = data.getFloat64(0);
+        double value = _readDoubleValue();
         return new DoubleConstantValue(value);
       case ConstantValueKind.STRING:
         String value = readString();
diff --git a/pkg/compiler/lib/src/serialization/helpers.dart b/pkg/compiler/lib/src/serialization/helpers.dart
index a75b7e3..d6db5f2 100644
--- a/pkg/compiler/lib/src/serialization/helpers.dart
+++ b/pkg/compiler/lib/src/serialization/helpers.dart
@@ -10,7 +10,7 @@
 /// and deserialization.
 enum DataKind {
   bool,
-  int,
+  uint30,
   string,
   enumValue,
   uri,
@@ -25,6 +25,8 @@
   sourceSpan,
   constant,
   import,
+  double,
+  int,
 }
 
 /// Enum used for identifying the enclosing entity of a member in serialization.
diff --git a/pkg/compiler/lib/src/serialization/mixins.dart b/pkg/compiler/lib/src/serialization/mixins.dart
index eb86a2a..be891a1 100644
--- a/pkg/compiler/lib/src/serialization/mixins.dart
+++ b/pkg/compiler/lib/src/serialization/mixins.dart
@@ -313,6 +313,36 @@
     }
     return map;
   }
+
+  @override
+  List<ir.DartType> readDartTypeNodes({bool emptyAsNull: false}) {
+    int count = readInt();
+    if (count == 0 && emptyAsNull) return null;
+    List<ir.DartType> list = new List<ir.DartType>(count);
+    for (int i = 0; i < count; i++) {
+      list[i] = readDartTypeNode();
+    }
+    return list;
+  }
+
+  @override
+  ir.Name readName() {
+    String text = readString();
+    ir.Library library = readValueOrNull(readLibraryNode);
+    return new ir.Name(text, library);
+  }
+
+  @override
+  ir.LibraryDependency readLibraryDependencyNode() {
+    ir.Library library = readLibraryNode();
+    int index = readInt();
+    return library.dependencies[index];
+  }
+
+  @override
+  ir.LibraryDependency readLibraryDependencyNodeOrNull() {
+    return readValueOrNull(readLibraryDependencyNode);
+  }
 }
 
 /// Mixin that implements all convenience methods of [DataSink].
@@ -643,4 +673,36 @@
       });
     }
   }
+
+  @override
+  void writeDartTypeNodes(Iterable<ir.DartType> values,
+      {bool allowNull: false}) {
+    if (values == null) {
+      assert(allowNull);
+      writeInt(0);
+    } else {
+      writeInt(values.length);
+      for (ir.DartType value in values) {
+        writeDartTypeNode(value);
+      }
+    }
+  }
+
+  @override
+  void writeName(ir.Name value) {
+    writeString(value.name);
+    writeValueOrNull(value.library, writeLibraryNode);
+  }
+
+  @override
+  void writeLibraryDependencyNode(ir.LibraryDependency value) {
+    ir.Library library = value.parent;
+    writeLibraryNode(library);
+    writeInt(library.dependencies.indexOf(value));
+  }
+
+  @override
+  void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value) {
+    writeValueOrNull(value, writeLibraryDependencyNode);
+  }
 }
diff --git a/pkg/compiler/lib/src/serialization/serialization.dart b/pkg/compiler/lib/src/serialization/serialization.dart
index 3348edd..c4dab5a 100644
--- a/pkg/compiler/lib/src/serialization/serialization.dart
+++ b/pkg/compiler/lib/src/serialization/serialization.dart
@@ -75,7 +75,7 @@
   /// Writes the boolean [value] to this data sink.
   void writeBool(bool value);
 
-  /// Writes the non-negative integer [value] to this data sink.
+  /// Writes the non-negative 30 bit integer [value] to this data sink.
   void writeInt(int value);
 
   /// Writes the potentially `null` non-negative [value] to this data sink.
@@ -137,6 +137,16 @@
   /// [DataSource.readMemberNodes].
   void writeMemberNodes(Iterable<ir.Member> values, {bool allowNull: false});
 
+  /// Writes a kernel name node to this data sink.
+  void writeName(ir.Name value);
+
+  /// Writes a kernel library dependency node [value] to this data sink.
+  void writeLibraryDependencyNode(ir.LibraryDependency value);
+
+  /// Writes a potentially `null` kernel library dependency node [value] to
+  /// this data sink.
+  void writeLibraryDependencyNodeOrNull(ir.LibraryDependency value);
+
   /// Writes a reference to the kernel tree node [value] to this data sink.
   void writeTreeNode(ir.TreeNode value);
 
@@ -191,6 +201,14 @@
   /// `true`, [value] is allowed to be `null`.
   void writeDartTypeNode(ir.DartType value, {bool allowNull: false});
 
+  /// Writes the kernel type node [values] to this data sink. If [allowNull] is
+  /// `true`, [values] is allowed to be `null`.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSource.readDartTypeNodes].
+  void writeDartTypeNodes(Iterable<ir.DartType> values,
+      {bool allowNull: false});
+
   /// Writes the source span [value] to this data sink.
   void writeSourceSpan(SourceSpan value);
 
@@ -313,6 +331,15 @@
   void writeConstantMap<V>(Map<ConstantValue, V> map, void f(V value),
       {bool allowNull: false});
 
+  /// Writes a double value to this data sink.
+  void writeDoubleValue(double value);
+
+  /// Writes an integer of arbitrary value to this data sink.
+  ///
+  /// This is should only when the value is not known to be a non-negative
+  /// 30 bit integer. Otherwise [writeInt] should be used.
+  void writeIntegerValue(int value);
+
   /// Writes the import [value] to this data sink.
   void writeImport(ImportEntity value);
 
@@ -380,7 +407,7 @@
   /// Reads a boolean value from this data source.
   bool readBool();
 
-  /// Reads a non-negative integer value from this data source.
+  /// Reads a non-negative 30 bit integer value from this data source.
   int readInt();
 
   /// Reads a potentially `null` non-negative integer value from this data
@@ -448,6 +475,16 @@
   List<ir.Member> readMemberNodes<E extends ir.Member>(
       {bool emptyAsNull: false});
 
+  /// Reads a kernel name node from this data source.
+  ir.Name readName();
+
+  /// Reads a kernel library dependency node from this data source.
+  ir.LibraryDependency readLibraryDependencyNode();
+
+  /// Reads a potentially `null` kernel library dependency node from this data
+  /// source.
+  ir.LibraryDependency readLibraryDependencyNodeOrNull();
+
   /// Reads a reference to a kernel tree node from this data source.
   ir.TreeNode readTreeNode();
 
@@ -497,6 +534,13 @@
   /// returned type is allowed to be `null`.
   ir.DartType readDartTypeNode({bool allowNull: false});
 
+  /// Reads a list of kernel type nodes from this data source. If [emptyAsNull]
+  /// is `true`, `null` is returned instead of an empty list.
+  ///
+  /// This is a convenience method to be used together with
+  /// [DataSink.writeDartTypeNodes].
+  List<ir.DartType> readDartTypeNodes({bool emptyAsNull: false});
+
   /// Reads a source span from this data source.
   SourceSpan readSourceSpan();
 
@@ -582,6 +626,15 @@
   /// Reads a constant value from this data source.
   ConstantValue readConstant();
 
+  /// Reads a double value from this data source.
+  double readDoubleValue();
+
+  /// Reads an integer of arbitrary value from this data source.
+  ///
+  /// This is should only when the value is not known to be a non-negative
+  /// 30 bit integer. Otherwise [readInt] should be used.
+  int readIntegerValue();
+
   /// Reads a list of constant values from this data source. If [emptyAsNull] is
   /// `true`, `null` is returned instead of an empty list.
   ///
diff --git a/pkg/compiler/lib/src/ssa/builder_kernel.dart b/pkg/compiler/lib/src/ssa/builder_kernel.dart
index 1500ab2..e8d55ba 100644
--- a/pkg/compiler/lib/src/ssa/builder_kernel.dart
+++ b/pkg/compiler/lib/src/ssa/builder_kernel.dart
@@ -31,7 +31,7 @@
 import '../js_backend/backend.dart' show FunctionInlineCache, JavaScriptBackend;
 import '../js_backend/runtime_types.dart' show RuntimeTypesSubstitutions;
 import '../js_emitter/js_emitter.dart' show NativeEmitter;
-import '../js_model/locals.dart' show forEachOrderedParameter, JumpVisitor;
+import '../js_model/locals.dart' show JumpVisitor;
 import '../js_model/elements.dart' show JGeneratorBody;
 import '../js_model/element_map.dart';
 import '../js_model/js_strategy.dart';
@@ -63,6 +63,8 @@
   final MemberEntity member;
   final AsyncMarker asyncMarker;
   final KernelToLocalsMap localsMap;
+  // [ir.Let] and [ir.LocalInitializer] bindings.
+  final Map<ir.VariableDeclaration, HInstruction> letBindings;
   final KernelToTypeInferenceMap typeInferenceMap;
   final SourceInformationBuilder sourceInformationBuilder;
   final StaticTypeProvider staticTypeProvider;
@@ -72,6 +74,7 @@
       this.member,
       this.asyncMarker,
       this.localsMap,
+      this.letBindings,
       this.typeInferenceMap,
       this.sourceInformationBuilder,
       this.staticTypeProvider);
@@ -115,10 +118,6 @@
 
   final NativeEmitter nativeEmitter;
 
-  // [ir.Let] and [ir.LocalInitializer] bindings.
-  final Map<ir.VariableDeclaration, HInstruction> letBindings =
-      <ir.VariableDeclaration, HInstruction>{};
-
   /// True if we are visiting the expression of a throw statement; we assume
   /// this is a slow path.
   bool _inExpressionOfThrow = false;
@@ -160,6 +159,9 @@
 
   KernelToLocalsMap get localsMap => _currentFrame.localsMap;
 
+  Map<ir.VariableDeclaration, HInstruction> get letBindings =>
+      _currentFrame.letBindings;
+
   JCommonElements get _commonElements => _elementMap.commonElements;
 
   KernelToTypeInferenceMap get _typeInferenceMap =>
@@ -192,6 +194,7 @@
         member,
         asyncMarker,
         closedWorld.globalLocalsMap.getLocalsMap(member),
+        {},
         new KernelToTypeInferenceMapImpl(member, globalInferenceResults),
         _currentFrame != null
             ? _currentFrame.sourceInformationBuilder
@@ -360,7 +363,9 @@
       graph.entry.addBefore(graph.entry.last, parameter);
       HInstruction value = typeBuilder.potentiallyCheckOrTrustTypeOfParameter(
           parameter, _getDartTypeIfValid(node.type));
-      add(new HFieldSet(abstractValueDomain, field, thisInstruction, value));
+      if (!closedWorld.elidedFields.contains(field)) {
+        add(new HFieldSet(abstractValueDomain, field, thisInstruction, value));
+      }
     } else {
       if (node.initializer != null) {
         node.initializer.accept(this);
@@ -438,25 +443,31 @@
   void _addFunctionTypeVariablesIfNeeded(MemberEntity member) {
     if (member is! FunctionEntity) return;
 
+    FunctionEntity function = member;
     List<TypeVariableType> typeVariables =
-        _elementMap.elementEnvironment.getFunctionTypeVariables(member);
+        _elementMap.elementEnvironment.getFunctionTypeVariables(function);
     if (typeVariables.isEmpty) {
       return;
     }
-    bool needsTypeArguments = rtiNeed.methodNeedsTypeArguments(member);
-    typeVariables.forEach((TypeVariableType typeVariableType) {
+    bool needsTypeArguments = rtiNeed.methodNeedsTypeArguments(function);
+    bool elideTypeParameters = function.parameterStructure.typeParameters == 0;
+    for (TypeVariableType typeVariable
+        in _elementMap.elementEnvironment.getFunctionTypeVariables(function)) {
       HInstruction param;
-      if (needsTypeArguments) {
-        param = addParameter(
-            typeVariableType.element, abstractValueDomain.nonNullType);
+      if (elideTypeParameters) {
+        // Add elided type parameters.
+        param = _computeTypeArgumentDefaultValue(function, typeVariable);
+      } else if (needsTypeArguments) {
+        param =
+            addParameter(typeVariable.element, abstractValueDomain.nonNullType);
       } else {
         // Unused, so bind to `dynamic`.
         param = graph.addConstantNull(closedWorld);
       }
-      Local local = localsHandler.getTypeVariableAsLocal(typeVariableType);
+      Local local = localsHandler.getTypeVariableAsLocal(typeVariable);
       localsHandler.directLocals[local] = param;
       functionTypeParameterLocals.add(local);
-    });
+    }
   }
 
   List<Local> functionTypeParameterLocals = <Local>[];
@@ -495,7 +506,9 @@
 
     if (_inliningStack.isEmpty) {
       openFunction(constructor,
-          functionNode: node.function, checks: TargetChecks.none);
+          functionNode: node.function,
+          parameterStructure: constructor.parameterStructure,
+          checks: TargetChecks.none);
     }
 
     // [constructorData.fieldValues] accumulates the field initializer values,
@@ -511,7 +524,7 @@
     InterfaceType thisType = _elementMap.elementEnvironment.getThisType(cls);
     List<FieldEntity> fields = <FieldEntity>[];
     _worldBuilder.forEachInstanceField(cls,
-        (ClassEntity enclosingClass, FieldEntity member) {
+        (ClassEntity enclosingClass, FieldEntity member, {bool isElided}) {
       HInstruction value = constructorData.fieldValues[member];
       if (value == null) {
         assert(
@@ -520,11 +533,13 @@
                 reporter.hasReportedError,
             'No initializer value for field ${member}');
       } else {
-        fields.add(member);
-        DartType type = _elementMap.elementEnvironment.getFieldType(member);
-        type = localsHandler.substInContext(type);
-        constructorArguments.add(
-            typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(value, type));
+        if (!isElided) {
+          fields.add(member);
+          DartType type = _elementMap.elementEnvironment.getFieldType(member);
+          type = localsHandler.substInContext(type);
+          constructorArguments.add(
+              typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(value, type));
+        }
       }
     });
 
@@ -602,7 +617,12 @@
       inlinedFrom(
           inlinedConstructor, _sourceInformationBuilder.buildCall(body, body),
           () {
-        void handleParameter(ir.VariableDeclaration node) {
+        ConstructorBodyEntity constructorBody =
+            _elementMap.getConstructorBody(body);
+
+        void handleParameter(ir.VariableDeclaration node, {bool isElided}) {
+          if (isElided) return;
+
           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.
@@ -612,21 +632,18 @@
         }
 
         // Provide the parameters to the generative constructor body.
-        body.function.positionalParameters.forEach(handleParameter);
-        body.function.namedParameters.toList()
-          ..sort(namedOrdering)
-          ..forEach(handleParameter);
+        forEachOrderedParameter(_elementMap, constructorBody, handleParameter);
 
         // If there are locals that escape (i.e. mutated in closures), we pass the
         // box to the constructor.
         CapturedScope scopeData =
-            closureDataLookup.getCapturedScope(inlinedConstructor);
+            closureDataLookup.getCapturedScope(constructorBody);
         if (scopeData.requiresContextBox) {
           bodyCallInputs.add(localsHandler.readLocal(scopeData.context));
         }
 
         // Pass type arguments.
-        ClassEntity inlinedConstructorClass = inlinedConstructor.enclosingClass;
+        ClassEntity inlinedConstructorClass = constructorBody.enclosingClass;
         if (closedWorld.rtiNeed
             .classNeedsTypeArguments(inlinedConstructorClass)) {
           InterfaceType thisType = _elementMap.elementEnvironment
@@ -639,8 +656,6 @@
           }
         }
 
-        ConstructorBodyEntity constructorBody =
-            _elementMap.getConstructorBody(body);
         if (!isCustomElement && // TODO(13836): Fix inlining.
             _tryInlineMethod(constructorBody, null, null, bodyCallInputs, null,
                 node, sourceInformation)) {
@@ -717,7 +732,8 @@
   /// [clazz].
   void _collectFieldValues(ir.Class clazz, ConstructorData constructorData) {
     ClassEntity cls = _elementMap.getClass(clazz);
-    _worldBuilder.forEachDirectInstanceField(cls, (FieldEntity field) {
+    _worldBuilder.forEachDirectInstanceField(cls, (FieldEntity field,
+        {bool isElided}) {
       _ensureTypeVariablesForInitializers(
           constructorData, field.enclosingClass);
 
@@ -990,8 +1006,12 @@
 
   /// Builds generative constructor body.
   void buildConstructorBody(ir.Constructor constructor) {
-    openFunction(_elementMap.getConstructorBody(constructor),
-        functionNode: constructor.function, checks: TargetChecks.none);
+    FunctionEntity constructorBody =
+        _elementMap.getConstructorBody(constructor);
+    openFunction(constructorBody,
+        functionNode: constructor.function,
+        parameterStructure: constructorBody.parameterStructure,
+        checks: TargetChecks.none);
     constructor.function.body.accept(this);
     closeFunction();
   }
@@ -1009,7 +1029,9 @@
     // checks.
     // TODO(sra): Instance methods can be generated with reduced checks if
     // called only from non-dynamic call-sites.
-    openFunction(function, functionNode: functionNode);
+    openFunction(function,
+        functionNode: functionNode,
+        parameterStructure: function.parameterStructure);
 
     // If [functionNode] is `operator==` we explicitly add a null check at the
     // beginning of the method. This is to avoid having call sites do the null
@@ -1066,7 +1088,9 @@
   /// 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, functionNode: functionNode);
+    openFunction(function,
+        functionNode: functionNode,
+        parameterStructure: function.parameterStructure);
 
     // Prepare to tail-call the body.
 
@@ -1082,7 +1106,9 @@
       inputs.add(graph.explicitReceiverParameter);
     }
     for (Local local in parameters.keys) {
-      inputs.add(localsHandler.readLocal(local));
+      if (!elidedParameters.contains(local)) {
+        inputs.add(localsHandler.readLocal(local));
+      }
     }
     for (Local local in functionTypeParameterLocals) {
       inputs.add(localsHandler.readLocal(local));
@@ -1130,7 +1156,10 @@
   void buildGeneratorBody(
       JGeneratorBody function, ir.FunctionNode functionNode) {
     FunctionEntity entry = function.function;
-    openFunction(entry, functionNode: functionNode, checks: TargetChecks.none);
+    openFunction(entry,
+        functionNode: functionNode,
+        parameterStructure: function.parameterStructure,
+        checks: TargetChecks.none);
     graph.needsAsyncRewrite = true;
     if (!function.elementType.containsFreeTypeVariables) {
       // We can generate the element type in place
@@ -1178,6 +1207,7 @@
         return;
       }
       HInstruction newParameter = localsHandler.directLocals[local];
+      assert(newParameter != null, "No initial instruction for ${local}.");
       DartType type = _getDartTypeIfValid(variable.type);
 
       if (targetChecks.checkAllParameters ||
@@ -1225,7 +1255,9 @@
     // TODO(johnniwinther): Non-js-interop external functions should
     // throw a runtime error.
     assert(functionNode.body == null);
-    openFunction(function, functionNode: functionNode);
+    openFunction(function,
+        functionNode: functionNode,
+        parameterStructure: function.parameterStructure);
 
     if (closedWorld.nativeData.isNativeMember(targetElement)) {
       nativeEmitter.nativeMethods.add(targetElement);
@@ -1246,7 +1278,7 @@
                 _sourceInformationBuilder.buildGet(functionNode)));
       }
 
-      for (ir.VariableDeclaration param in functionNode.positionalParameters) {
+      void handleParameter(ir.VariableDeclaration param) {
         templateArguments.add('#');
         Local local = localsMap.getLocalVariable(param);
         // Convert Dart function to JavaScript function.
@@ -1265,6 +1297,23 @@
         inputs.add(argument);
       }
 
+      for (int position = 0;
+          position < function.parameterStructure.positionalParameters;
+          position++) {
+        handleParameter(functionNode.positionalParameters[position]);
+      }
+      if (functionNode.namedParameters.isNotEmpty) {
+        List<ir.VariableDeclaration> namedParameters = functionNode
+            .namedParameters
+            // Filter elided parameters.
+            .where((p) =>
+                function.parameterStructure.namedParameters.contains(p.name))
+            .toList();
+        // Sort by file offset to visit parameters in declaration order.
+        namedParameters.sort(nativeOrdering);
+        namedParameters.forEach(handleParameter);
+      }
+
       String arguments = templateArguments.join(',');
 
       // TODO(sra): Use declared type or NativeBehavior type.
@@ -1307,38 +1356,57 @@
   }
 
   void openFunction(MemberEntity member,
-      {ir.FunctionNode functionNode, TargetChecks checks}) {
+      {ir.FunctionNode functionNode,
+      ParameterStructure parameterStructure,
+      TargetChecks checks}) {
     // TODO(sra): Pass from all sites.
     checks ??= TargetChecks.dynamicChecks;
 
-    Map<Local, AbstractValue> parameterMap = <Local, AbstractValue>{};
+    Map<Local, AbstractValue> parameterMap = {};
+    List<ir.VariableDeclaration> elidedParameters = [];
+    Set<Local> elidedParameterSet = new Set();
     if (functionNode != null) {
-      void handleParameter(ir.VariableDeclaration node) {
+      assert(parameterStructure != null);
+
+      void handleParameter(ir.VariableDeclaration node,
+          {bool isOptional, bool isElided}) {
         Local local = localsMap.getLocalVariable(node);
+        if (isElided) {
+          elidedParameters.add(node);
+          elidedParameterSet.add(local);
+        }
         parameterMap[local] =
             _typeInferenceMap.getInferredTypeOfParameter(local);
       }
 
-      functionNode.positionalParameters.forEach(handleParameter);
-      functionNode.namedParameters.toList()
-        ..sort(namedOrdering)
-        ..forEach(handleParameter);
+      forEachOrderedParameterByFunctionNode(
+          functionNode, parameterStructure, handleParameter);
+
       _returnType = _elementMap.getDartType(functionNode.returnType);
     }
 
     HBasicBlock block = graph.addNewBlock();
+    // Create `graph.entry` as an initially empty block. `graph.entry` is
+    // treated specially (holding parameters, local variables and constants)
+    // 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);
+    open(block);
 
     localsHandler.startFunction(
         targetElement,
         closureDataLookup.getScopeInfo(targetElement),
         closureDataLookup.getCapturedScope(targetElement),
         parameterMap,
+        elidedParameterSet,
         _sourceInformationBuilder.buildDeclaration(targetElement),
         isGenerativeConstructorBody: targetElement is ConstructorBodyEntity);
-    close(new HGoto(abstractValueDomain)).addSuccessor(block);
 
-    open(block);
+    for (ir.VariableDeclaration node in elidedParameters) {
+      Local local = localsMap.getLocalVariable(node);
+      localsHandler.updateLocal(local, _defaultValueForParameter(node));
+    }
 
     _addClassTypeVariablesIfNeeded(member);
     _addFunctionTypeVariablesIfNeeded(member);
@@ -1855,8 +1923,15 @@
         _sourceInformationBuilder.buildLoop(node));
 
     void finalizerFunction() {
-      _pushDynamicInvocation(node, null, Selectors.cancel, [streamIterator],
-          const <DartType>[], _sourceInformationBuilder.buildGeneric(node));
+      _pushDynamicInvocation(
+          node,
+          null,
+          Selectors.cancel,
+          [streamIterator],
+          const <DartType>[],
+          _sourceInformationBuilder
+              // ignore:deprecated_member_use_from_same_package
+              .buildGeneric(node));
       add(new HAwait(pop(), abstractValueDomain.dynamicType));
     }
 
@@ -2965,11 +3040,14 @@
           sourceInformation: _sourceInformationBuilder.buildSet(node));
       pop();
     } else {
-      add(new HStaticStore(
-          abstractValueDomain,
-          _elementMap.getMember(staticTarget),
-          typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
-              value, _getDartTypeIfValid(staticTarget.setterType))));
+      MemberEntity target = _elementMap.getMember(staticTarget);
+      if (!closedWorld.elidedFields.contains(target)) {
+        add(new HStaticStore(
+            abstractValueDomain,
+            target,
+            typeBuilder.potentiallyCheckOrTrustTypeOfAssignment(
+                value, _getDartTypeIfValid(staticTarget.setterType))));
+      }
     }
     stack.add(value);
   }
@@ -3190,12 +3268,8 @@
 
         // Visit named arguments in parameter-position order, selecting provided
         // or default value.
-        // TODO(sra): Ensure the stored order is canonical so we don't have to
-        // sort. The old builder uses CallStructure.makeArgumentList which
-        // depends on the old element model.
-        var namedParameters = target.namedParameters.toList()
-          ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) =>
-              a.name.compareTo(b.name));
+        var namedParameters = target.namedParameters.toList();
+        namedParameters.sort(nativeOrdering);
         for (ir.VariableDeclaration parameter in namedParameters) {
           HInstruction value = namedValues[parameter.name];
           values.add(value);
@@ -3259,20 +3333,21 @@
   /// filling in the default argument value.
   List<HInstruction> _visitArgumentsForStaticTarget(
       ir.FunctionNode target,
+      ParameterStructure parameterStructure,
       ir.Arguments arguments,
       List<DartType> typeArguments,
       SourceInformation sourceInformation) {
     // Visit arguments in source order, then re-order and fill in defaults.
-    var values = _visitPositionalArguments(arguments);
+    List<HInstruction> values = _visitPositionalArguments(arguments);
 
-    while (values.length < target.positionalParameters.length) {
+    while (values.length < parameterStructure.positionalParameters) {
       ir.VariableDeclaration parameter =
           target.positionalParameters[values.length];
       values.add(_defaultValueForParameter(parameter));
     }
 
-    if (target.namedParameters.isNotEmpty) {
-      var namedValues = <String, HInstruction>{};
+    if (parameterStructure.namedParameters.isNotEmpty) {
+      Map<String, HInstruction> namedValues = {};
       for (ir.NamedExpression argument in arguments.named) {
         argument.value.accept(this);
         namedValues[argument.name] = pop();
@@ -3283,9 +3358,11 @@
       // TODO(sra): Ensure the stored order is canonical so we don't have to
       // sort. The old builder uses CallStructure.makeArgumentList which depends
       // on the old element model.
-      var namedParameters = target.namedParameters.toList()
-        ..sort((ir.VariableDeclaration a, ir.VariableDeclaration b) =>
-            a.name.compareTo(b.name));
+      List<ir.VariableDeclaration> namedParameters = target.namedParameters
+          // Filter elided parameters.
+          .where((p) => parameterStructure.namedParameters.contains(p.name))
+          .toList()
+            ..sort(namedOrdering);
       for (ir.VariableDeclaration parameter in namedParameters) {
         HInstruction value = namedValues[parameter.name];
         if (value == null) {
@@ -3344,7 +3421,11 @@
             .isJsInteropMember(function)
         ? _visitArgumentsForNativeStaticTarget(target.function, node.arguments)
         : _visitArgumentsForStaticTarget(
-            target.function, node.arguments, typeArguments, sourceInformation);
+            target.function,
+            function.parameterStructure,
+            node.arguments,
+            typeArguments,
+            sourceInformation);
 
     // Error in the arguments provided. Do not process further.
     if (arguments == null) {
@@ -4280,12 +4361,22 @@
       // Factory constructor that is syntactic sugar for creating a JavaScript
       // object literal.
       ConstructorEntity constructor = element;
-      ParameterStructure params = constructor.parameterStructure;
       int i = 0;
       int positions = 0;
       var filteredArguments = <HInstruction>[];
       var parameterNameMap = new Map<String, js.Expression>();
-      params.namedParameters.forEach((String parameterName) {
+
+      // Note: we don't use `constructor.parameterStructure` here because
+      // we don't elide parameters to js-interop external static targets
+      // (including factory constructors.)
+      // TODO(johnniwinther): can we elide those parameters? This should be
+      // consistent with what we do with instance methods.
+      ir.Procedure node = _elementMap.getMemberDefinition(constructor).node;
+      List<ir.VariableDeclaration> namedParameters =
+          node.function.namedParameters.toList();
+      namedParameters.sort(nativeOrdering);
+      for (ir.VariableDeclaration variable in namedParameters) {
+        String parameterName = variable.name;
         // TODO(jacobr): consider throwing if parameter names do not match
         // names of properties in the class.
         HInstruction argument = arguments[i];
@@ -4295,7 +4386,7 @@
           parameterNameMap[jsName] = new js.InterpolatedExpression(positions++);
         }
         i++;
-      });
+      }
       var codeTemplate =
           new js.Template(null, js.objectLiteral(parameterNameMap));
 
@@ -4378,7 +4469,8 @@
 
     List<HInstruction> capturedVariables = <HInstruction>[];
     _worldBuilder.forEachInstanceField(closureClassEntity,
-        (_, FieldEntity field) {
+        (_, FieldEntity field, {bool isElided}) {
+      if (isElided) return;
       capturedVariables
           .add(localsHandler.readLocal(closureInfo.getLocalForField(field)));
     });
@@ -4615,8 +4707,13 @@
 
     MemberDefinition targetDefinition = _elementMap.getMemberDefinition(member);
     ir.Procedure target = targetDefinition.node;
+    FunctionEntity function = member;
     List<HInstruction> arguments = _visitArgumentsForStaticTarget(
-        target.function, node.arguments, typeArguments, sourceInformation);
+        target.function,
+        function.parameterStructure,
+        node.arguments,
+        typeArguments,
+        sourceInformation);
     _buildInvokeSuper(
         _elementMap.getSelector(node),
         _elementMap.getClass(_containingClass(node)),
@@ -4679,7 +4776,11 @@
     arguments.addAll(closedWorld.nativeData.isJsInteropMember(constructor)
         ? _visitArgumentsForNativeStaticTarget(target.function, node.arguments)
         : _visitArgumentsForStaticTarget(
-            target.function, node.arguments, typeArguments, sourceInformation));
+            target.function,
+            constructor.parameterStructure,
+            node.arguments,
+            typeArguments,
+            sourceInformation));
     if (commonElements.isSymbolConstructor(constructor)) {
       constructor = commonElements.symbolValidatedConstructor;
     }
@@ -5044,8 +5145,7 @@
     }
 
     bool heuristicSayGoodToGo() {
-      // Don't inline recursively, directly or indirectly.
-      if (function == targetElement) return false;
+      // Don't inline recursively,
       if (_inliningStack.any((entry) => entry.function == function)) {
         return false;
       }
@@ -5291,24 +5391,28 @@
         // Pass type variable bounds as type arguments.
         for (TypeVariableType typeVariable in _elementMap.elementEnvironment
             .getFunctionTypeVariables(function)) {
-          DartType bound = _elementMap.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.
-            compiledArguments[compiledArgumentIndex++] =
-                graph.addConstantInt(-2, closedWorld);
-          } else {
-            compiledArguments[compiledArgumentIndex++] =
-                typeBuilder.analyzeTypeArgument(bound, function);
-          }
+          compiledArguments[compiledArgumentIndex++] =
+              _computeTypeArgumentDefaultValue(function, typeVariable);
         }
       }
     }
     return compiledArguments;
   }
 
+  HInstruction _computeTypeArgumentDefaultValue(
+      FunctionEntity function, TypeVariableType typeVariable) {
+    DartType bound = _elementMap.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);
+    }
+  }
+
   /// This method is invoked before inlining the body of [function] into this
   /// [SsaGraphBuilder].
   void _enterInlinedMethod(FunctionEntity function,
@@ -5363,17 +5467,23 @@
     }
 
     bool hasBox = false;
-    forEachOrderedParameter(closedWorld.globalLocalsMap, _elementMap, function,
-        (Local parameter) {
-      if (forGenerativeConstructorBody &&
-          scopeData.isBoxedVariable(parameter)) {
+    KernelToLocalsMap localsMap =
+        closedWorld.globalLocalsMap.getLocalsMap(function);
+    forEachOrderedParameter(_elementMap, function,
+        (ir.VariableDeclaration variable, {bool isElided}) {
+      Local local = localsMap.getLocalVariable(variable);
+      if (isElided) {
+        localsHandler.updateLocal(local, _defaultValueForParameter(variable));
+        return;
+      }
+      if (forGenerativeConstructorBody && scopeData.isBoxedVariable(local)) {
         // The parameter will be a field in the box passed as the last
         // parameter. So no need to have it.
         hasBox = true;
         return;
       }
       HInstruction argument = compiledArguments[argumentIndex++];
-      localsHandler.updateLocal(parameter, argument);
+      localsHandler.updateLocal(local, argument);
     });
 
     if (hasBox) {
@@ -5399,9 +5509,17 @@
       });
     }
     if (rtiNeed.methodNeedsTypeArguments(function)) {
+      bool inlineTypeParameters =
+          function.parameterStructure.typeParameters == 0;
       for (TypeVariableType typeVariable in _elementMap.elementEnvironment
           .getFunctionTypeVariables(function)) {
-        HInstruction argument = compiledArguments[argumentIndex++];
+        HInstruction argument;
+        if (inlineTypeParameters) {
+          // Add inlined type parameters.
+          argument = _computeTypeArgumentDefaultValue(function, typeVariable);
+        } else {
+          argument = compiledArguments[argumentIndex++];
+        }
         localsHandler.updateLocal(
             localsHandler.getTypeVariableAsLocal(typeVariable), argument);
       }
@@ -5525,8 +5643,9 @@
 
     KernelToLocalsMap localsMap =
         closedWorld.globalLocalsMap.getLocalsMap(function);
-    forEachOrderedParameter(closedWorld.globalLocalsMap, _elementMap, function,
-        (Local parameter) {
+    forEachOrderedParameter(_elementMap, function,
+        (ir.VariableDeclaration variable, {bool isElided}) {
+      Local parameter = localsMap.getLocalVariable(variable);
       HInstruction argument = localsHandler.readLocal(parameter);
       DartType type = localsMap.getLocalType(_elementMap, parameter);
       HInstruction checkedOrTrusted;
diff --git a/pkg/compiler/lib/src/ssa/codegen.dart b/pkg/compiler/lib/src/ssa/codegen.dart
index dc941f4..f93696b 100644
--- a/pkg/compiler/lib/src/ssa/codegen.dart
+++ b/pkg/compiler/lib/src/ssa/codegen.dart
@@ -899,7 +899,9 @@
     if (info.catchBlock != null) {
       void register(ClassEntity classElement) {
         if (classElement != null) {
-          _registry.registerInstantiatedClass(classElement);
+          _registry
+              // ignore:deprecated_member_use_from_same_package
+              .registerInstantiatedClass(classElement);
         }
       }
 
@@ -1832,7 +1834,9 @@
         methodName = 'split';
         // Split returns a List, so we make sure the backend knows the
         // list class is instantiated.
-        _registry.registerInstantiatedClass(_commonElements.listClass);
+        _registry
+            // ignore:deprecated_member_use_from_same_package
+            .registerInstantiatedClass(_commonElements.listClass);
       } else if (_nativeData.isNativeMember(target) &&
           target.isFunction &&
           !node.isInterceptedCall) {
@@ -2256,7 +2260,9 @@
     // function expressions. We have to register their use here, as otherwise
     // code for them might not be emitted.
     if (node.element.isClosure) {
-      _registry.registerInstantiatedClass(node.element);
+      _registry
+          // ignore:deprecated_member_use_from_same_package
+          .registerInstantiatedClass(node.element);
     }
     node.instantiatedTypes?.forEach(_registry.registerInstantiation);
     if (node.callMethod != null) {
@@ -2632,7 +2638,9 @@
   }
 
   void visitLiteralList(HLiteralList node) {
-    _registry.registerInstantiatedClass(_commonElements.listClass);
+    _registry
+        // ignore:deprecated_member_use_from_same_package
+        .registerInstantiatedClass(_commonElements.listClass);
     generateArrayLiteral(node);
   }
 
@@ -3195,7 +3203,9 @@
         // We expect only flat types for the INSTANCE representation.
         assert(
             (type as InterfaceType).typeArguments.length == arguments.length);
-        _registry.registerInstantiatedClass(_commonElements.listClass);
+        _registry
+            // ignore:deprecated_member_use_from_same_package
+            .registerInstantiatedClass(_commonElements.listClass);
         push(new js.ArrayInitializer(arguments)
             .withSourceInformation(node.sourceInformation));
     }
diff --git a/pkg/compiler/lib/src/ssa/graph_builder.dart b/pkg/compiler/lib/src/ssa/graph_builder.dart
index 7b78b8c..cf71ede 100644
--- a/pkg/compiler/lib/src/ssa/graph_builder.dart
+++ b/pkg/compiler/lib/src/ssa/graph_builder.dart
@@ -153,9 +153,10 @@
   /// [isAborted].
   bool isReachable = true;
 
-  HParameterValue lastAddedParameter;
+  HLocalValue lastAddedParameter;
 
   Map<Local, HInstruction> parameters = <Local, HInstruction>{};
+  Set<Local> elidedParameters;
 
   HBasicBlock addNewBlock() {
     HBasicBlock block = graph.addNewBlock();
@@ -207,8 +208,11 @@
     current.add(instruction);
   }
 
-  HParameterValue addParameter(Entity parameter, AbstractValue type) {
-    HParameterValue result = new HParameterValue(parameter, type);
+  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 {
diff --git a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
index 18f2ce2..fb3df50 100644
--- a/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
+++ b/pkg/compiler/lib/src/ssa/invoke_dynamic_specializers.dart
@@ -13,6 +13,7 @@
 import '../universe/call_structure.dart';
 import '../universe/selector.dart';
 import '../world.dart' show JClosedWorld;
+import 'logging.dart';
 import 'nodes.dart';
 import 'types.dart';
 
@@ -38,7 +39,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     return null;
   }
 
@@ -120,7 +122,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction receiver = instruction.inputs[1];
     HInstruction index = instruction.inputs[2];
     if (receiver
@@ -142,8 +145,10 @@
         return null;
       }
     }
-    return new HIndexAssign(closedWorld.abstractValueDomain, receiver, index,
-        value, instruction.selector);
+    HIndexAssign converted = new HIndexAssign(closedWorld.abstractValueDomain,
+        receiver, index, value, instruction.selector);
+    log?.registerIndexAssign(instruction, converted);
+    return converted;
   }
 
   /// Returns [true] if [value] meets the requirements for being stored into
@@ -188,13 +193,13 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     if (instruction.inputs[1]
         .isIndexablePrimitive(closedWorld.abstractValueDomain)
         .isPotentiallyFalse) {
       return null;
     }
-    // TODO(johnniwinther): Merge this and the following if statement.
     if (instruction.inputs[2]
             .isInteger(closedWorld.abstractValueDomain)
             .isPotentiallyFalse &&
@@ -206,8 +211,10 @@
         instruction.getDartReceiver(closedWorld).instructionType;
     AbstractValue type = AbstractValueFactory.inferredTypeForSelector(
         instruction.selector, receiverType, results);
-    return new HIndex(instruction.inputs[1], instruction.inputs[2],
+    HIndex converted = new HIndex(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, type);
+    log?.registerIndex(instruction, converted);
+    return converted;
   }
 }
 
@@ -240,14 +247,17 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
-      return new HBitNot(
+      HBitNot converted = new HBitNot(
           input,
           instruction.selector,
           computeTypeFromInputTypes(
               instruction, results, options, closedWorld));
+      log?.registerBitNot(instruction, converted);
+      return converted;
     }
     return null;
   }
@@ -293,14 +303,17 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
-      return new HNegate(
+      HNegate converted = new HNegate(
           input,
           instruction.selector,
           computeTypeFromInputTypes(
               instruction, results, options, closedWorld));
+      log?.registerUnaryNegate(instruction, converted);
+      return converted;
     }
     return null;
   }
@@ -334,17 +347,23 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction input = instruction.inputs[1];
     if (input.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
-      return new HAbs(
+      HAbs converted = new HAbs(
           input,
           instruction.selector,
           computeTypeFromInputTypes(
               instruction, results, options, closedWorld));
+      log?.registerAbs(instruction, converted);
+      return converted;
     }
     return null;
   }
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {}
 }
 
 abstract class BinaryArithmeticSpecializer extends InvokeDynamicSpecializer {
@@ -395,11 +414,17 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     if (isBuiltin(instruction, closedWorld)) {
       HInstruction builtin =
           newBuiltinVariant(instruction, results, options, closedWorld);
-      if (builtin != null) return builtin;
+      if (log != null) {
+        registerOptimization(log, instruction, builtin);
+      }
+      if (builtin != null) {
+        return builtin;
+      }
       // Even if there is no builtin equivalent instruction, we know
       // the instruction does not have any side effect, and that it
       // can be GVN'ed.
@@ -432,6 +457,9 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JClosedWorld closedWorld);
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted);
 }
 
 class AddSpecializer extends BinaryArithmeticSpecializer {
@@ -467,6 +495,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerAdd(original, converted);
+  }
 }
 
 class DivideSpecializer extends BinaryArithmeticSpecializer {
@@ -497,6 +531,12 @@
     return new HDivide(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.doubleType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerDivide(original, converted);
+  }
 }
 
 class ModuloSpecializer extends BinaryArithmeticSpecializer {
@@ -583,6 +623,12 @@
     // don't want to ruin GVN opportunities.
     return null;
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerModulo(original, converted);
+  }
 }
 
 class RemainderSpecializer extends BinaryArithmeticSpecializer {
@@ -615,6 +661,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerRemainder(original, converted);
+  }
 }
 
 class MultiplySpecializer extends BinaryArithmeticSpecializer {
@@ -647,6 +699,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerMultiply(original, converted);
+  }
 }
 
 class SubtractSpecializer extends BinaryArithmeticSpecializer {
@@ -667,6 +725,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerSubtract(original, converted);
+  }
 }
 
 class TruncatingDivideSpecializer extends BinaryArithmeticSpecializer {
@@ -731,7 +795,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction right = instruction.inputs[2];
     if (isBuiltin(instruction, closedWorld)) {
       if (right
@@ -739,12 +804,20 @@
               .isDefinitelyTrue &&
           isNotZero(right)) {
         if (hasUint31Result(instruction, closedWorld)) {
-          return newBuiltinVariant(instruction, results, options, closedWorld);
+          HInstruction converted =
+              newBuiltinVariant(instruction, results, options, closedWorld);
+          if (log != null) {
+            registerOptimization(log, instruction, converted);
+          }
+          return converted;
         }
         // We can call _tdivFast because the rhs is a 32bit integer
         // and not 0, nor -1.
         instruction.selector = renameToOptimizedSelector(
             '_tdivFast', instruction.selector, commonElements);
+        if (log != null) {
+          registerOptimization(log, instruction, null);
+        }
       }
       clearAllSideEffects(instruction);
     }
@@ -762,6 +835,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerTruncatingDivide(original, converted);
+  }
 }
 
 abstract class BinaryBitOpSpecializer extends BinaryArithmeticSpecializer {
@@ -826,12 +905,18 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
       if (argumentLessThan32(right)) {
-        return newBuiltinVariant(instruction, results, options, closedWorld);
+        HInstruction converted =
+            newBuiltinVariant(instruction, results, options, closedWorld);
+        if (log != null) {
+          registerOptimization(log, instruction, converted);
+        }
+        return converted;
       }
       // Even if there is no builtin equivalent instruction, we know
       // the instruction does not have any side effect, and that it
@@ -841,6 +926,9 @@
         instruction.selector = renameToOptimizedSelector(
             '_shlPositive', instruction.selector, commonElements);
       }
+      if (log != null) {
+        registerOptimization(log, instruction, null);
+      }
     }
     return null;
   }
@@ -856,6 +944,12 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerShiftLeft(original, converted);
+  }
 }
 
 class ShiftRightSpecializer extends BinaryBitOpSpecializer {
@@ -880,12 +974,18 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
       if (argumentLessThan32(right) && isPositive(left, closedWorld)) {
-        return newBuiltinVariant(instruction, results, options, closedWorld);
+        HInstruction converted =
+            newBuiltinVariant(instruction, results, options, closedWorld);
+        if (log != null) {
+          registerOptimization(log, instruction, converted);
+        }
+        return converted;
       }
       // Even if there is no builtin equivalent instruction, we know
       // the instruction does not have any side effect, and that it
@@ -894,13 +994,22 @@
       if (isPositive(right, closedWorld) && isPositive(left, closedWorld)) {
         instruction.selector = renameToOptimizedSelector(
             '_shrBothPositive', instruction.selector, commonElements);
+        if (log != null) {
+          registerOptimization(log, instruction, null);
+        }
       } else if (isPositive(left, closedWorld) &&
           right.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
         instruction.selector = renameToOptimizedSelector(
             '_shrReceiverPositive', instruction.selector, commonElements);
+        if (log != null) {
+          registerOptimization(log, instruction, null);
+        }
       } else if (isPositive(right, closedWorld)) {
         instruction.selector = renameToOptimizedSelector(
             '_shrOtherPositive', instruction.selector, commonElements);
+        if (log != null) {
+          registerOptimization(log, instruction, null);
+        }
       }
     }
     return null;
@@ -921,6 +1030,12 @@
   BinaryOperation operation(ConstantSystem constantSystem) {
     return constantSystem.shiftRight;
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerShiftRight(original, converted);
+  }
 }
 
 class BitOrSpecializer extends BinaryBitOpSpecializer {
@@ -956,6 +1071,11 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerBitOr(original, converted);
+  }
 }
 
 class BitAndSpecializer extends BinaryBitOpSpecializer {
@@ -994,6 +1114,11 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerBitAnd(original, converted);
+  }
 }
 
 class BitXorSpecializer extends BinaryBitOpSpecializer {
@@ -1029,6 +1154,11 @@
         instruction.selector,
         computeTypeFromInputTypes(instruction, results, options, closedWorld));
   }
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerBitXor(original, converted);
+  }
 }
 
 abstract class RelationalSpecializer extends InvokeDynamicSpecializer {
@@ -1054,18 +1184,26 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     if (left.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue &&
         right.isNumber(closedWorld.abstractValueDomain).isDefinitelyTrue) {
-      return newBuiltinVariant(instruction, closedWorld);
+      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
+      if (log != null) {
+        registerOptimization(log, instruction, converted);
+      }
+      return converted;
     }
     return null;
   }
 
   HInstruction newBuiltinVariant(
       HInvokeDynamic instruction, JClosedWorld closedWorld);
+
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted);
 }
 
 class EqualsSpecializer extends RelationalSpecializer {
@@ -1077,7 +1215,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction left = instruction.inputs[1];
     HInstruction right = instruction.inputs[2];
     AbstractValue instructionType = left.instructionType;
@@ -1085,7 +1224,11 @@
         left
             .isPrimitiveOrNull(closedWorld.abstractValueDomain)
             .isDefinitelyTrue) {
-      return newBuiltinVariant(instruction, closedWorld);
+      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
+      if (log != null) {
+        registerOptimization(log, instruction, converted);
+      }
+      return converted;
     }
     if (closedWorld.includesClosureCall(
         instruction.selector, instructionType)) {
@@ -1098,7 +1241,11 @@
     // a regular object or an interceptor.
     if (matches
         .every(closedWorld.commonElements.isDefaultEqualityImplementation)) {
-      return newBuiltinVariant(instruction, closedWorld);
+      HInstruction converted = newBuiltinVariant(instruction, closedWorld);
+      if (log != null) {
+        registerOptimization(log, instruction, converted);
+      }
+      return converted;
     }
     return null;
   }
@@ -1112,6 +1259,12 @@
     return new HIdentity(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerEquals(original, converted);
+  }
 }
 
 class LessSpecializer extends RelationalSpecializer {
@@ -1126,6 +1279,12 @@
     return new HLess(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerLess(original, converted);
+  }
 }
 
 class GreaterSpecializer extends RelationalSpecializer {
@@ -1140,6 +1299,12 @@
     return new HGreater(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerGreater(original, converted);
+  }
 }
 
 class GreaterEqualSpecializer extends RelationalSpecializer {
@@ -1154,6 +1319,12 @@
     return new HGreaterEqual(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerGreaterEqual(original, converted);
+  }
 }
 
 class LessEqualSpecializer extends RelationalSpecializer {
@@ -1168,6 +1339,12 @@
     return new HLessEqual(instruction.inputs[1], instruction.inputs[2],
         instruction.selector, closedWorld.abstractValueDomain.boolType);
   }
+
+  @override
+  void registerOptimization(
+      OptimizationTestLog log, HInstruction original, HInstruction converted) {
+    log.registerLessEqual(original, converted);
+  }
 }
 
 class CodeUnitAtSpecializer extends InvokeDynamicSpecializer {
@@ -1183,7 +1360,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     // TODO(sra): Implement a builtin HCodeUnitAt instruction and the same index
     // bounds checking optimizations as for HIndex.
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
@@ -1200,6 +1378,7 @@
         instruction.selector = renameToOptimizedSelector(
             '_codeUnitAt', instruction.selector, commonElements);
       }
+      log?.registerCodeUnitAt(instruction);
     }
     return null;
   }
@@ -1214,7 +1393,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     // `compareTo` has no side-effect (other than throwing) and can be GVN'ed
     // for some known types.
@@ -1240,16 +1420,20 @@
                   .isString(closedWorld.abstractValueDomain)
                   .isDefinitelyTrue)) {
         if (identical(receiver.nonCheck(), argument.nonCheck())) {
-          return graph.addConstantInt(0, closedWorld);
+          HInstruction converted = graph.addConstantInt(0, closedWorld);
+          log?.registerCompareTo(instruction, converted);
+          return converted;
         }
       }
       clearAllSideEffects(instruction);
+      log?.registerCompareTo(instruction);
     }
     return null;
   }
 }
 
-class IdempotentStringOperationSpecializer extends InvokeDynamicSpecializer {
+abstract class IdempotentStringOperationSpecializer
+    extends InvokeDynamicSpecializer {
   const IdempotentStringOperationSpecializer();
 
   HInstruction tryConvertToBuiltin(
@@ -1258,7 +1442,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     if (receiver
         .isStringOrNull(closedWorld.abstractValueDomain)
@@ -1266,17 +1451,32 @@
       // String.xxx does not have any side effect (other than throwing), and it
       // can be GVN'ed.
       clearAllSideEffects(instruction);
+      if (log != null) {
+        registerOptimization(log, instruction);
+      }
     }
     return null;
   }
+
+  void registerOptimization(OptimizationTestLog log, HInstruction original);
 }
 
 class SubstringSpecializer extends IdempotentStringOperationSpecializer {
   const SubstringSpecializer();
+
+  @override
+  void registerOptimization(OptimizationTestLog log, HInstruction original) {
+    log.registerSubstring(original);
+  }
 }
 
 class TrimSpecializer extends IdempotentStringOperationSpecializer {
   const TrimSpecializer();
+
+  @override
+  void registerOptimization(OptimizationTestLog log, HInstruction original) {
+    log.registerTrim(original);
+  }
 }
 
 class PatternMatchSpecializer extends InvokeDynamicSpecializer {
@@ -1288,7 +1488,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     HInstruction pattern = instruction.inputs[2];
     if (receiver
@@ -1300,6 +1501,7 @@
       // String.contains(String s) does not have any side effect (other than
       // throwing), and it can be GVN'ed.
       clearAllSideEffects(instruction);
+      log?.registerPatternMatch(instruction);
     }
     return null;
   }
@@ -1318,7 +1520,8 @@
       GlobalTypeInferenceResults results,
       CompilerOptions options,
       JCommonElements commonElements,
-      JClosedWorld closedWorld) {
+      JClosedWorld closedWorld,
+      OptimizationTestLog log) {
     HInstruction receiver = instruction.getDartReceiver(closedWorld);
     if (receiver
         .isNumberOrNull(closedWorld.abstractValueDomain)
@@ -1326,6 +1529,7 @@
       // Even if there is no builtin equivalent instruction, we know the
       // instruction does not have any side effect, and that it can be GVN'ed.
       clearAllSideEffects(instruction);
+      log?.registerRound(instruction);
     }
     return null;
   }
diff --git a/pkg/compiler/lib/src/ssa/locals_handler.dart b/pkg/compiler/lib/src/ssa/locals_handler.dart
index ff3ec93..991cef0 100644
--- a/pkg/compiler/lib/src/ssa/locals_handler.dart
+++ b/pkg/compiler/lib/src/ssa/locals_handler.dart
@@ -196,6 +196,7 @@
       ScopeInfo scopeInfo,
       CapturedScope scopeData,
       Map<Local, AbstractValue> parameters,
+      Set<Local> elidedParameters,
       SourceInformation sourceInformation,
       {bool isGenerativeConstructorBody}) {
     this.scopeInfo = scopeInfo;
@@ -208,10 +209,12 @@
           return;
         }
       }
-      HInstruction parameter = builder.addParameter(local, typeMask);
+      HInstruction parameter = builder.addParameter(local, typeMask,
+          isElided: elidedParameters.contains(local));
       builder.parameters[local] = parameter;
       directLocals[local] = parameter;
     });
+    builder.elidedParameters = elidedParameters;
 
     enterScope(scopeData, sourceInformation,
         forGenerativeConstructorBody: isGenerativeConstructorBody);
diff --git a/pkg/compiler/lib/src/ssa/logging.dart b/pkg/compiler/lib/src/ssa/logging.dart
index c213791..68d648f 100644
--- a/pkg/compiler/lib/src/ssa/logging.dart
+++ b/pkg/compiler/lib/src/ssa/logging.dart
@@ -2,30 +2,217 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-import 'nodes.dart';
 import '../util/features.dart';
+import 'nodes.dart';
 
 /// Log used for unit testing optimizations.
-class OptimizationLog {
+class OptimizationTestLog {
   List<OptimizationLogEntry> entries = [];
 
-  void registerFieldGet(HInvokeDynamicGetter node, HFieldGet fieldGet) {
+  Map<String, Set<HInstruction>> _unconverted;
+
+  Features _register(String tag, HInstruction original, HInstruction converted,
+      void f(Features features)) {
+    if (converted == null) {
+      _unconverted ??= {};
+      Set<HInstruction> set = _unconverted[tag] ??= new Set<HInstruction>();
+      if (!set.add(original)) {
+        return null;
+      }
+    }
+    Features features = new Features();
+    f(features);
+    entries.add(new OptimizationLogEntry(tag, features));
+    return features;
+  }
+
+  void registerFieldGet(HInvokeDynamicGetter original, HFieldGet converted) {
     Features features = new Features();
     features['name'] =
-        '${fieldGet.element.enclosingClass.name}.${fieldGet.element.name}';
+        '${converted.element.enclosingClass.name}.${converted.element.name}';
     entries.add(new OptimizationLogEntry('FieldGet', features));
   }
 
-  void registerFieldSet(HInvokeDynamicSetter node, HFieldSet fieldSet) {
+  void registerFieldSet(HInvokeDynamicSetter original, [HFieldSet converted]) {
     Features features = new Features();
-    features['name'] =
-        '${fieldSet.element.enclosingClass.name}.${fieldSet.element.name}';
+    if (converted != null) {
+      features['name'] =
+          '${converted.element.enclosingClass.name}.${converted.element.name}';
+    } else {
+      features['removed'] = original.selector.name;
+    }
     entries.add(new OptimizationLogEntry('FieldSet', features));
   }
 
+  Features _registerSpecializer(
+      HInvokeDynamic original, HInstruction converted, String name,
+      [String unconvertedName]) {
+    assert(!(converted == null && unconvertedName == null));
+    return _register('Specializer', original, converted, (Features features) {
+      if (converted != null) {
+        features.add(name);
+      } else {
+        features.add(unconvertedName);
+      }
+    });
+  }
+
+  void registerIndexAssign(HInvokeDynamic original, HIndexAssign converted) {
+    _registerSpecializer(original, converted, 'IndexAssign');
+  }
+
+  void registerIndex(HInvokeDynamic original, HIndex converted) {
+    _registerSpecializer(original, converted, 'Index');
+  }
+
+  void registerBitNot(HInvokeDynamic original, HBitNot converted) {
+    _registerSpecializer(original, converted, 'BitNot');
+  }
+
+  void registerUnaryNegate(HInvokeDynamic original, HNegate converted) {
+    _registerSpecializer(original, converted, 'Negate');
+  }
+
+  void registerAbs(HInvokeDynamic original, HAbs converted) {
+    _registerSpecializer(original, converted, 'Abs');
+  }
+
+  void registerAdd(HInvokeDynamic original, HAdd converted) {
+    _registerSpecializer(original, converted, 'Add');
+  }
+
+  void registerDivide(HInvokeDynamic original, HDivide converted) {
+    _registerSpecializer(original, converted, 'Divide');
+  }
+
+  void registerModulo(HInvokeDynamic original, [HRemainder converted]) {
+    _registerSpecializer(original, converted, 'Modulo', 'DynamicModulo');
+  }
+
+  void registerRemainder(HInvokeDynamic original, HRemainder converted) {
+    _registerSpecializer(original, converted, 'Remainder');
+  }
+
+  void registerMultiply(HInvokeDynamic original, HMultiply converted) {
+    _registerSpecializer(original, converted, 'Multiply');
+  }
+
+  void registerSubtract(HInvokeDynamic original, HSubtract converted) {
+    _registerSpecializer(original, converted, 'Subtract');
+  }
+
+  void registerTruncatingDivide(
+      HInvokeDynamic original, HTruncatingDivide converted) {
+    _registerSpecializer(original, converted, 'TruncatingDivide',
+        'TruncatingDivide.${original.selector.name}');
+  }
+
+  void registerShiftLeft(HInvokeDynamic original, HShiftLeft converted) {
+    _registerSpecializer(original, converted, 'ShiftLeft',
+        'ShiftLeft.${original.selector.name}');
+  }
+
+  void registerShiftRight(HInvokeDynamic original, HShiftRight converted) {
+    _registerSpecializer(original, converted, 'ShiftRight',
+        'ShiftRight.${original.selector.name}');
+  }
+
+  void registerBitOr(HInvokeDynamic original, HBitOr converted) {
+    _registerSpecializer(original, converted, 'BitOr');
+  }
+
+  void registerBitAnd(HInvokeDynamic original, HBitAnd converted) {
+    _registerSpecializer(original, converted, 'BitAnd');
+  }
+
+  void registerBitXor(HInvokeDynamic original, HBitXor converted) {
+    _registerSpecializer(original, converted, 'BitXor');
+  }
+
+  void registerEquals(HInvokeDynamic original, HIdentity converted) {
+    _registerSpecializer(original, converted, 'Equals');
+  }
+
+  void registerLess(HInvokeDynamic original, HLess converted) {
+    _registerSpecializer(original, converted, 'Less');
+  }
+
+  void registerGreater(HInvokeDynamic original, HGreater converted) {
+    _registerSpecializer(original, converted, 'Greater');
+  }
+
+  void registerLessEqual(HInvokeDynamic original, HLessEqual converted) {
+    _registerSpecializer(original, converted, 'LessEquals');
+  }
+
+  void registerGreaterEqual(HInvokeDynamic original, HGreaterEqual converted) {
+    _registerSpecializer(original, converted, 'GreaterEquals');
+  }
+
+  void registerCodeUnitAt(HInvokeDynamic original) {
+    Features features = new Features();
+    features['name'] = original.selector.name;
+    entries.add(new OptimizationLogEntry('CodeUnitAt', features));
+  }
+
+  void registerCompareTo(HInvokeDynamic original, [HConstant converted]) {
+    Features features = new Features();
+    if (converted != null) {
+      features['constant'] = converted.constant.toDartText();
+    }
+    entries.add(new OptimizationLogEntry('CompareTo', features));
+  }
+
+  void registerSubstring(HInvokeDynamic original) {
+    Features features = new Features();
+    entries.add(new OptimizationLogEntry('Substring', features));
+  }
+
+  void registerTrim(HInvokeDynamic original) {
+    Features features = new Features();
+    entries.add(new OptimizationLogEntry('Trim', features));
+  }
+
+  void registerPatternMatch(HInvokeDynamic original) {
+    Features features = new Features();
+    entries.add(new OptimizationLogEntry('PatternMatch', features));
+  }
+
+  void registerRound(HInvokeDynamic original) {
+    _registerSpecializer(original, null, null, 'Round');
+  }
+
+  void registerTypeConversion(
+      HInstruction original, HTypeConversion converted) {
+    Features features = new Features();
+    switch (converted.kind) {
+      case HTypeConversion.CHECKED_MODE_CHECK:
+        features['kind'] = 'checked';
+        break;
+      case HTypeConversion.ARGUMENT_TYPE_CHECK:
+        features['kind'] = 'argument';
+        break;
+      case HTypeConversion.CAST_TYPE_CHECK:
+        features['kind'] = 'cast';
+        break;
+      case HTypeConversion.BOOLEAN_CONVERSION_CHECK:
+        features['kind'] = 'boolean';
+        break;
+      case HTypeConversion.RECEIVER_TYPE_CHECK:
+        features['kind'] = 'receiver';
+        break;
+    }
+    if (converted.typeExpression != null) {
+      features['type'] = '${converted.typeExpression}';
+    }
+    entries.add(new OptimizationLogEntry('TypeConversion', features));
+  }
+
   String getText() {
     return entries.join(',\n');
   }
+
+  String toString() => 'OptimizationLog(${getText()})';
 }
 
 /// A registered optimization.
diff --git a/pkg/compiler/lib/src/ssa/nodes.dart b/pkg/compiler/lib/src/ssa/nodes.dart
index dc693ef..5b0006f 100644
--- a/pkg/compiler/lib/src/ssa/nodes.dart
+++ b/pkg/compiler/lib/src/ssa/nodes.dart
@@ -2540,7 +2540,7 @@
 }
 
 class HParameterValue extends HLocalValue {
-  HParameterValue(Entity variable, type) : super(variable, type);
+  HParameterValue(Entity variable, AbstractValue type) : super(variable, type);
 
   // [HParameterValue]s are either the value of the parameter (in fully SSA
   // converted code), or the mutable variable containing the value (in
diff --git a/pkg/compiler/lib/src/ssa/optimize.dart b/pkg/compiler/lib/src/ssa/optimize.dart
index 309566c..007950f 100644
--- a/pkg/compiler/lib/src/ssa/optimize.dart
+++ b/pkg/compiler/lib/src/ssa/optimize.dart
@@ -43,7 +43,7 @@
 
   Map<HInstruction, Range> ranges = <HInstruction, Range>{};
 
-  Map<MemberEntity, OptimizationLog> loggersForTesting;
+  Map<MemberEntity, OptimizationTestLog> loggersForTesting;
 
   SsaOptimizerTask(this._backend) : super(_backend.compiler.measurer);
 
@@ -69,10 +69,10 @@
     SsaCodeMotion codeMotion;
     SsaLoadElimination loadElimination;
 
-    OptimizationLog log;
+    OptimizationTestLog log;
     if (retainDataForTesting) {
       loggersForTesting ??= {};
-      loggersForTesting[work.element] = log = new OptimizationLog();
+      loggersForTesting[work.element] = log = new OptimizationTestLog();
     }
 
     measure(() {
@@ -85,7 +85,7 @@
         new SsaRedundantPhiEliminator(),
         new SsaDeadPhiEliminator(),
         new SsaTypePropagator(globalInferenceResults, _options,
-            closedWorld.commonElements, closedWorld),
+            closedWorld.commonElements, closedWorld, log),
         // After type propagation, more instructions can be
         // simplified.
         new SsaInstructionSimplifier(globalInferenceResults, _options,
@@ -95,7 +95,7 @@
             _rtiSubstitutions, closedWorld, registry, log),
         new SsaCheckInserter(trustPrimitives, closedWorld, boundsChecked),
         new SsaTypePropagator(globalInferenceResults, _options,
-            closedWorld.commonElements, closedWorld),
+            closedWorld.commonElements, closedWorld, log),
         // Run a dead code eliminator before LICM because dead
         // interceptors are often in the way of LICM'able instructions.
         new SsaDeadCodeEliminator(closedWorld, this),
@@ -103,7 +103,7 @@
         // After GVN, some instructions might need their type to be
         // updated because they now have different inputs.
         new SsaTypePropagator(globalInferenceResults, _options,
-            closedWorld.commonElements, closedWorld),
+            closedWorld.commonElements, closedWorld, log),
         codeMotion = new SsaCodeMotion(closedWorld.abstractValueDomain),
         loadElimination = new SsaLoadElimination(_compiler, closedWorld),
         new SsaRedundantPhiEliminator(),
@@ -113,7 +113,7 @@
         // learn from the refined type.
         new SsaTypeConversionInserter(closedWorld),
         new SsaTypePropagator(globalInferenceResults, _options,
-            closedWorld.commonElements, closedWorld),
+            closedWorld.commonElements, closedWorld, log),
         new SsaValueRangeAnalyzer(closedWorld, this),
         // Previous optimizations may have generated new
         // opportunities for instruction simplification.
@@ -136,7 +136,7 @@
           loadElimination.newGvnCandidates) {
         phases = <OptimizationPhase>[
           new SsaTypePropagator(globalInferenceResults, _options,
-              closedWorld.commonElements, closedWorld),
+              closedWorld.commonElements, closedWorld, log),
           new SsaGlobalValueNumberer(closedWorld.abstractValueDomain),
           new SsaCodeMotion(closedWorld.abstractValueDomain),
           new SsaValueRangeAnalyzer(closedWorld, this),
@@ -149,7 +149,7 @@
       } else {
         phases = <OptimizationPhase>[
           new SsaTypePropagator(globalInferenceResults, _options,
-              closedWorld.commonElements, closedWorld),
+              closedWorld.commonElements, closedWorld, log),
           // Run the simplifier to remove unneeded type checks inserted by
           // type propagation.
           new SsaInstructionSimplifier(globalInferenceResults, _options,
@@ -196,7 +196,7 @@
   final RuntimeTypesSubstitutions _rtiSubstitutions;
   final JClosedWorld _closedWorld;
   final CodegenRegistry _registry;
-  final OptimizationLog _log;
+  final OptimizationTestLog _log;
   HGraph _graph;
 
   SsaInstructionSimplifier(this._globalInferenceResults, this._options,
@@ -548,8 +548,11 @@
         _globalInferenceResults,
         _options,
         commonElements,
-        _closedWorld);
-    if (instruction != null) return instruction;
+        _closedWorld,
+        _log);
+    if (instruction != null) {
+      return instruction;
+    }
 
     Selector selector = node.selector;
     AbstractValue mask = node.mask;
@@ -757,6 +760,9 @@
     // We can replace the call to the native class interceptor method (target)
     // if the target does no conversions or useful type checks.
     if (_options.disableInlining) return null;
+    if (_closedWorld.annotationsData.hasNoInline(method)) {
+      return null;
+    }
     if (!node.isInterceptedCall) return null;
 
     FunctionType type = _closedWorld.elementEnvironment.getFunctionType(method);
@@ -1286,11 +1292,16 @@
         value = other;
       }
     }
-    HFieldSet result =
-        new HFieldSet(_abstractValueDomain, field, receiver, value)
-          ..sourceInformation = node.sourceInformation;
-    _log?.registerFieldSet(node, result);
-    return result;
+    if (_closedWorld.elidedFields.contains(field)) {
+      _log?.registerFieldSet(node);
+      return value;
+    } else {
+      HFieldSet result =
+          new HFieldSet(_abstractValueDomain, field, receiver, value)
+            ..sourceInformation = node.sourceInformation;
+      _log?.registerFieldSet(node, result);
+      return result;
+    }
   }
 
   HInstruction visitInvokeClosure(HInvokeClosure node) {
@@ -1358,7 +1369,25 @@
           return argument;
         }
       }
+    } else if (element == commonElements.assertHelper ||
+        element == commonElements.assertTest) {
+      if (node.inputs.length == 1) {
+        HInstruction argument = node.inputs[0];
+        if (argument is HConstant) {
+          ConstantValue constant = argument.constant;
+          if (constant.isBool) {
+            bool value = constant.isTrue;
+            if (element == commonElements.assertTest) {
+              // `assertTest(argument)` effectively negates the argument.
+              return _graph.addConstantBool(!value, _closedWorld);
+            }
+            // `assertHelper(true)` is a no-op, other values throw.
+            if (value) return argument;
+          }
+        }
+      }
     }
+
     return node;
   }
 
@@ -2922,7 +2951,8 @@
     if (shouldTrackInitialValues(instruction)) {
       int argumentIndex = 0;
       compiler.codegenWorldBuilder.forEachInstanceField(instruction.element,
-          (_, FieldEntity member) {
+          (_, FieldEntity member, {bool isElided}) {
+        if (isElided) return;
         if (compiler.elementHasCompileTimeError(
             // ignore: UNNECESSARY_CAST
             member as Entity)) return;
diff --git a/pkg/compiler/lib/src/ssa/types_propagation.dart b/pkg/compiler/lib/src/ssa/types_propagation.dart
index 492e6ea..8199ed4 100644
--- a/pkg/compiler/lib/src/ssa/types_propagation.dart
+++ b/pkg/compiler/lib/src/ssa/types_propagation.dart
@@ -10,6 +10,7 @@
 import '../options.dart';
 import '../universe/selector.dart' show Selector;
 import '../world.dart' show JClosedWorld;
+import 'logging.dart';
 import 'nodes.dart';
 import 'optimize.dart';
 
@@ -39,10 +40,11 @@
   final CompilerOptions options;
   final CommonElements commonElements;
   final JClosedWorld closedWorld;
+  final OptimizationTestLog _log;
   String get name => 'SsaTypePropagator';
 
-  SsaTypePropagator(
-      this.results, this.options, this.commonElements, this.closedWorld);
+  SsaTypePropagator(this.results, this.options, this.commonElements,
+      this.closedWorld, this._log);
 
   AbstractValueDomain get abstractValueDomain =>
       closedWorld.abstractValueDomain;
@@ -280,6 +282,7 @@
         receiverTypeCheckSelector: selector);
     instruction.block.addBefore(instruction, converted);
     input.replaceAllUsersDominatedBy(instruction, converted);
+    _log?.registerTypeConversion(instruction, converted);
   }
 
   bool isCheckEnoughForNsmOrAe(HInstruction instruction, AbstractValue type) {
diff --git a/pkg/compiler/lib/src/universe/codegen_world_builder.dart b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
index 4d4bab4..323bca3 100644
--- a/pkg/compiler/lib/src/universe/codegen_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/codegen_world_builder.dart
@@ -37,14 +37,20 @@
   /// 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));
+      void f(ClassEntity declarer, FieldEntity field, {bool isElided}));
 
   /// 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));
+      covariant ClassEntity cls, void f(FieldEntity field, {bool isElided}));
 
   /// Calls [f] for each parameter of [function] providing the type and name of
   /// the parameter and the [defaultValue] if the parameter is optional.
@@ -687,26 +693,35 @@
   @override
   void forEachParameter(FunctionEntity function,
       void f(DartType type, String name, ConstantValue defaultValue)) {
-    _elementMap.forEachParameter(function, f);
+    _elementMap.forEachParameter(function, f,
+        isNative: _world.nativeData.isNativeMember(function));
   }
 
   @override
   void forEachParameterAsLocal(
       FunctionEntity function, void f(Local parameter)) {
-    forEachOrderedParameter(_globalLocalsMap, _elementMap, function, f);
-  }
-
-  @override
-  void forEachInstanceField(
-      ClassEntity cls, void f(ClassEntity declarer, FieldEntity field)) {
-    _elementEnvironment.forEachClassMember(cls,
-        (ClassEntity declarer, MemberEntity member) {
-      if (member.isField && member.isInstanceMember) f(declarer, member);
+    forEachOrderedParameterAsLocal(_globalLocalsMap, _elementMap, function,
+        (Local parameter, {bool isElided}) {
+      if (!isElided) {
+        f(parameter);
+      }
     });
   }
 
   @override
-  void forEachDirectInstanceField(ClassEntity cls, void f(FieldEntity field)) {
+  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.elidedFields.contains(member));
+      }
+    });
+  }
+
+  @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.
@@ -715,7 +730,7 @@
       if (declarer != cls) return;
       if (!member.isField) return;
       if (!member.isInstanceMember) return;
-      f(member);
+      f(member, isElided: _world.elidedFields.contains(member));
     });
   }
 
diff --git a/pkg/compiler/lib/src/universe/member_usage.dart b/pkg/compiler/lib/src/universe/member_usage.dart
index 57481fb..b0898df 100644
--- a/pkg/compiler/lib/src/universe/member_usage.dart
+++ b/pkg/compiler/lib/src/universe/member_usage.dart
@@ -67,6 +67,9 @@
     }
   }
 
+  /// `true` if [entity] has been initialized.
+  bool get hasInit => true;
+
   /// `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;
@@ -149,41 +152,61 @@
 }
 
 class FieldUsage extends MemberUsage {
+  bool hasInit = false;
   bool hasRead = false;
   bool hasWrite = false;
 
   FieldUsage(FieldEntity field, {bool isNative: false})
       : super.internal(field) {
+    // TODO(johnniwinther): Track native fields through member usage.
     if (!isNative) {
-      // All field initializers must be resolved as they could
-      // have an observable side-effect (and cannot be tree-shaken
-      // away).
-      fullyUse();
+      init();
     }
   }
 
   @override
-  bool get fullyUsed => hasRead && hasWrite;
+  bool get hasPendingNormalUse => !fullyUsed;
 
   @override
-  EnumSet<MemberUse> init() => read();
+  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;
+  }
 
   @override
   EnumSet<MemberUse> read() {
-    if (fullyUsed) {
+    if (hasRead) {
       return MemberUses.NONE;
     }
     hasRead = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    if (!fullyUsed) {
+      result = result.union(MemberUses.PARTIAL_USE_ONLY);
+    }
+    return result;
   }
 
   @override
   EnumSet<MemberUse> write() {
-    if (fullyUsed) {
+    if (hasWrite) {
       return MemberUses.NONE;
     }
     hasWrite = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    EnumSet<MemberUse> result = _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    if (!fullyUsed) {
+      result = result.union(MemberUses.PARTIAL_USE_ONLY);
+    }
+    return result;
   }
 
   @override
@@ -194,29 +217,43 @@
     if (fullyUsed) {
       return MemberUses.NONE;
     }
-    hasRead = hasWrite = true;
+    hasInit = hasRead = hasWrite = true;
     return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
   }
+
+  String toString() => 'FieldUsage($entity,hasInit=$hasInit,hasRead=$hasRead,'
+      'hasWrite=$hasWrite,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
 }
 
 class FinalFieldUsage extends MemberUsage {
+  bool hasInit = false;
   bool hasRead = false;
 
   FinalFieldUsage(FieldEntity field, {bool isNative: false})
       : super.internal(field) {
     if (!isNative) {
-      // All field initializers must be resolved as they could
-      // have an observable side-effect (and cannot be tree-shaken
-      // away).
-      read();
+      init();
     }
   }
 
   @override
-  bool get fullyUsed => hasRead;
+  bool get hasPendingNormalUse => !fullyUsed;
 
   @override
-  EnumSet<MemberUse> init() => read();
+  bool get fullyUsed => hasInit && hasRead;
+
+  @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> read() {
@@ -224,14 +261,27 @@
       return MemberUses.NONE;
     }
     hasRead = true;
-    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+    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() => read();
+  EnumSet<MemberUse> fullyUse() {
+    if (fullyUsed) {
+      return MemberUses.NONE;
+    }
+    hasInit = hasRead = true;
+    return _pendingUse.removeAll(MemberUses.NORMAL_ONLY);
+  }
+
+  String toString() => 'FinalFieldUsage($entity,hasInit=$hasInit,'
+      'hasRead=$hasRead,pendingUse=${_pendingUse.iterable(MemberUse.values)}';
 }
 
 class FunctionUsage extends MemberUsage {
@@ -519,7 +569,7 @@
   ///
   /// This is used to check that no partial use is missed by the enqueuer, as
   /// asserted through the `Enqueuery.checkEnqueuerConsistency` method.
-  PARTIAL_USE
+  PARTIAL_USE,
 }
 
 /// Common [EnumSet]s used for [MemberUse].
@@ -636,6 +686,9 @@
   EnumSet<MemberUse> tearOff() => normalUse();
 
   @override
+  bool get hasInit => true;
+
+  @override
   bool get fullyUsed => hasNormalUse;
 
   @override
@@ -661,6 +714,9 @@
 
   FunctionEntity get entity => super.entity;
 
+  @override
+  bool get hasInit => true;
+
   EnumSet<MemberUse> tearOff() {
     if (hasClosurization) {
       return MemberUses.NONE;
diff --git a/pkg/compiler/lib/src/universe/resolution_world_builder.dart b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
index 62bce9b..da4c609 100644
--- a/pkg/compiler/lib/src/universe/resolution_world_builder.dart
+++ b/pkg/compiler/lib/src/universe/resolution_world_builder.dart
@@ -1068,6 +1068,22 @@
     BackendUsage backendUsage = _backendUsageBuilder.close();
     _closed = true;
 
+    Map<MemberEntity, MemberUsage> liveMemberUsage = {};
+    _memberUsage.forEach((MemberEntity member, MemberUsage memberUsage) {
+      if (memberUsage.hasUse) {
+        liveMemberUsage[member] = memberUsage;
+        assert(_processedMembers.contains(member),
+            "Member $member is used but not processed: $memberUsage.");
+      } else {
+        assert(!_processedMembers.contains(member),
+            "Member $member is processed but not used: $memberUsage.");
+      }
+    });
+    for (MemberEntity member in _processedMembers) {
+      assert(_memberUsage.containsKey(member),
+          "Member $member is processed but has not usage.");
+    }
+
     KClosedWorld closedWorld = new KClosedWorldImpl(_elementMap,
         options: _options,
         elementEnvironment: _elementEnvironment,
@@ -1084,11 +1100,11 @@
         liveNativeClasses: _nativeResolutionEnqueuer.liveNativeClasses,
         liveInstanceMembers: _liveInstanceMembers,
         assignedInstanceMembers: computeAssignedInstanceMembers(),
-        processedMembers: _processedMembers,
+        liveMemberUsage: liveMemberUsage,
         mixinUses: _classHierarchyBuilder.mixinUses,
         typesImplementedBySubclasses: typesImplementedBySubclasses,
         classHierarchy: _classHierarchyBuilder.close(),
-        annotationsData: _annotationsDataBuilder);
+        annotationsData: _annotationsDataBuilder.close());
     if (retainDataForTesting) {
       _closedWorldCache = closedWorld;
     }
diff --git a/pkg/compiler/lib/src/util/features.dart b/pkg/compiler/lib/src/util/features.dart
index 652f8ab..d0547d3 100644
--- a/pkg/compiler/lib/src/util/features.dart
+++ b/pkg/compiler/lib/src/util/features.dart
@@ -62,6 +62,8 @@
     return sb.toString();
   }
 
+  String toString() => 'Features(${getText()})';
+
   /// Creates a [Features] object by parse the [text] encoding.
   ///
   /// Single features will be parsed as strings and list features (features
diff --git a/pkg/compiler/lib/src/world.dart b/pkg/compiler/lib/src/world.dart
index 0ed8695..b674a0b 100644
--- a/pkg/compiler/lib/src/world.dart
+++ b/pkg/compiler/lib/src/world.dart
@@ -31,6 +31,7 @@
 import 'js_model/locals.dart';
 import 'js_emitter/sorter.dart';
 import 'universe/class_hierarchy.dart';
+import 'universe/member_usage.dart';
 import 'universe/selector.dart' show Selector;
 
 /// Common superinterface for [OpenWorld] and [JClosedWorld].
@@ -201,6 +202,8 @@
   /// 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);
+
+  Iterable<FieldEntity> get elidedFields;
 }
 
 abstract class OpenWorld implements World {
@@ -249,7 +252,7 @@
   Iterable<MemberEntity> get assignedInstanceMembers;
 
   Iterable<ClassEntity> get liveNativeClasses;
-  Iterable<MemberEntity> get processedMembers;
+  Map<MemberEntity, MemberUsage> get liveMemberUsage;
   RuntimeTypesNeed get rtiNeed;
   NoSuchMethodData get noSuchMethodData;
 
diff --git a/pkg/dartfix/CHANGELOG.md b/pkg/dartfix/CHANGELOG.md
index 9ba3827..153554b 100644
--- a/pkg/dartfix/CHANGELOG.md
+++ b/pkg/dartfix/CHANGELOG.md
@@ -1,3 +1,7 @@
+# 0.1.5
+* add command line options for selecting/excluding fixes to apply
+* add experimental NNBD migration support
+
 # 0.1.4
  * update protocol version constraints
 
diff --git a/pkg/dartfix/README.md b/pkg/dartfix/README.md
index 45f61cb..43ed757 100644
--- a/pkg/dartfix/README.md
+++ b/pkg/dartfix/README.md
@@ -1,8 +1,5 @@
-The `dartfix` tool is a command-line interface
-for making automated updates to your Dart code.
-The tool isn't in the Dart SDK;
-instead, it's distributed in the [`dartfix` package.][dartfix]
-
+`dartfix` is a command-line tool for migrating your Dart code
+to use newer syntax styles.
 
 ## Usage
 
@@ -24,13 +21,21 @@
 ```
 
 ## Features
+`dartfix` applies different types of "fixes" to migrate your Dart code.
+By default, all fixes are applied, but you can select only the specific fixes you
+want. See `dartfix --help` for more about the available command line options.
 
-As of release 0.1.3, `dartfix` can make the following changes to your code:
+Some of the fixes that you can apply are "required" in that the Dart language
+is changing and at some point the old syntax will no longer be supported.
+To only apply these changes, pass the `--required` option on the command line.
+The required fixes include:
 
-* Convert code to use the following [features added to Dart in 2.1][]:
-  * Find classes used as mixins, and convert them to use the `mixin` keyword
+* Find classes used as mixins, and convert them to use the `mixin` keyword
     instead of `class`.
-  * Find `double` literals that end in `.0`, and remove the `.0`.
+    Mixin support is one of the [features added to Dart in 2.1][].
+    At some point in the future, the Dart team plans
+    to disallow using classes as mixins.
+
 * Move named constructor type arguments from the name to the type. <br>
   For example, given `class A<T> { A.from(Object obj) { } }`,
   `dartfix` changes constructor invocations in the following way:
@@ -43,6 +48,11 @@
   A<String>.from(anObject) // Same, but the type is directly after `A`.
   ```
 
+Other changes are recommended but not required. These include:
+
+* Find `double` literals that end in `.0`, and remove the `.0`.
+  Language support for this was [added in Dart in 2.1][].
+
 ## Installing and updating dartfix
 
 The easiest way to use `dartfix` is to [globally install][] it,
@@ -56,27 +66,6 @@
 We recommend updating `dartfix` whenever you update your Dart SDK
 or when a new feature is released.
 
-## Options
-
-<dl>
-  <dt><code>--[no-]color</code></dt>
-  <dd> Use colors when printing messages. On by default. </dd>
-
-  <dt><code>-f, --force</code></dt>
-  <dd>Apply the recommended changes even if the input code has errors.
-  </dd>
-
-  <dt><code>-h, --help</code></dt>
-  <dd>See a complete list of `dartfix` options.</dd>
-
-  <dt><code>-v, --verbose</code></dt>
-  <dd>Verbose output.</dd>
-
-  <dt><code>-w, --overwrite</code></dt>
-  <dd>Apply the recommended changes.</dd>
-</dl>
-
-
 ## Filing issues
 
 If you want a new fix, first look at [dartfix issues][]
@@ -85,6 +74,7 @@
 
 [dartfix]: https://pub.dartlang.org/packages/dartfix
 [dartfmt]: https://www.dartlang.org/tools/dartfmt
+[added in Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
 [features added to Dart in 2.1]: https://github.com/dart-lang/sdk/blob/master/CHANGELOG.md#210---2018-11-15
 [globally install]: https://www.dartlang.org/tools/pub/cmd/pub-global
 [new issue]: https://github.com/dart-lang/sdk/issues/new?title=dartfix%20request%3A%20%3CSUMMARIZE%20REQUEST%20HERE%3E
diff --git a/pkg/dartfix/lib/src/driver.dart b/pkg/dartfix/lib/src/driver.dart
index 7881d73..ba7cea7 100644
--- a/pkg/dartfix/lib/src/driver.dart
+++ b/pkg/dartfix/lib/src/driver.dart
@@ -46,10 +46,15 @@
     if (!await startServer(options)) {
       context.exit(15);
     }
-
     try {
-      final progress = await setupAnalysis(options);
-      result = await requestFixes(options, progress);
+      if (checkSupported(options)) {
+        if (options.listFixes) {
+          await showListOfFixes();
+        } else {
+          final progress = await setupAnalysis(options);
+          result = await requestFixes(options, progress);
+        }
+      }
     } finally {
       await server.stop();
     }
@@ -78,6 +83,39 @@
     return handler.serverConnected(timeLimit: const Duration(seconds: 15));
   }
 
+  /// Check if the specified options is supported by the version of analysis
+  /// server being run and return `true` if they are.
+  /// Display an error message and return `false` if not.
+  bool checkSupported(Options options) {
+    if (handler.serverProtocolVersion.compareTo(new Version(1, 22, 2)) >= 0) {
+      return true;
+    }
+    if (options.excludeFixes.isNotEmpty) {
+      unsupportedOption(excludeOption);
+      return false;
+    }
+    if (options.includeFixes.isNotEmpty) {
+      unsupportedOption(includeOption);
+      return false;
+    }
+    if (options.listFixes) {
+      unsupportedOption(listOption);
+      return false;
+    }
+    if (options.requiredFixes) {
+      unsupportedOption(requiredOption);
+      return false;
+    }
+    return true;
+  }
+
+  void unsupportedOption(String option) {
+    final version = handler.serverProtocolVersion.toString();
+    logger.stderr('''
+The --$option option is not supported by analysis server version $version.
+Please upgrade to a newer version of the Dart SDK to use this option.''');
+  }
+
   Future<Progress> setupAnalysis(Options options) async {
     final progress = logger.progress('${ansi.emphasized('Calculating fixes')}');
     logger.trace('');
@@ -97,8 +135,19 @@
       Options options, Progress progress) async {
     logger.trace('Requesting fixes');
     Future isAnalysisComplete = handler.analysisComplete();
-    Map<String, dynamic> json = await server.send(
-        EDIT_REQUEST_DARTFIX, new EditDartfixParams(options.targets).toJson());
+
+    final params = new EditDartfixParams(options.targets);
+    if (options.excludeFixes.isNotEmpty) {
+      params.excludedFixes = options.excludeFixes;
+    }
+    if (options.includeFixes.isNotEmpty) {
+      params.includedFixes = options.includeFixes;
+    }
+    if (options.requiredFixes) {
+      params.includeRequiredFixes = true;
+    }
+    Map<String, dynamic> json =
+        await server.send(EDIT_REQUEST_DARTFIX, params.toJson());
 
     // TODO(danrubel): This is imprecise signal for determining when all
     // analysis error notifications have been received. Consider adding a new
@@ -184,6 +233,39 @@
     }
     return filePath;
   }
+
+  showListOfFixes() async {
+    final progress =
+        logger.progress('${ansi.emphasized('Getting list of fixes')}');
+    logger.trace('');
+    Map<String, dynamic> json = await server.send(
+        EDIT_REQUEST_GET_DARTFIX_INFO, new EditGetDartfixInfoParams().toJson());
+
+    progress.finish(showTiming: true);
+    ResponseDecoder decoder = new ResponseDecoder(null);
+    final result = EditGetDartfixInfoResult.fromJson(decoder, 'result', json);
+
+    final fixes = new List<DartFix>.from(result.fixes)
+      ..sort((f1, f2) => f1.name.compareTo(f2.name));
+
+    for (DartFix fix in fixes) {
+      String line = fix.name;
+      if (fix.isRequired == true) {
+        line = '$line (required)';
+      }
+      logger.stdout('');
+      logger.stdout(line);
+      if (fix.description != null) {
+        for (String line in indentAndWrapDescription(fix.description)) {
+          logger.stdout(line);
+        }
+      }
+    }
+    return result;
+  }
+
+  List<String> indentAndWrapDescription(String description) =>
+      description.split('\n').map((line) => '    $line').toList();
 }
 
 class _Listener with ServerListener, BadMessageListener {
@@ -205,12 +287,19 @@
   final Driver driver;
   final Logger logger;
   final Server server;
+  Version serverProtocolVersion;
 
   _Handler(this.driver)
       : logger = driver.logger,
         server = driver.server;
 
   @override
+  bool checkServerProtocolVersion(Version version) {
+    serverProtocolVersion = version;
+    return super.checkServerProtocolVersion(version);
+  }
+
+  @override
   void onFailedToConnect() {
     logger.stderr('Failed to connect to server');
   }
diff --git a/pkg/dartfix/lib/src/options.dart b/pkg/dartfix/lib/src/options.dart
index 2353b66..a9af28e 100644
--- a/pkg/dartfix/lib/src/options.dart
+++ b/pkg/dartfix/lib/src/options.dart
@@ -16,23 +16,49 @@
 
   List<String> targets;
   final String sdkPath;
+
+  final bool requiredFixes;
+  final List<String> includeFixes;
+  final List<String> excludeFixes;
+
   final bool force;
+  final bool listFixes;
   final bool overwrite;
-  final bool verbose;
   final bool useColor;
+  final bool verbose;
 
   static Options parse(List<String> args, {Context context, Logger logger}) {
     final parser = new ArgParser(allowTrailingOptions: true)
+      ..addSeparator('Choosing fixes to be applied:')
+      ..addMultiOption(includeOption,
+          abbr: 'i', help: 'Include a specific fix.', valueHelp: 'name-of-fix')
+      ..addMultiOption(excludeOption,
+          abbr: 'x', help: 'Exclude a specific fix.', valueHelp: 'name-of-fix')
+      ..addFlag(requiredOption,
+          abbr: 'r',
+          help: 'Apply required fixes.',
+          defaultsTo: false,
+          negatable: false)
+      ..addFlag(listOption,
+          abbr: 'l',
+          help: 'Display a list of fixes that can be applied.',
+          defaultsTo: false,
+          negatable: false)
+      ..addSeparator('Modifying files:')
       ..addFlag(overwriteOption,
           abbr: 'w',
-          help: 'Overwrite files with the recommended changes.',
+          help: 'Overwrite files with the changes.',
           defaultsTo: false,
           negatable: false)
       ..addFlag(forceOption,
           abbr: 'f',
-          help: 'Apply the recommended changes even if there are errors.',
+          help: 'Overwrite files even if there are errors.',
           defaultsTo: false,
           negatable: false)
+      ..addSeparator('Miscelaneous:')
+      ..addFlag(_colorOption,
+          help: 'Use ansi colors when printing messages.',
+          defaultsTo: Ansi.terminalSupportsAnsi)
       ..addFlag(_helpOption,
           abbr: 'h',
           help: 'Display this help message.',
@@ -42,10 +68,7 @@
           abbr: 'v',
           defaultsTo: false,
           help: 'Verbose output.',
-          negatable: false)
-      ..addFlag('color',
-          help: 'Use ansi colors when printing messages.',
-          defaultsTo: Ansi.terminalSupportsAnsi);
+          negatable: false);
 
     context ??= new Context();
 
@@ -80,6 +103,11 @@
       context.exit(1);
     }
 
+    if (options.listFixes) {
+      _showUsage(parser, logger, showListHint: false);
+      return options;
+    }
+
     // Validate the Dart SDK location
     String sdkPath = options.sdkPath;
     if (sdkPath == null) {
@@ -126,12 +154,20 @@
   }
 
   Options._fromArgs(this.context, ArgResults results)
-      : targets = results.rest,
-        force = results[forceOption] as bool,
+      : force = results[forceOption] as bool,
+        includeFixes =
+            (results[includeOption] as List ?? []).cast<String>().toList(),
+        excludeFixes =
+            (results[excludeOption] as List ?? []).cast<String>().toList(),
+        listFixes = results[listOption] as bool,
         overwrite = results[overwriteOption] as bool,
-        verbose = results[_verboseOption] as bool,
-        useColor = results.wasParsed('color') ? results['color'] as bool : null,
-        sdkPath = _getSdkPath();
+        requiredFixes = results[requiredOption] as bool,
+        sdkPath = _getSdkPath(),
+        targets = results.rest,
+        useColor = results.wasParsed(_colorOption)
+            ? results[_colorOption] as bool
+            : null,
+        verbose = results[_verboseOption] as bool;
 
   String makeAbsoluteAndNormalize(String target) {
     if (!path.isAbsolute(target)) {
@@ -146,15 +182,34 @@
         : path.dirname(path.dirname(Platform.resolvedExecutable));
   }
 
-  static _showUsage(ArgParser parser, Logger logger) {
+  static _showUsage(ArgParser parser, Logger logger,
+      {bool showListHint = true}) {
     logger.stderr('Usage: $_binaryName [options...] <directory paths>');
     logger.stderr('');
     logger.stderr(parser.usage);
+    logger.stderr('''
+
+If neither --$includeOption nor --$requiredOption is specified, then all fixes
+will be applied. Any fixes specified using --$excludeOption will not be applied
+regardless of whether they are required or specifed using --$includeOption.''');
+    if (showListHint) {
+      logger.stderr('''
+
+Use --list to display the fixes that can be specified
+using either --$includeOption or --$excludeOption.''');
+    }
   }
 }
 
 const _binaryName = 'dartfix';
+const _colorOption = 'color';
 const forceOption = 'force';
 const _helpOption = 'help';
 const overwriteOption = 'overwrite';
 const _verboseOption = 'verbose';
+
+// options only supported by server 1.22.2 and greater
+const excludeOption = 'exclude';
+const includeOption = 'include';
+const listOption = 'list';
+const requiredOption = 'required';
diff --git a/pkg/dartfix/pubspec.yaml b/pkg/dartfix/pubspec.yaml
index bf1bbdc..88c9dfc 100644
--- a/pkg/dartfix/pubspec.yaml
+++ b/pkg/dartfix/pubspec.yaml
@@ -1,5 +1,5 @@
 name: dartfix
-version: 0.1.4
+version: 0.1.5-dev
 author: Dart Team <misc@dartlang.org>
 description:
   A tool for migrating Dart source to newer versions of the Dart SDK,
@@ -12,7 +12,7 @@
 dependencies:
   # pin to an exact version of analysis_server_client because the edit.dartfix protocol
   # is experimental and will continue to evolve
-  analysis_server_client: 1.1.1
+  analysis_server_client: 1.1.2
   args: ^1.4.0
   cli_util: ^0.1.3
   path: ^1.6.0
diff --git a/pkg/dartfix/test/all.dart b/pkg/dartfix/test/all.dart
index 8fea855..010f047 100644
--- a/pkg/dartfix/test/all.dart
+++ b/pkg/dartfix/test/all.dart
@@ -4,10 +4,20 @@
 
 import 'package:test/test.dart';
 
+import 'src/client_version_test.dart' as client_version_test;
+import 'src/driver_exclude_test.dart' as driver_exclude_test;
+import 'src/driver_include_test.dart' as driver_include_test;
+import 'src/driver_list_test.dart' as driver_list_test;
+import 'src/driver_required_test.dart' as driver_required_test;
 import 'src/driver_test.dart' as driver_test;
 import 'src/options_test.dart' as options_test;
 
 main() {
+  client_version_test.main();
+  group('driver', driver_exclude_test.main);
+  group('driver', driver_include_test.main);
+  group('driver', driver_list_test.main);
+  group('driver', driver_required_test.main);
   group('driver', driver_test.main);
   group('options', options_test.main);
 }
diff --git a/pkg/dartfix/test/src/client_version_test.dart b/pkg/dartfix/test/src/client_version_test.dart
new file mode 100644
index 0000000..790e48b
--- /dev/null
+++ b/pkg/dartfix/test/src/client_version_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.
+
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+main() {
+  test('client version', () {
+    // The edit.dartfix protocol is experimental and will continue to evolve
+    // an so dartfix will only work with this specific version of the
+    // analysis_server_client package.
+    // If the protocol changes, then a new version of both the
+    // analysis_server_client and dartfix packages must be published.
+    expect(clientVersion, clientVersionInDartfixPubspec);
+  });
+}
+
+String get clientVersion =>
+    findValue(findFile('pkg/analysis_server_client/pubspec.yaml'), 'version');
+
+String get clientVersionInDartfixPubspec =>
+    findValue(findFile('pkg/dartfix/pubspec.yaml'), 'analysis_server_client');
diff --git a/pkg/dartfix/test/src/driver_exclude_test.dart b/pkg/dartfix/test/src/driver_exclude_test.dart
new file mode 100644
index 0000000..7cb2020
--- /dev/null
+++ b/pkg/dartfix/test/src/driver_exclude_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:dartfix/src/driver.dart';
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+const _debug = false;
+
+main() {
+  File exampleFile;
+  Directory exampleDir;
+
+  test('exclude fix', () async {
+    exampleFile = findFile('pkg/dartfix/example/example.dart');
+    exampleDir = exampleFile.parent;
+
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    String exampleSource = await exampleFile.readAsString();
+
+    await driver.start(['-xuse-mixin', exampleDir.path],
+        testContext: testContext, testLogger: testLogger);
+    if (_debug) {
+      print(testLogger.stderrBuffer.toString());
+      print(testLogger.stdoutBuffer.toString());
+      print('--- original example');
+      print(exampleSource);
+    }
+
+    final suggestions = driver.result.suggestions;
+    expect(suggestions, hasLength(1));
+    expectDoesNotHaveSuggestion(suggestions, 'Convert MyMixin to a mixin');
+    expectHasSuggestion(suggestions, 'Replace a double literal');
+  });
+}
diff --git a/pkg/dartfix/test/src/driver_include_test.dart b/pkg/dartfix/test/src/driver_include_test.dart
new file mode 100644
index 0000000..d25e710
--- /dev/null
+++ b/pkg/dartfix/test/src/driver_include_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:dartfix/src/driver.dart';
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+const _debug = false;
+
+main() {
+  File exampleFile;
+  Directory exampleDir;
+
+  test('include fix', () async {
+    exampleFile = findFile('pkg/dartfix/example/example.dart');
+    exampleDir = exampleFile.parent;
+
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    String exampleSource = await exampleFile.readAsString();
+
+    await driver.start(['-iuse-mixin', exampleDir.path],
+        testContext: testContext, testLogger: testLogger);
+    if (_debug) {
+      print(testLogger.stderrBuffer.toString());
+      print(testLogger.stdoutBuffer.toString());
+      print('--- original example');
+      print(exampleSource);
+    }
+
+    final suggestions = driver.result.suggestions;
+    expect(suggestions, hasLength(1));
+    expectHasSuggestion(suggestions, 'Convert MyMixin to a mixin');
+    expectDoesNotHaveSuggestion(suggestions, 'Replace a double literal');
+  });
+}
diff --git a/pkg/dartfix/test/src/driver_list_test.dart b/pkg/dartfix/test/src/driver_list_test.dart
new file mode 100644
index 0000000..372c98b
--- /dev/null
+++ b/pkg/dartfix/test/src/driver_list_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.
+
+import 'package:dartfix/src/driver.dart';
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+main() {
+  test('list fixes', () async {
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    await driver.start(['--list'], // list fixes
+        testContext: testContext,
+        testLogger: testLogger);
+    final errText = testLogger.stderrBuffer.toString();
+    final outText = testLogger.stdoutBuffer.toString();
+    print(errText);
+    print(outText);
+    expect(outText, contains('use-mixin'));
+  });
+}
diff --git a/pkg/dartfix/test/src/driver_required_test.dart b/pkg/dartfix/test/src/driver_required_test.dart
new file mode 100644
index 0000000..408cbbf
--- /dev/null
+++ b/pkg/dartfix/test/src/driver_required_test.dart
@@ -0,0 +1,41 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:io';
+
+import 'package:dartfix/src/driver.dart';
+import 'package:test/test.dart';
+
+import 'test_context.dart';
+
+const _debug = false;
+
+main() {
+  test('required fixes', () async {
+    File exampleFile;
+    Directory exampleDir;
+
+    exampleFile = findFile('pkg/dartfix/example/example.dart');
+    exampleDir = exampleFile.parent;
+
+    final driver = new Driver();
+    final testContext = new TestContext();
+    final testLogger = new TestLogger();
+    String exampleSource = await exampleFile.readAsString();
+
+    await driver.start(['-r', exampleDir.path],
+        testContext: testContext, testLogger: testLogger);
+    if (_debug) {
+      print(testLogger.stderrBuffer.toString());
+      print(testLogger.stdoutBuffer.toString());
+      print('--- original example');
+      print(exampleSource);
+    }
+
+    final suggestions = driver.result.suggestions;
+    expect(suggestions, hasLength(1));
+    expectHasSuggestion(suggestions, 'Convert MyMixin to a mixin');
+    expectDoesNotHaveSuggestion(suggestions, 'Replace a double literal');
+  });
+}
diff --git a/pkg/dartfix/test/src/driver_test.dart b/pkg/dartfix/test/src/driver_test.dart
index 5801b0d..f84e20b 100644
--- a/pkg/dartfix/test/src/driver_test.dart
+++ b/pkg/dartfix/test/src/driver_test.dart
@@ -10,7 +10,7 @@
 
 import 'test_context.dart';
 
-const _debug = true;
+const _debug = false;
 const _updateExample = false;
 
 main() {
@@ -24,15 +24,6 @@
     exampleDir = exampleFile.parent;
   });
 
-  test('client version', () {
-    // The edit.dartfix protocol is experimental and will continue to evolve
-    // an so dartfix will only work with this specific version of the
-    // analysis_server_client package.
-    // If the protocol changes, then a new version of both the
-    // analysis_server_client and dartfix packages must be published.
-    expect(clientVersion, clientVersionInDartfixPubspec);
-  });
-
   test('fix example', () async {
     final driver = new Driver();
     final testContext = new TestContext();
@@ -98,47 +89,6 @@
   });
 }
 
-String get clientVersion =>
-    findValue(findFile('pkg/analysis_server_client/pubspec.yaml'), 'version');
-
-String get clientVersionInDartfixPubspec =>
-    findValue(findFile('pkg/dartfix/pubspec.yaml'), 'analysis_server_client');
-
-File findFile(String relPath) {
-  Directory dir = Directory.current;
-  while (true) {
-    final file = new File.fromUri(dir.uri.resolve(relPath));
-    if (file.existsSync()) {
-      return file;
-    }
-    final parent = dir.parent;
-    if (parent.path == dir.path) {
-      fail('Failed to find $relPath');
-    }
-    dir = parent;
-  }
-}
-
-String findValue(File pubspec, String key) {
-  List<String> lines = pubspec.readAsLinesSync();
-  for (String line in lines) {
-    if (line.trim().startsWith('$key:')) {
-      return line.split(':')[1].trim();
-    }
-  }
-  fail('Failed to find $key in ${pubspec.path}');
-}
-
-void expectHasSuggestion(
-    List<DartFixSuggestion> suggestions, String expectedText) {
-  for (DartFixSuggestion suggestion in suggestions) {
-    if (suggestion.description.contains(expectedText)) {
-      return;
-    }
-  }
-  fail('Failed to find suggestion containing: $expectedText');
-}
-
 String replaceLeadingComment(String source) {
   final out = new StringBuffer('''
 // This file contains code that has been modified by running dartfix.
diff --git a/pkg/dartfix/test/src/options_test.dart b/pkg/dartfix/test/src/options_test.dart
index 7ce0e1a..971517a 100644
--- a/pkg/dartfix/test/src/options_test.dart
+++ b/pkg/dartfix/test/src/options_test.dart
@@ -24,7 +24,11 @@
     String errorOut,
     int exitCode,
     bool force = false,
+    List<String> includeFixes = const <String>[],
+    List<String> excludeFixes = const <String>[],
+    bool listFixes = false,
     String normalOut,
+    bool requiredFixes = false,
     bool overwrite = false,
     List<String> targetSuffixes,
     bool verbose = false,
@@ -47,7 +51,11 @@
       expect(actualExitCode, isNull, reason: 'exit code');
     }
     expect(options.force, force);
+    expect(options.requiredFixes, requiredFixes);
     expect(options.overwrite, overwrite);
+    expect(options.listFixes, listFixes);
+    expect(options.includeFixes, includeFixes);
+    expect(options.excludeFixes, excludeFixes);
     expect(options.verbose, verbose);
     expect(path.isAbsolute(options.sdkPath), isTrue, reason: options.sdkPath);
     for (String target in options.targets) {
@@ -62,6 +70,11 @@
     return options;
   }
 
+  test('exclude fix', () {
+    parse(['--exclude', 'c', '--exclude', 'd', 'foo'],
+        excludeFixes: ['c', 'd'], targetSuffixes: ['foo']);
+  });
+
   test('force', () {
     parse(['--force', 'foo'], force: true, targetSuffixes: ['foo']);
   });
@@ -70,6 +83,11 @@
     parse(['--help'], errorOut: 'Display this help message', exitCode: 1);
   });
 
+  test('include fix', () {
+    parse(['--include', 'a', '--include', 'b', 'foo'],
+        includeFixes: ['a', 'b'], targetSuffixes: ['foo']);
+  });
+
   test('invalid option', () {
     parse(['--foo'],
         errorOut: 'Could not find an option named "foo"', exitCode: 15);
@@ -89,10 +107,18 @@
         errorOut: 'Expected directory, but found', exitCode: 15);
   });
 
+  test('list fixes', () {
+    parse(['--list'], errorOut: 'Display this help message', listFixes: true);
+  });
+
   test('overwrite', () {
     parse(['--overwrite', 'foo'], overwrite: true, targetSuffixes: ['foo']);
   });
 
+  test('required fixes', () {
+    parse(['--required', 'foo'], requiredFixes: true);
+  });
+
   test('simple', () {
     parse(['foo'], targetSuffixes: ['foo']);
   });
diff --git a/pkg/dartfix/test/src/test_context.dart b/pkg/dartfix/test/src/test_context.dart
index 63d9357..39ab0b3 100644
--- a/pkg/dartfix/test/src/test_context.dart
+++ b/pkg/dartfix/test/src/test_context.dart
@@ -2,9 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
+import 'dart:io';
+
+import 'package:analysis_server_client/protocol.dart';
 import 'package:analyzer/src/test_utilities/resource_provider_mixin.dart';
 import 'package:cli_util/cli_logging.dart';
 import 'package:dartfix/src/context.dart';
+import 'package:test/test.dart';
 
 class TestContext with ResourceProviderMixin implements Context {
   @override
@@ -62,3 +66,47 @@
   @override
   void trace(String message) {}
 }
+
+void expectHasSuggestion(
+    List<DartFixSuggestion> suggestions, String expectedText) {
+  for (DartFixSuggestion suggestion in suggestions) {
+    if (suggestion.description.contains(expectedText)) {
+      return;
+    }
+  }
+  fail('Failed to find suggestion containing: $expectedText');
+}
+
+void expectDoesNotHaveSuggestion(
+    List<DartFixSuggestion> suggestions, String expectedText) {
+  for (DartFixSuggestion suggestion in suggestions) {
+    if (suggestion.description.contains(expectedText)) {
+      fail('Did not expect to find suggestion containing: $expectedText');
+    }
+  }
+}
+
+File findFile(String relPath) {
+  Directory dir = Directory.current;
+  while (true) {
+    final file = new File.fromUri(dir.uri.resolve(relPath));
+    if (file.existsSync()) {
+      return file;
+    }
+    final parent = dir.parent;
+    if (parent.path == dir.path) {
+      fail('Failed to find $relPath');
+    }
+    dir = parent;
+  }
+}
+
+String findValue(File pubspec, String key) {
+  List<String> lines = pubspec.readAsLinesSync();
+  for (String line in lines) {
+    if (line.trim().startsWith('$key:')) {
+      return line.split(':')[1].trim();
+    }
+  }
+  fail('Failed to find $key in ${pubspec.path}');
+}
diff --git a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
index ec56994..54e0f0f 100644
--- a/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
+++ b/pkg/dev_compiler/lib/src/analyzer/code_generator.dart
@@ -6422,10 +6422,10 @@
   visitWithClause(node) => _unreachable(node);
 
   @override
-  visitCollectionForElement(CollectionForElement node) => _unreachable(node);
+  visitForElement(ForElement node) => _unreachable(node);
 
   @override
-  visitCollectionIfElement(CollectionIfElement node) => _unreachable(node);
+  visitIfElement(IfElement node) => _unreachable(node);
 
   @override
   visitForEachPartsWithDeclaration(ForEachPartsWithDeclaration node) =>
@@ -6442,12 +6442,6 @@
   visitListLiteral2(ListLiteral2 node) => _unreachable(node);
 
   @override
-  visitMapForElement(MapForElement node) => _unreachable(node);
-
-  @override
-  visitMapIfElement(MapIfElement node) => _unreachable(node);
-
-  @override
   visitMapLiteral2(MapLiteral2 node) => _unreachable(node);
 
   @override
diff --git a/pkg/dev_compiler/lib/src/kernel/constants.dart b/pkg/dev_compiler/lib/src/kernel/constants.dart
index b05b840..0e9d692 100644
--- a/pkg/dev_compiler/lib/src/kernel/constants.dart
+++ b/pkg/dev_compiler/lib/src/kernel/constants.dart
@@ -14,12 +14,13 @@
 /// [evaluate] computes the value of a constant expression, if available.
 class DevCompilerConstants {
   final _ConstantVisitor _visitor;
-  final _ConstantEvaluator _evaluator;
+  final ConstantEvaluator _evaluator;
 
   DevCompilerConstants(
       TypeEnvironment types, Map<String, String> declaredVariables)
       : _visitor = _ConstantVisitor(types.coreTypes),
-        _evaluator = _ConstantEvaluator(types, declaredVariables);
+        _evaluator = ConstantEvaluator(DevCompilerConstantsBackend(),
+            declaredVariables, types, false, const _ErrorReporter());
 
   /// Determines if an expression is constant.
   bool isConstant(Expression e) => _visitor.isConstant(e);
@@ -36,7 +37,7 @@
 
     try {
       var result = cache ? _evaluator.evaluate(e) : e.accept(_evaluator);
-      return identical(result, _evaluator.unavailableConstant) ? null : result;
+      return result is UnevaluatedConstant ? null : result;
     } on _AbortCurrentEvaluation {
       // TODO(jmesserly): the try+catch is necessary because the front end is
       // not issuing sufficient errors, so the constant evaluation can fail.
@@ -167,147 +168,26 @@
   }
 }
 
-/// The visitor that evaluates constants, building on Kernel's
-/// [ConstantEvaluator] class (used by the VM) and fixing some of its behavior
-/// to work better for DDC.
-//
-// TODO(jmesserly): make some changes in the base class to make it a better fit
-// for compilers like DDC?
-class _ConstantEvaluator extends ConstantEvaluator {
-  final Map<String, String> declaredVariables;
-
-  /// Used to denote an unavailable constant value from another module
-  ///
-  // TODO(jmesserly): this happens when we try to evaluate constant values from
-  // an external library, that was from an outline kernel file. The kernel file
-  // does not contain the initializer value of the constant.
-  final Constant unavailableConstant;
-
-  _ConstantEvaluator(TypeEnvironment types, this.declaredVariables,
-      {bool enableAsserts: false})
-      : unavailableConstant = InstanceConstant(null, [], {}),
-        super(_ConstantsBackend(types.coreTypes), types, types.coreTypes,
-            enableAsserts, const _ErrorReporter()) {
-    env = EvaluationEnvironment();
-  }
+/// Implement the class for compiler specific behavior.
+class DevCompilerConstantsBackend extends ConstantsBackend {
+  DevCompilerConstantsBackend();
 
   @override
-  visitVariableGet(node) {
-    // The base evaluator expects that variable declarations are visited during
-    // the transformation step, so it doesn't handle constant variables.
-    // Instead handle them here.
-    if (node.variable.isConst) {
-      return evaluate(node.variable.initializer);
-    }
-    // Fall back to the base evaluator for other cases (e.g. parameters of a
-    // constant constructor).
-    return super.visitVariableGet(node);
-  }
-
-  @override
-  visitStaticGet(StaticGet node) {
-    // Handle unavailable field constants. This happens if an external library
-    // only has its outline available.
-    var target = node.target;
-    if (target is Field &&
-        target.isConst &&
-        target.isInExternalLibrary &&
-        target.initializer == null) {
-      return unavailableConstant;
-    }
-    return super.visitStaticGet(node);
-  }
-
-  @override
-  visitConstructorInvocation(ConstructorInvocation node) {
-    // Handle unavailable constructor bodies.
-    // This happens if an external library only has its outline available.
-    var target = node.target;
-    if (target.isConst &&
-        target.isInExternalLibrary &&
-        target.function.body is EmptyStatement &&
-        target.initializers.isEmpty) {
-      return unavailableConstant;
-    }
-    return super.visitConstructorInvocation(node);
-  }
-
-  @override
-  visitStaticInvocation(node) {
-    // Handle int/bool/String.fromEnvironment constructors.
-    //
-    // (The VM handles this via its `native` calls and implements it in
-    // VmConstantsBackend.buildConstantForNative.)
-    var target = node.target;
-    if (isFromEnvironmentInvocation(coreTypes, node)) {
-      var firstArg = evaluatePositionalArguments(node.arguments)[0];
-      var defaultArg = evaluateNamedArguments(node.arguments)['defaultValue'];
-
-      var varName = (firstArg as StringConstant).value;
-      var value = declaredVariables[varName];
-      var targetClass = target.enclosingClass;
-
-      if (targetClass == coreTypes.stringClass) {
-        if (value != null) return canonicalize(StringConstant(value));
-        return defaultArg ?? nullConstant;
-      } else if (targetClass == coreTypes.intClass) {
-        var intValue = int.tryParse(value ?? '');
-        if (intValue != null) return canonicalize(IntConstant(intValue));
-        return defaultArg ?? nullConstant;
-      } else if (targetClass == coreTypes.boolClass) {
-        if (value == "true") return trueConstant;
-        if (value == "false") return falseConstant;
-        return defaultArg ?? falseConstant;
-      }
-    }
-    return super.visitStaticInvocation(node);
-  }
-
-  @override
-  evaluateBinaryNumericOperation(String op, num a, num b, TreeNode node) {
-    // Use doubles to match JS number semantics.
-    return super
-        .evaluateBinaryNumericOperation(op, a.toDouble(), b.toDouble(), node);
-  }
-
-  @override
-  canonicalize(Constant constant) {
+  Constant lowerConstant(Constant constant) {
     if (constant is DoubleConstant) {
       // Convert to an integer when possible (matching the runtime behavior
       // of `is int`).
       var d = constant.value;
       if (d.isFinite) {
         var i = d.toInt();
-        if (d == i.toDouble()) return super.canonicalize(IntConstant(i));
+        if (d == i.toDouble()) return IntConstant(i);
       }
     }
-    return super.canonicalize(constant);
-  }
-}
-
-/// Implement the class for compiler specific behavior.
-///
-/// This is mostly unused by DDC, because we don't use the global constant
-/// transformer.
-class _ConstantsBackend implements ConstantsBackend {
-  final CoreTypes coreTypes;
-  final Field symbolNameField;
-
-  _ConstantsBackend(this.coreTypes)
-      : symbolNameField = coreTypes.internalSymbolClass.fields
-            .firstWhere((f) => f.name.name == '_name');
-
-  @override
-  buildConstantForNative(nativeName, typeArguments, positionalArguments,
-      namedArguments, context, node, errorReporter, abortEvaluation) {
-    throw StateError('unreachable'); // DDC does not use VM native syntax
+    return constant;
   }
 
-  @override
-  lowerMapConstant(constant) => constant;
-
-  @override
-  lowerListConstant(constant) => constant;
+  // Use doubles to match JS number semantics.
+  num prepareNumericOperand(num operand) => operand.toDouble();
 }
 
 class _ErrorReporter extends SimpleErrorReporter {
diff --git a/pkg/dev_compiler/lib/src/kernel/target.dart b/pkg/dev_compiler/lib/src/kernel/target.dart
index fdabc09..75aedd1 100644
--- a/pkg/dev_compiler/lib/src/kernel/target.dart
+++ b/pkg/dev_compiler/lib/src/kernel/target.dart
@@ -8,6 +8,8 @@
 import 'package:kernel/core_types.dart';
 import 'package:kernel/class_hierarchy.dart';
 import 'package:kernel/target/targets.dart';
+import 'package:kernel/transformations/constants.dart' show ConstantsBackend;
+import 'constants.dart' show DevCompilerConstantsBackend;
 import 'kernel_helpers.dart';
 
 /// A kernel [Target] to configure the Dart Front End for dartdevc.
@@ -146,6 +148,10 @@
     // TODO(sigmund): implement;
     return InvalidExpression(null);
   }
+
+  @override
+  ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
+      new DevCompilerConstantsBackend();
 }
 
 /// Analyzes a component to determine if any covariance checks in private
diff --git a/pkg/dev_compiler/pubspec.yaml b/pkg/dev_compiler/pubspec.yaml
index 86d997a..ea33a0b 100644
--- a/pkg/dev_compiler/pubspec.yaml
+++ b/pkg/dev_compiler/pubspec.yaml
@@ -1 +1,20 @@
 name: dev_compiler
+publish_to: none
+
+environment:
+  sdk: '>=2.1.0 <3.0.0'
+
+dependencies:
+  analyzer: any
+  bazel_worker: any
+  build_integration:
+    path: ../build_integration
+  cli_util: any
+  source_maps: any
+
+dev_dependencies:
+  sourcemap_testing:
+    path: ../sourcemap_testing
+  test: any
+  testing:
+    path: ../testing
diff --git a/pkg/dev_compiler/tool/ddb b/pkg/dev_compiler/tool/ddb
index 3e045cc..ea3a7a5 100755
--- a/pkg/dev_compiler/tool/ddb
+++ b/pkg/dev_compiler/tool/ddb
@@ -36,6 +36,10 @@
         help: 'Platform to run on (node|d8|chrome).  Default is node.',
         allowed: ['node', 'd8', 'chrome'],
         defaultsTo: 'node')
+    ..addOption('port',
+        abbr: 'p',
+        help: 'Run with the corresponding chrome/V8 debugging port open.',
+        defaultsTo: '9222')
     ..addOption('binary', abbr: 'b', help: 'Runtime binary path.');
 
   var options = parser.parse(args);
@@ -49,6 +53,7 @@
   var debug = options['debug'] as bool;
   var kernel = options['kernel'] as bool;
   var binary = options['binary'] as String;
+  var port = int.parse(options['port'] as String);
 
   var dartBinary = Platform.resolvedExecutable;
   var dartPath = path.dirname(dartBinary);
@@ -175,10 +180,13 @@
     new File(htmlFile).writeAsStringSync(html);
     var tmp = path.join(Directory.systemTemp.path, 'ddc');
 
-    result = Process.runSync(chromeBinary,
-        ['--auto-open-devtools-for-tabs',
-         '--allow-file-access-from-files',
-         '--user-data-dir=$tmp', htmlFile]);
+    result = Process.runSync(chromeBinary, [
+      '--auto-open-devtools-for-tabs',
+      '--allow-file-access-from-files',
+      '--remote-debugging-port=$port',
+      '--user-data-dir=$tmp',
+      htmlFile
+    ]);
   } else if (node) {
     var nodePath = '$sdkJsPath:$libRoot';
     var runjs = '''
@@ -204,8 +212,9 @@
     var nodeFile = '$libRoot/$basename.run.js';
     new File(nodeFile).writeAsStringSync(runjs);
     var nodeBinary = binary ?? 'node';
-    result = Process
-        .runSync(nodeBinary, [nodeFile], environment: {'NODE_PATH': nodePath});
+    result = Process.runSync(
+        nodeBinary, ['--inspect=localhost:$port', nodeFile],
+        environment: {'NODE_PATH': nodePath});
     stdout
       ..write(result.stdout)
       ..flush();
diff --git a/pkg/dev_compiler/tool/input_sdk/libraries.dart b/pkg/dev_compiler/tool/input_sdk/libraries.dart
index 6009d0c..1a08e42 100644
--- a/pkg/dev_compiler/tool/input_sdk/libraries.dart
+++ b/pkg/dev_compiler/tool/input_sdk/libraries.dart
@@ -61,6 +61,11 @@
       categories: "Client,Server,Embedded",
       maturity: Maturity.UNSTABLE,
       dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"),
+  "ffi": const LibraryInfo("ffi/ffi.dart",
+      categories: "Server",
+      // TODO(dacoharkes): Update maturity when we release dart:ffi.
+      // https://github.com/dart-lang/sdk/issues/34452
+      maturity: Maturity.EXPERIMENTAL),
   "html": const LibraryInfo("html/dart2js/html_dart2js.dart",
       categories: "Client",
       maturity: Maturity.WEB_STABLE,
diff --git a/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart b/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
index 983bbcd..fe36fea 100644
--- a/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
+++ b/pkg/dev_compiler/tool/input_sdk/patch/async_patch.dart
@@ -5,8 +5,7 @@
 // Patch file for the dart:async library.
 
 import 'dart:_js_helper' show notNull, patch, ReifyFunctionTypes;
-import 'dart:_isolate_helper'
-    show TimerImpl, global, leaveJsAsync, enterJsAsync;
+import 'dart:_isolate_helper' show TimerImpl;
 import 'dart:_foreign_helper' show JS, JSExportName;
 import 'dart:_runtime' as dart;
 
@@ -147,32 +146,30 @@
   static _TakeCallback _initializeScheduleImmediate() {
     // TODO(rnystrom): Not needed by dev_compiler.
     // requiresPreamble();
-    if (JS('', '#.scheduleImmediate', global) != null) {
+    if (JS('', '#.scheduleImmediate', dart.global_) != null) {
       return _scheduleImmediateJsOverride;
     }
-    if (JS('', '#.MutationObserver', global) != null &&
-        JS('', '#.document', global) != null) {
+    if (JS('', '#.MutationObserver', dart.global_) != null &&
+        JS('', '#.document', dart.global_) != null) {
       // Use mutationObservers.
-      var div = JS('', '#.document.createElement("div")', global);
-      var span = JS('', '#.document.createElement("span")', global);
+      var div = JS('', '#.document.createElement("div")', dart.global_);
+      var span = JS('', '#.document.createElement("span")', dart.global_);
       _Callback storedCallback;
 
       internalCallback(_) {
-        leaveJsAsync();
         var f = storedCallback;
         storedCallback = null;
+        dart.removeAsyncCallback();
         f();
       }
 
-      ;
-
       var observer =
-          JS('', 'new #.MutationObserver(#)', global, internalCallback);
+          JS('', 'new #.MutationObserver(#)', dart.global_, internalCallback);
       JS('', '#.observe(#, { childList: true })', observer, div);
 
       return (void callback()) {
         assert(storedCallback == null);
-        enterJsAsync();
+        dart.addAsyncCallback();
         storedCallback = callback;
         // Because of a broken shadow-dom polyfill we have to change the
         // children instead a cheap property.
@@ -180,7 +177,7 @@
         JS('', '#.firstChild ? #.removeChild(#): #.appendChild(#)', div, div,
             span, div, span);
       };
-    } else if (JS('', '#.setImmediate', global) != null) {
+    } else if (JS('', '#.setImmediate', dart.global_) != null) {
       return _scheduleImmediateWithSetImmediate;
     }
     // TODO(20055): We should use DOM promises when available.
@@ -189,24 +186,22 @@
 
   static void _scheduleImmediateJsOverride(void callback()) {
     internalCallback() {
-      leaveJsAsync();
+      dart.removeAsyncCallback();
       callback();
     }
 
-    ;
-    enterJsAsync();
-    JS('void', '#.scheduleImmediate(#)', global, internalCallback);
+    dart.addAsyncCallback();
+    JS('void', '#.scheduleImmediate(#)', dart.global_, internalCallback);
   }
 
   static void _scheduleImmediateWithSetImmediate(void callback()) {
     internalCallback() {
-      leaveJsAsync();
+      dart.removeAsyncCallback();
       callback();
     }
 
-    ;
-    enterJsAsync();
-    JS('void', '#.setImmediate(#)', global, internalCallback);
+    dart.addAsyncCallback();
+    JS('void', '#.setImmediate(#)', dart.global_, internalCallback);
   }
 
   static void _scheduleImmediateWithTimer(void callback()) {
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 116464a..5eaff1c 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
@@ -181,3 +181,18 @@
   JS('', '#.clear()', constantMaps);
   JS('', '#.clear()', _ignoreSubtypeCache);
 }
+
+/// Marks enqueuing an async operation.
+///
+/// This will be called by library code when enqueuing an async operation
+/// controlled by the JavaScript event handler.
+///
+/// It will also call [removeAsyncCallback] when Dart callback is about to be
+/// executed (note this is called *before* the callback executes, so more
+/// async operations could be added from that).
+void Function() addAsyncCallback = JS('', 'function() {}');
+
+/// Marks leaving a javascript async operation.
+///
+/// See [addAsyncCallback].
+void Function() removeAsyncCallback = JS('', 'function() {}');
diff --git a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
index 6ee554b..63849d8 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/debugger.dart
@@ -679,7 +679,11 @@
 
   String preview(object) {
     Map map = object;
-    return '${getObjectTypeName(map)} length ${map.length}';
+    try {
+      return '${getObjectTypeName(map)} length ${map.length}';
+    } catch (e) {
+      return safePreview(object, JsonMLConfig.none);
+    }
   }
 
   List<NameValuePair> children(object) {
diff --git a/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart b/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
index 6de83f2..6f98394 100644
--- a/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
+++ b/pkg/dev_compiler/tool/input_sdk/private/isolate_helper.dart
@@ -8,27 +8,6 @@
 import 'dart:async';
 import 'dart:_foreign_helper' show JS;
 
-/// Marks entering a JavaScript async operation to keep the worker alive.
-///
-/// To be called by library code before starting an async operation controlled
-/// by the JavaScript event handler.
-///
-/// Also call [leaveJsAsync] in all callback handlers marking the end of that
-/// async operation (also error handlers) so the worker can be released.
-///
-/// These functions only has to be called for code that can be run from a
-/// worker-isolate (so not for general dom operations).
-///
-// TODO(jmesserly): we could potentially use this to track when all async
-// operations have completed, for example, to run a bunch of test `main()`
-// methods in batch mode the same V8 process.
-enterJsAsync() {}
-
-/// Marks leaving a javascript async operation.
-///
-/// See [enterJsAsync].
-leaveJsAsync() {}
-
 /// Deprecated way of initializing `main()` in DDC, typically called from JS.
 @deprecated
 void startRootIsolate(main, args) {
@@ -62,12 +41,12 @@
     if (hasTimer()) {
       void internalCallback() {
         _handle = null;
-        leaveJsAsync();
+        dart.removeAsyncCallback();
         _tick = 1;
         callback();
       }
 
-      enterJsAsync();
+      dart.addAsyncCallback();
 
       _handle = JS(
           'int', '#.setTimeout(#, #)', global, internalCallback, milliseconds);
@@ -79,7 +58,7 @@
   TimerImpl.periodic(int milliseconds, void callback(Timer timer))
       : _once = false {
     if (hasTimer()) {
-      enterJsAsync();
+      dart.addAsyncCallback();
       int start = JS('int', 'Date.now()');
       _handle = JS('int', '#.setInterval(#, #)', global, () {
         int tick = this._tick + 1;
@@ -102,7 +81,7 @@
   void cancel() {
     if (hasTimer()) {
       if (_handle == null) return;
-      leaveJsAsync();
+      dart.removeAsyncCallback();
       if (_once) {
         JS('void', '#.clearTimeout(#)', global, _handle);
       } else {
diff --git a/pkg/expect/lib/matchers_lite.dart b/pkg/expect/lib/matchers_lite.dart
new file mode 100644
index 0000000..004e37e
--- /dev/null
+++ b/pkg/expect/lib/matchers_lite.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.
+
+/// This library is supposed help to remove dependencies on package:test from
+/// an existing test.
+///
+/// Feel free to add more matchers, as long as they remain lite. Batteries
+/// aren't included here. This is intended to be used in low-level platform
+/// tests and shouldn't rely on advanced features such as reflection. Using
+/// asynchronous code is acceptable, but only for testing code that is
+/// *already* asynchronous, but try to avoid using "async" and other generators
+/// (it's hard testing the implemention of generators if the test
+/// infrastructure relies on them itself).
+library expect.matchers_lite;
+
+import "expect.dart" show Expect;
+
+typedef Matcher = void Function(Object actual);
+
+void expect(Object actual, Object expected) {
+  if (expected is Matcher) {
+    expected(actual);
+  } else {
+    equals(expected)(actual);
+  }
+}
+
+Matcher unorderedEquals(Iterable<Object> expected) {
+  return (Object actual) => Expect.setEquals(expected, actual);
+}
+
+fail(String message) {
+  Expect.fail(message);
+}
+
+Matcher same(Object expected) {
+  return (Object actual) => Expect.identical(expected, actual);
+}
+
+Matcher equals(Object expected) {
+  if (expected is String) {
+    return (Object actual) => Expect.stringEquals(expected, actual);
+  } else if (expected is Iterable<Object>) {
+    return (dynamic actual) =>
+        Expect.listEquals(expected.toList(), actual.toList());
+  } else {
+    return (Object actual) => Expect.equals(expected, actual);
+  }
+}
+
+final Matcher isEmpty = (dynamic actual) => Expect.isTrue(actual.isEmpty);
+
+final Matcher isNull = (Object actual) => Expect.isNull(actual);
diff --git a/pkg/front_end/analysis_options.yaml b/pkg/front_end/analysis_options.yaml
index 0fb6ccc..2b7dca6 100644
--- a/pkg/front_end/analysis_options.yaml
+++ b/pkg/front_end/analysis_options.yaml
@@ -8,6 +8,3 @@
   errors:
     # Allow having TODOs in the code
     todo: ignore
-
-    # Allow deprecated calls from within the same package
-    deprecated_member_use_from_same_package: ignore
diff --git a/pkg/front_end/lib/src/api_prototype/compiler_options.dart b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
index 5211c44..e867b2c 100644
--- a/pkg/front_end/lib/src/api_prototype/compiler_options.dart
+++ b/pkg/front_end/lib/src/api_prototype/compiler_options.dart
@@ -127,6 +127,12 @@
   /// Features not mentioned in the map will have their default value.
   Map<ExperimentalFlag, bool> experimentalFlags = <ExperimentalFlag, bool>{};
 
+  /// Environment map used when evaluating `bool.fromEnvironment`,
+  /// `int.fromEnvironment` and `String.fromEnvironment` during constant
+  /// evaluation. If the map is `null`, all environment constants will be left
+  /// unevaluated and can be evaluated by a constant evaluator later.
+  Map<String, String> environmentDefines = null;
+
   /// The target platform that will consume the compiled code.
   ///
   /// Used to provide platform-specific details to the compiler like:
diff --git a/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart b/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart
index e34b709..47c30f0 100644
--- a/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart
+++ b/pkg/front_end/lib/src/api_prototype/diagnostic_message.dart
@@ -4,7 +4,8 @@
 
 library front_end.diagnostic_message;
 
-import '../fasta/fasta_codes.dart' show Code, FormattedMessage;
+import '../fasta/fasta_codes.dart'
+    show Code, DiagnosticMessageFromJson, FormattedMessage;
 
 import '../fasta/severity.dart' show Severity;
 
@@ -38,7 +39,19 @@
 
 /// This method is subject to change.
 Uri getMessageUri(DiagnosticMessage message) {
-  return message is FormattedMessage ? message.uri : null;
+  return message is FormattedMessage
+      ? message.uri
+      : message is DiagnosticMessageFromJson ? message.uri : null;
+}
+
+/// This method is subject to change.
+int getMessageCharOffset(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.charOffset : null;
+}
+
+/// This method is subject to change.
+int getMessageLength(DiagnosticMessage message) {
+  return message is FormattedMessage ? message.length : null;
 }
 
 /// This method is subject to change.
@@ -60,3 +73,9 @@
 Map<String, dynamic> getMessageArguments(DiagnosticMessage message) {
   return message is FormattedMessage ? message.arguments : null;
 }
+
+/// This method is subject to change.
+Iterable<DiagnosticMessage> getMessageRelatedInformation(
+    DiagnosticMessage message) {
+  return message is FormattedMessage ? message.relatedInformation : null;
+}
diff --git a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
index 1441108..a9b772d 100644
--- a/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
+++ b/pkg/front_end/lib/src/api_prototype/experimental_flags.dart
@@ -5,16 +5,22 @@
 // TODO(askesc): Generate this file from a flag specification.
 
 enum ExperimentalFlag {
-  setLiterals,
   constantUpdate2018,
+  controlFlowCollections,
+  setLiterals,
+  spreadCollections,
 }
 
 ExperimentalFlag parseExperimentalFlag(String flag) {
   switch (flag) {
-    case "set-literals":
-      return ExperimentalFlag.setLiterals;
     case "constant-update-2018":
       return ExperimentalFlag.constantUpdate2018;
+    case "control-flow-collections":
+      return ExperimentalFlag.controlFlowCollections;
+    case "set-literals":
+      return ExperimentalFlag.setLiterals;
+    case "spread-collections":
+      return ExperimentalFlag.spreadCollections;
   }
   return null;
 }
diff --git a/pkg/front_end/lib/src/api_unstable/dart2js.dart b/pkg/front_end/lib/src/api_unstable/dart2js.dart
index 188c88b..d716845 100644
--- a/pkg/front_end/lib/src/api_unstable/dart2js.dart
+++ b/pkg/front_end/lib/src/api_unstable/dart2js.dart
@@ -35,7 +35,14 @@
 export '../api_prototype/compiler_options.dart'
     show CompilerOptions, parseExperimentalFlags;
 
-export '../api_prototype/diagnostic_message.dart' show DiagnosticMessage;
+export '../api_prototype/diagnostic_message.dart'
+    show
+        DiagnosticMessage,
+        getMessageCharOffset,
+        getMessageHeaderText,
+        getMessageLength,
+        getMessageRelatedInformation,
+        getMessageUri;
 
 export '../api_prototype/experimental_flags.dart' show ExperimentalFlag;
 
@@ -49,8 +56,6 @@
 export '../compute_platform_binaries_location.dart'
     show computePlatformBinariesLocation;
 
-export '../fasta/fasta_codes.dart' show FormattedMessage;
-
 export '../fasta/kernel/redirecting_factory_body.dart'
     show RedirectingFactoryBody;
 
diff --git a/pkg/front_end/lib/src/api_unstable/vm.dart b/pkg/front_end/lib/src/api_unstable/vm.dart
index 5d7cd8c..e7c5bcd 100644
--- a/pkg/front_end/lib/src/api_unstable/vm.dart
+++ b/pkg/front_end/lib/src/api_unstable/vm.dart
@@ -53,10 +53,13 @@
         templateConstEvalNonConstantLiteral,
         templateConstEvalNonConstantVariableGet,
         templateConstEvalZeroDivisor,
-        templateFfiAnnotationMissing,
+        templateFfiFieldAnnotation,
+        templateFfiStructAnnotation,
+        templateFfiNotStatic,
         templateFfiTypeInvalid,
         templateFfiTypeMismatch,
-        templateFfiTypeOpaque;
+        templateFfiTypeUnsized,
+        templateFfiFieldInitializer;
 
 export '../fasta/hybrid_file_system.dart' show HybridFileSystem;
 
diff --git a/pkg/front_end/lib/src/base/processed_options.dart b/pkg/front_end/lib/src/base/processed_options.dart
index 4ef234d..82804be 100644
--- a/pkg/front_end/lib/src/base/processed_options.dart
+++ b/pkg/front_end/lib/src/base/processed_options.dart
@@ -177,10 +177,14 @@
   /// The Uri where output is generated, may be null.
   final Uri output;
 
+  final Map<String, String> environmentDefines;
+
   /// Initializes a [ProcessedOptions] object wrapping the given [rawOptions].
   ProcessedOptions({CompilerOptions options, List<Uri> inputs, this.output})
       : this._raw = options ?? new CompilerOptions(),
         this.inputs = inputs ?? <Uri>[],
+        // TODO(askesc): Copy the map when kernel_service supports that.
+        this.environmentDefines = options?.environmentDefines,
         // TODO(sigmund, ahe): create ticker even earlier or pass in a stopwatch
         // collecting time since the start of the VM.
         this.ticker = new Ticker(isVerbose: options?.verbose ?? false);
@@ -212,14 +216,17 @@
     if (CompilerContext.current.options.setExitCodeOnProblem) {
       exitCode = 1;
     }
-    (_raw.onDiagnostic ??
-        _defaultDiagnosticMessageHandler)(format(message, severity, context));
+    reportDiagnosticMessage(format(message, severity, context));
     if (command_line_reporting.shouldThrowOn(severity)) {
       throw new DebugAbort(
           message.uri, message.charOffset, severity, StackTrace.current);
     }
   }
 
+  void reportDiagnosticMessage(DiagnosticMessage message) {
+    (_raw.onDiagnostic ?? _defaultDiagnosticMessageHandler)(message);
+  }
+
   void _defaultDiagnosticMessageHandler(DiagnosticMessage message) {
     printDiagnosticMessage(message, print);
   }
@@ -300,6 +307,7 @@
 
   bool isExperimentEnabled(ExperimentalFlag flag) {
     // TODO(askesc): Determine default flag value from specification file.
+    if (flag == ExperimentalFlag.setLiterals) return true;
     return _raw.experimentalFlags[flag] ?? false;
   }
 
diff --git a/pkg/front_end/lib/src/fasta/builder/builder.dart b/pkg/front_end/lib/src/fasta/builder/builder.dart
index 70b361c..cce01a4 100644
--- a/pkg/front_end/lib/src/fasta/builder/builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/builder.dart
@@ -30,8 +30,6 @@
 
 export 'formal_parameter_builder.dart' show FormalParameterBuilder;
 
-export 'function_type_alias_builder.dart' show FunctionTypeAliasBuilder;
-
 export 'function_type_builder.dart' show FunctionTypeBuilder;
 
 export 'invalid_type_builder.dart' show InvalidTypeBuilder;
@@ -54,6 +52,8 @@
 
 export 'procedure_builder.dart' show ProcedureBuilder;
 
+export 'type_alias_builder.dart' show TypeAliasBuilder;
+
 export 'type_builder.dart' show TypeBuilder;
 
 export 'type_declaration_builder.dart' show TypeDeclarationBuilder;
diff --git a/pkg/front_end/lib/src/fasta/builder/function_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/function_type_alias_builder.dart
deleted file mode 100644
index 7abb3f3..0000000
--- a/pkg/front_end/lib/src/fasta/builder/function_type_alias_builder.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-library fasta.function_type_alias_builder;
-
-import 'builder.dart'
-    show
-        LibraryBuilder,
-        MetadataBuilder,
-        TypeBuilder,
-        TypeDeclarationBuilder,
-        TypeVariableBuilder;
-
-abstract class FunctionTypeAliasBuilder<T extends TypeBuilder, R>
-    extends TypeDeclarationBuilder<T, R> {
-  final T type;
-
-  final List<TypeVariableBuilder> typeVariables;
-
-  FunctionTypeAliasBuilder(List<MetadataBuilder> metadata, String name,
-      this.typeVariables, this.type, LibraryBuilder parent, int charOffset)
-      : super(metadata, null, name, parent, charOffset);
-
-  String get debugName => "FunctionTypeAliasBuilder";
-
-  LibraryBuilder get parent => super.parent;
-
-  int get typeVariablesCount;
-}
diff --git a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
index 16fc417..cb656b4 100644
--- a/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/metadata_builder.dart
@@ -10,20 +10,21 @@
 
 abstract class MetadataBuilder<T extends TypeBuilder> {
   final int charOffset;
+
   MetadataBuilder(Declaration parent, this.charOffset);
 
   factory MetadataBuilder.fromConstructor(
       ConstructorReferenceBuilder constructorReference,
-      List arguments,
+      List<Object> arguments,
       Declaration parent,
       int charOffset) {
-    return new ConstructorMetadataBuilder(
+    return new ConstructorMetadataBuilder<T>(
         constructorReference, arguments, parent, charOffset);
   }
 
   factory MetadataBuilder.fromExpression(
       Object expression, String postfix, Declaration parent, int charOffset) {
-    return new ExpressionMetadataBuilder(
+    return new ExpressionMetadataBuilder<T>(
         expression, postfix, parent, charOffset);
   }
 }
@@ -32,7 +33,7 @@
     extends MetadataBuilder<T> {
   final ConstructorReferenceBuilder constructorReference;
 
-  final List arguments;
+  final List<Object> arguments;
 
   ConstructorMetadataBuilder(this.constructorReference, this.arguments,
       Declaration parent, int charOffset)
diff --git a/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
new file mode 100644
index 0000000..e941212
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/builder/type_alias_builder.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library fasta.function_type_alias_builder;
+
+import 'builder.dart'
+    show
+        LibraryBuilder,
+        MetadataBuilder,
+        TypeBuilder,
+        TypeDeclarationBuilder,
+        TypeVariableBuilder;
+
+abstract class TypeAliasBuilder<T extends TypeBuilder, R>
+    extends TypeDeclarationBuilder<T, R> {
+  final T type;
+
+  final List<TypeVariableBuilder<T, R>> typeVariables;
+
+  TypeAliasBuilder(
+      List<MetadataBuilder<T>> metadata,
+      String name,
+      this.typeVariables,
+      this.type,
+      LibraryBuilder<T, Object> parent,
+      int charOffset)
+      : super(metadata, null, name, parent, charOffset);
+
+  String get debugName => "TypeAliasBuilder";
+
+  LibraryBuilder<T, Object> get parent => super.parent;
+
+  int get typeVariablesCount;
+}
diff --git a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
index e4f8c41..b28cf9f 100644
--- a/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
+++ b/pkg/front_end/lib/src/fasta/builder/type_declaration_builder.dart
@@ -14,7 +14,7 @@
 
 abstract class TypeDeclarationBuilder<T extends TypeBuilder, R>
     extends ModifierBuilder {
-  final List<MetadataBuilder> metadata;
+  final List<MetadataBuilder<T>> metadata;
 
   final int modifiers;
 
@@ -34,8 +34,9 @@
 
   int get typeVariablesCount => 0;
 
-  R buildType(LibraryBuilder library, List<T> arguments);
+  R buildType(LibraryBuilder<T, Object> library, List<T> arguments);
 
   /// [arguments] have already been built.
-  R buildTypesWithBuiltArguments(LibraryBuilder library, List<R> arguments);
+  R buildTypesWithBuiltArguments(
+      LibraryBuilder<T, Object> library, List<R> arguments);
 }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
index 89fb431..fd0a4d2 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_class_builder.dart
@@ -105,6 +105,19 @@
     return computeTypeBuilder(library, cls.mixedInType);
   }
 
+  List<KernelTypeBuilder> get interfaces {
+    if (cls.implementedTypes.isEmpty) return null;
+    if (super.interfaces == null) {
+      List<KernelTypeBuilder> result =
+          new List<KernelTypeBuilder>(cls.implementedTypes.length);
+      for (int i = 0; i < result.length; i++) {
+        result[i] = computeTypeBuilder(library, cls.implementedTypes[i]);
+      }
+      super.interfaces = result;
+    }
+    return super.interfaces;
+  }
+
   void set mixedInType(KernelTypeBuilder mixin) {
     unimplemented("mixedInType=", -1, null);
   }
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
index 92b5c40..610dcea 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_library_builder.dart
@@ -48,7 +48,7 @@
 
 import 'dill_loader.dart' show DillLoader;
 
-import 'dill_typedef_builder.dart' show DillFunctionTypeAliasBuilder;
+import 'dill_type_alias_builder.dart' show DillTypeAliasBuilder;
 
 class DillLibraryBuilder extends LibraryBuilder<KernelTypeBuilder, Library> {
   final Library library;
@@ -64,6 +64,9 @@
   DillLibraryBuilder(this.library, this.loader)
       : super(library.fileUri, new Scope.top(), new Scope.top());
 
+  @override
+  bool get isSynthetic => library.isSynthetic;
+
   Uri get uri => library.importUri;
 
   Uri get fileUri => library.fileUri;
@@ -132,17 +135,12 @@
   }
 
   void addTypedef(Typedef typedef) {
-    DartType alias = typedef.type;
-    if (alias is FunctionType) {
-      if (alias.typedefType == null) {
-        unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
-      }
-      addBuilder(typedef.name, new DillFunctionTypeAliasBuilder(typedef, this),
-          typedef.fileOffset);
-    } else {
-      unhandled("${alias.runtimeType}", "addTypedef", typedef.fileOffset,
-          typedef.fileUri);
+    DartType type = typedef.type;
+    if (type is FunctionType && type.typedefType == null) {
+      unhandled("null", "addTypedef", typedef.fileOffset, typedef.fileUri);
     }
+    addBuilder(typedef.name, new DillTypeAliasBuilder(typedef, this),
+        typedef.fileOffset);
   }
 
   @override
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
index ccda959..aa5785b 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_loader.dart
@@ -6,34 +6,15 @@
 
 import 'dart:async' show Future;
 
-import 'package:kernel/ast.dart'
-    show
-        BottomType,
-        Class,
-        Component,
-        DartType,
-        DartTypeVisitor,
-        DynamicType,
-        FunctionType,
-        InterfaceType,
-        InvalidType,
-        Library,
-        TypeParameter,
-        TypeParameterType,
-        TypedefType,
-        VoidType;
+import 'package:kernel/ast.dart' show Class, Component, DartType, Library;
 
 import '../fasta_codes.dart'
     show SummaryTemplate, Template, templateDillOutlineSummary;
 
 import '../kernel/kernel_builder.dart'
-    show
-        DynamicTypeBuilder,
-        KernelNamedTypeBuilder,
-        KernelTypeBuilder,
-        KernelTypeVariableBuilder,
-        LibraryBuilder,
-        VoidTypeBuilder;
+    show KernelClassBuilder, KernelTypeBuilder, LibraryBuilder;
+
+import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
 
 import '../loader.dart' show Loader;
 
@@ -41,8 +22,6 @@
 
 import '../target_implementation.dart' show TargetImplementation;
 
-import 'dill_class_builder.dart' show DillClassBuilder;
-
 import 'dill_library_builder.dart' show DillLibraryBuilder;
 
 import 'dill_target.dart' show DillTarget;
@@ -99,71 +78,15 @@
     });
   }
 
+  @override
+  KernelClassBuilder computeClassBuilderFromTargetClass(Class cls) {
+    Library kernelLibrary = cls.enclosingLibrary;
+    LibraryBuilder library = builders[kernelLibrary.importUri];
+    return library[cls.name];
+  }
+
+  @override
   KernelTypeBuilder computeTypeBuilder(DartType type) {
     return type.accept(new TypeBuilderComputer(this));
   }
 }
-
-class TypeBuilderComputer implements DartTypeVisitor<KernelTypeBuilder> {
-  final DillLoader loader;
-
-  const TypeBuilderComputer(this.loader);
-
-  KernelTypeBuilder defaultDartType(DartType node) {
-    throw "Unsupported";
-  }
-
-  KernelTypeBuilder visitInvalidType(InvalidType node) {
-    throw "Not implemented";
-  }
-
-  KernelTypeBuilder visitDynamicType(DynamicType node) {
-    return new KernelNamedTypeBuilder("dynamic", null)
-      ..bind(new DynamicTypeBuilder<KernelTypeBuilder, DartType>(
-          const DynamicType(), loader.coreLibrary, -1));
-  }
-
-  KernelTypeBuilder visitVoidType(VoidType node) {
-    return new KernelNamedTypeBuilder("void", null)
-      ..bind(new VoidTypeBuilder<KernelTypeBuilder, VoidType>(
-          const VoidType(), loader.coreLibrary, -1));
-  }
-
-  KernelTypeBuilder visitBottomType(BottomType node) {
-    throw "Not implemented";
-  }
-
-  KernelTypeBuilder visitInterfaceType(InterfaceType node) {
-    Class kernelClass = node.classNode;
-    Library kernelLibrary = kernelClass.enclosingLibrary;
-    DillLibraryBuilder library = loader.builders[kernelLibrary.importUri];
-    String name = kernelClass.name;
-    DillClassBuilder cls = library[name];
-    List<KernelTypeBuilder> arguments;
-    List<DartType> kernelArguments = node.typeArguments;
-    if (kernelArguments.isNotEmpty) {
-      arguments = new List<KernelTypeBuilder>(kernelArguments.length);
-      for (int i = 0; i < kernelArguments.length; i++) {
-        arguments[i] = kernelArguments[i].accept(this);
-      }
-    }
-    return new KernelNamedTypeBuilder(name, arguments)..bind(cls);
-  }
-
-  KernelTypeBuilder visitFunctionType(FunctionType node) {
-    throw "Not implemented";
-  }
-
-  KernelTypeBuilder visitTypeParameterType(TypeParameterType node) {
-    TypeParameter parameter = node.parameter;
-    Class kernelClass = parameter.parent;
-    Library kernelLibrary = kernelClass.enclosingLibrary;
-    DillLibraryBuilder library = loader.builders[kernelLibrary.importUri];
-    return new KernelNamedTypeBuilder(parameter.name, null)
-      ..bind(new KernelTypeVariableBuilder.fromKernel(parameter, library));
-  }
-
-  KernelTypeBuilder visitTypedefType(TypedefType node) {
-    throw "Not implemented";
-  }
-}
diff --git a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
similarity index 76%
rename from pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
rename to pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
index a395dca..6667e06 100644
--- a/pkg/front_end/lib/src/fasta/dill/dill_typedef_builder.dart
+++ b/pkg/front_end/lib/src/fasta/dill/dill_type_alias_builder.dart
@@ -4,11 +4,11 @@
 
 library fasta.dill_typedef_builder;
 
-import 'package:kernel/ast.dart' show DartType, Typedef;
+import 'package:kernel/ast.dart' show DartType, Library, Typedef;
 
 import '../kernel/kernel_builder.dart'
     show
-        KernelFunctionTypeAliasBuilder,
+        KernelTypeAliasBuilder,
         KernelFunctionTypeBuilder,
         KernelTypeBuilder,
         LibraryBuilder,
@@ -18,12 +18,12 @@
 
 import 'dill_library_builder.dart' show DillLibraryBuilder;
 
-class DillFunctionTypeAliasBuilder extends KernelFunctionTypeAliasBuilder {
-  DillFunctionTypeAliasBuilder(Typedef typedef, DillLibraryBuilder parent)
+class DillTypeAliasBuilder extends KernelTypeAliasBuilder {
+  DillTypeAliasBuilder(Typedef typedef, DillLibraryBuilder parent)
       : super(null, typedef.name, null, null, parent, typedef.fileOffset,
             typedef);
 
-  List<MetadataBuilder> get metadata {
+  List<MetadataBuilder<KernelTypeBuilder>> get metadata {
     return unimplemented("metadata", -1, null);
   }
 
@@ -36,11 +36,14 @@
   }
 
   @override
-  DartType buildThisType(LibraryBuilder library) => thisType ??= target.type;
+  DartType buildThisType(LibraryBuilder<KernelTypeBuilder, Library> library) {
+    return thisType ??= target.type;
+  }
 
   @override
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<KernelTypeBuilder> arguments) {
+      LibraryBuilder<KernelTypeBuilder, Library> library,
+      List<KernelTypeBuilder> arguments) {
     // For performance reasons, [typeVariables] aren't restored from [target].
     // So, if [arguments] is null, the default types should be retrieved from
     // [cls.typeParameters].
diff --git a/pkg/front_end/lib/src/fasta/fasta_codes.dart b/pkg/front_end/lib/src/fasta/fasta_codes.dart
index fb721dd..322c728 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes.dart
@@ -4,7 +4,7 @@
 
 library fasta.codes;
 
-import 'dart:convert' show JsonEncoder;
+import 'dart:convert' show JsonEncoder, json;
 
 import 'package:kernel/ast.dart'
     show Constant, DartType, demangleMixinApplicationName;
@@ -185,10 +185,56 @@
   }
 
   Map<String, Object> toJson() {
-    // The should be kept in sync with package:kernel/problems.md
+    // This should be kept in sync with package:kernel/problems.md
     return <String, Object>{
       "ansiFormatted": ansiFormatted.toList(),
       "plainTextFormatted": plainTextFormatted.toList(),
+      "severity": severity.index,
+      "uri": uri.toString(),
+    };
+  }
+
+  String toJsonString() {
+    JsonEncoder encoder = new JsonEncoder.withIndent("  ");
+    return encoder.convert(this);
+  }
+}
+
+class DiagnosticMessageFromJson implements DiagnosticMessage {
+  @override
+  final Iterable<String> ansiFormatted;
+
+  @override
+  final Iterable<String> plainTextFormatted;
+
+  @override
+  final Severity severity;
+
+  final Uri uri;
+
+  DiagnosticMessageFromJson(
+      this.ansiFormatted, this.plainTextFormatted, this.severity, this.uri);
+
+  factory DiagnosticMessageFromJson.fromJson(String jsonString) {
+    Map<String, Object> decoded = json.decode(jsonString);
+    List<String> ansiFormatted =
+        new List<String>.from(decoded["ansiFormatted"]);
+    List<String> plainTextFormatted =
+        new List<String>.from(decoded["plainTextFormatted"]);
+    Severity severity = Severity.values[decoded["severity"]];
+    Uri uri = Uri.parse(decoded["uri"]);
+
+    return new DiagnosticMessageFromJson(
+        ansiFormatted, plainTextFormatted, severity, uri);
+  }
+
+  Map<String, Object> toJson() {
+    // This should be kept in sync with package:kernel/problems.md
+    return <String, Object>{
+      "ansiFormatted": ansiFormatted.toList(),
+      "plainTextFormatted": plainTextFormatted.toList(),
+      "severity": severity.index,
+      "uri": uri.toString(),
     };
   }
 
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 2688486..e57910c 100644
--- a/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
+++ b/pkg/front_end/lib/src/fasta/fasta_codes_generated.dart
@@ -3348,28 +3348,101 @@
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 const Template<
-    Message Function(
-        String
-            name)> templateFfiAnnotationMissing = const Template<
+    Message Function(String name)> templateFfiFieldAnnotation = const Template<
         Message Function(String name)>(
     messageTemplate:
-        r"""Field '#name' is missing an annotation to declare its C++ type,dart:ffi structs (Pointer<Void>) cannot have regular Dart fields.""",
-    withArguments: _withArgumentsFfiAnnotationMissing);
+        r"""Field '#name' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi structs (Pointer<Void>) cannot have regular Dart fields.""",
+    withArguments: _withArgumentsFfiFieldAnnotation);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name)> codeFfiAnnotationMissing =
+const Code<Message Function(String name)> codeFfiFieldAnnotation =
     const Code<Message Function(String name)>(
-  "FfiAnnotationMissing",
-  templateFfiAnnotationMissing,
+  "FfiFieldAnnotation",
+  templateFfiFieldAnnotation,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiAnnotationMissing(String name) {
+Message _withArgumentsFfiFieldAnnotation(String name) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
-  return new Message(codeFfiAnnotationMissing,
+  return new Message(codeFfiFieldAnnotation,
       message:
-          """Field '${name}' is missing an annotation to declare its C++ type,dart:ffi structs (Pointer<Void>) cannot have regular Dart fields.""",
+          """Field '${name}' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi structs (Pointer<Void>) cannot have regular Dart fields.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiFieldInitializer = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Field '#name' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
+    withArguments: _withArgumentsFfiFieldInitializer);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiFieldInitializer =
+    const Code<Message Function(String name)>(
+  "FfiFieldInitializer",
+  templateFfiFieldInitializer,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiFieldInitializer(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiFieldInitializer,
+      message:
+          """Field '${name}' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiNotStatic = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from c.""",
+    withArguments: _withArgumentsFfiNotStatic);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiNotStatic =
+    const Code<Message Function(String name)>(
+  "FfiNotStatic",
+  templateFfiNotStatic,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiNotStatic(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiNotStatic,
+      message:
+          """${name} expects a static function as parameter. dart:ffi only supports calling static Dart functions from c.""",
+      arguments: {'name': name});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(String name)> templateFfiStructAnnotation = const Template<
+        Message Function(String name)>(
+    messageTemplate:
+        r"""Class '#name' is a dart:ffi Pointer but has no struct annotation. Only struct Pointers can have fields.""",
+    withArguments: _withArgumentsFfiStructAnnotation);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(String name)> codeFfiStructAnnotation =
+    const Code<Message Function(String name)>(
+  "FfiStructAnnotation",
+  templateFfiStructAnnotation,
+);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsFfiStructAnnotation(String name) {
+  if (name.isEmpty) throw 'No name provided';
+  name = demangleMixinApplicationName(name);
+  return new Message(codeFfiStructAnnotation,
+      message:
+          """Class '${name}' is a dart:ffi Pointer but has no struct annotation. Only struct Pointers can have fields.""",
       arguments: {'name': name});
 }
 
@@ -3378,7 +3451,7 @@
     Message Function(DartType _type)> templateFfiTypeInvalid = const Template<
         Message Function(DartType _type)>(
     messageTemplate:
-        r"""Expected type '#type' to be a valid and instantiated subtype of '_NativeType'.""",
+        r"""Expected type '#type' to be a valid and instantiated subtype of 'NativeType'.""",
     withArguments: _withArgumentsFfiTypeInvalid);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -3395,7 +3468,7 @@
   String type = typeParts.join();
   return new Message(codeFfiTypeInvalid,
       message:
-          """Expected type '${type}' to be a valid and instantiated subtype of '_NativeType'.""" +
+          """Expected type '${type}' to be a valid and instantiated subtype of 'NativeType'.""" +
               labeler.originMessages,
       arguments: {'type': _type});
 }
@@ -3442,29 +3515,29 @@
     Message Function(
         String name,
         DartType
-            _type)> templateFfiTypeOpaque = const Template<
+            _type)> templateFfiTypeUnsized = const Template<
         Message Function(String name, DartType _type)>(
     messageTemplate:
-        r"""Method '#name' cannot be called on something of type '#type' as this type is opaque.""",
-    withArguments: _withArgumentsFfiTypeOpaque);
+        r"""Method '#name' cannot be called on something of type '#type' as this type is unsized.""",
+    withArguments: _withArgumentsFfiTypeUnsized);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String name, DartType _type)> codeFfiTypeOpaque =
+const Code<Message Function(String name, DartType _type)> codeFfiTypeUnsized =
     const Code<Message Function(String name, DartType _type)>(
-  "FfiTypeOpaque",
-  templateFfiTypeOpaque,
+  "FfiTypeUnsized",
+  templateFfiTypeUnsized,
 );
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-Message _withArgumentsFfiTypeOpaque(String name, DartType _type) {
+Message _withArgumentsFfiTypeUnsized(String name, DartType _type) {
   if (name.isEmpty) throw 'No name provided';
   name = demangleMixinApplicationName(name);
   TypeLabeler labeler = new TypeLabeler();
   List<Object> typeParts = labeler.labelType(_type);
   String type = typeParts.join();
-  return new Message(codeFfiTypeOpaque,
+  return new Message(codeFfiTypeUnsized,
       message:
-          """Method '${name}' cannot be called on something of type '${type}' as this type is opaque.""" +
+          """Method '${name}' cannot be called on something of type '${type}' as this type is unsized.""" +
               labeler.originMessages,
       arguments: {'name': name, 'type': _type});
 }
@@ -4751,12 +4824,16 @@
     Message Function(
         String string,
         String string2,
+        String string3,
         Uri
             uri_)> templateInitializeFromDillUnknownProblem = const Template<
-        Message Function(String string, String string2, Uri uri_)>(
+        Message Function(
+            String string, String string2, String string3, Uri uri_)>(
     messageTemplate:
         r"""Tried to initialize from a previous compilation (#string), but couldn't.
-Error message was '#string2'. This might be a bug.
+Error message was '#string2'.
+Stacktrace included '#string3'.
+This might be a bug.
 
 The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
 If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
@@ -4764,61 +4841,77 @@
     withArguments: _withArgumentsInitializeFromDillUnknownProblem);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2, Uri uri_)>
-    codeInitializeFromDillUnknownProblem =
-    const Code<Message Function(String string, String string2, Uri uri_)>(
+const Code<
+        Message Function(
+            String string, String string2, String string3, Uri uri_)>
+    codeInitializeFromDillUnknownProblem = const Code<
+            Message Function(
+                String string, String string2, String string3, Uri uri_)>(
         "InitializeFromDillUnknownProblem",
         templateInitializeFromDillUnknownProblem,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInitializeFromDillUnknownProblem(
-    String string, String string2, Uri uri_) {
+    String string, String string2, String string3, Uri uri_) {
   if (string.isEmpty) throw 'No string provided';
   if (string2.isEmpty) throw 'No string provided';
+  if (string3.isEmpty) throw 'No string provided';
   String uri = relativizeUri(uri_);
   return new Message(codeInitializeFromDillUnknownProblem,
       message:
           """Tried to initialize from a previous compilation (${string}), but couldn't.
-Error message was '${string2}'. This might be a bug.
+Error message was '${string2}'.
+Stacktrace included '${string3}'.
+This might be a bug.
 
 The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
 If you are comfortable with it, it would improve the chances of fixing any bug if you included the file ${uri} in your error report, but be aware that this file includes your source code.
 Either way, you should probably delete the file so it doesn't use unnecessary disk space.""",
-      arguments: {'string': string, 'string2': string2, 'uri': uri_});
+      arguments: {
+        'string': string,
+        'string2': string2,
+        'string3': string3,
+        'uri': uri_
+      });
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Template<Message Function(String string, String string2)>
-    templateInitializeFromDillUnknownProblemNoDump =
-    const Template<Message Function(String string, String string2)>(
+const Template<Message Function(String string, String string2, String string3)>
+    templateInitializeFromDillUnknownProblemNoDump = const Template<
+            Message Function(String string, String string2, String string3)>(
         messageTemplate:
             r"""Tried to initialize from a previous compilation (#string), but couldn't.
-Error message was '#string2'. This might be a bug.
+Error message was '#string2'.
+Stacktrace included '#string3'.
+This might be a bug.
 
 The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
         withArguments: _withArgumentsInitializeFromDillUnknownProblemNoDump);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
-const Code<Message Function(String string, String string2)>
+const Code<Message Function(String string, String string2, String string3)>
     codeInitializeFromDillUnknownProblemNoDump =
-    const Code<Message Function(String string, String string2)>(
+    const Code<Message Function(String string, String string2, String string3)>(
         "InitializeFromDillUnknownProblemNoDump",
         templateInitializeFromDillUnknownProblemNoDump,
         severity: Severity.warning);
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
 Message _withArgumentsInitializeFromDillUnknownProblemNoDump(
-    String string, String string2) {
+    String string, String string2, String string3) {
   if (string.isEmpty) throw 'No string provided';
   if (string2.isEmpty) throw 'No string provided';
+  if (string3.isEmpty) throw 'No string provided';
   return new Message(codeInitializeFromDillUnknownProblemNoDump,
       message:
           """Tried to initialize from a previous compilation (${string}), but couldn't.
-Error message was '${string2}'. This might be a bug.
+Error message was '${string2}'.
+Stacktrace included '${string3}'.
+This might be a bug.
 
 The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.""",
-      arguments: {'string': string, 'string2': string2});
+      arguments: {'string': string, 'string2': string2, 'string3': string3});
 }
 
 // DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
@@ -5659,6 +5752,41 @@
     Message Function(
         DartType _type,
         DartType
+            _type2)> templateInvalidCastLiteralSet = const Template<
+        Message Function(DartType _type, DartType _type2)>(
+    messageTemplate:
+        r"""The set literal type '#type' isn't of expected type '#type2'.""",
+    tipTemplate:
+        r"""Change the type of the set literal or the context in which it is used.""",
+    withArguments: _withArgumentsInvalidCastLiteralSet);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Code<Message Function(DartType _type, DartType _type2)>
+    codeInvalidCastLiteralSet =
+    const Code<Message Function(DartType _type, DartType _type2)>(
+        "InvalidCastLiteralSet", templateInvalidCastLiteralSet,
+        analyzerCodes: <String>["INVALID_CAST_LITERAL_SET"]);
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+Message _withArgumentsInvalidCastLiteralSet(DartType _type, DartType _type2) {
+  TypeLabeler labeler = new TypeLabeler();
+  List<Object> typeParts = labeler.labelType(_type);
+  List<Object> type2Parts = labeler.labelType(_type2);
+  String type = typeParts.join();
+  String type2 = type2Parts.join();
+  return new Message(codeInvalidCastLiteralSet,
+      message:
+          """The set literal type '${type}' isn't of expected type '${type2}'.""" +
+              labeler.originMessages,
+      tip: """Change the type of the set literal or the context in which it is used.""",
+      arguments: {'type': _type, 'type2': _type2});
+}
+
+// DO NOT EDIT. THIS FILE IS GENERATED. SEE TOP OF FILE.
+const Template<
+    Message Function(
+        DartType _type,
+        DartType
             _type2)> templateInvalidCastLocalFunction = const Template<
         Message Function(DartType _type, DartType _type2)>(
     messageTemplate:
diff --git a/pkg/front_end/lib/src/fasta/incremental_compiler.dart b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
index 220f440..4155df3 100644
--- a/pkg/front_end/lib/src/fasta/incremental_compiler.dart
+++ b/pkg/front_end/lib/src/fasta/incremental_compiler.dart
@@ -56,6 +56,7 @@
 
 import 'fasta_codes.dart'
     show
+        DiagnosticMessageFromJson,
         templateInitializeFromDillNotSelfContained,
         templateInitializeFromDillNotSelfContainedNoDump,
         templateInitializeFromDillUnknownProblem,
@@ -93,6 +94,8 @@
   Component componentToInitializeFrom;
   bool initializedFromDill = false;
   bool hasToCheckPackageUris = false;
+  Map<Uri, List<DiagnosticMessageFromJson>> remainingComponentProblems =
+      new Map<Uri, List<DiagnosticMessageFromJson>>();
 
   KernelTarget userCode;
 
@@ -128,7 +131,7 @@
         if (initializeFromDillUri != null) {
           try {
             bytesLength += await initializeFromDill(uriTranslator, c, data);
-          } catch (e) {
+          } catch (e, st) {
             // We might have loaded x out of y libraries into the component.
             // To avoid any unforeseen problems start over.
             bytesLength = prepareSummary(summaryBytes, uriTranslator, c, data);
@@ -156,9 +159,11 @@
                     ? templateInitializeFromDillUnknownProblem.withArguments(
                         initializeFromDillUri.toString(),
                         "$e",
+                        "$st",
                         gzInitializedFrom)
                     : templateInitializeFromDillUnknownProblemNoDump
-                        .withArguments(initializeFromDillUri.toString(), "$e");
+                        .withArguments(
+                            initializeFromDillUri.toString(), "$e", "$st");
                 dillLoadedData.loader
                     .addProblem(message, TreeNode.noOffset, 1, null);
               }
@@ -200,10 +205,7 @@
       }
 
       ClassHierarchy hierarchy = userCode?.loader?.hierarchy;
-      Set<LibraryBuilder> notReusedLibraries;
-      if (hierarchy != null) {
-        notReusedLibraries = new Set<LibraryBuilder>();
-      }
+      Set<LibraryBuilder> notReusedLibraries = new Set<LibraryBuilder>();
       List<LibraryBuilder> reusedLibraries = computeReusedLibraries(
           invalidatedUris, uriTranslator,
           notReused: notReusedLibraries);
@@ -215,6 +217,14 @@
         userBuilders?.remove(uri);
       }
 
+      // Remove component problems for libraries we don't reuse.
+      if (remainingComponentProblems.isNotEmpty) {
+        for (LibraryBuilder builder in notReusedLibraries) {
+          Library lib = builder.target;
+          removeLibraryFromRemainingComponentProblems(lib, uriTranslator);
+        }
+      }
+
       if (hierarchy != null) {
         List<Library> removedLibraries = new List<Library>();
         for (LibraryBuilder builder in notReusedLibraries) {
@@ -223,6 +233,7 @@
         }
         hierarchy.applyTreeChanges(removedLibraries, const []);
       }
+      notReusedLibraries = null;
 
       if (userCode != null) {
         ticker.logMs("Decided to reuse ${reusedLibraries.length}"
@@ -250,7 +261,7 @@
         }
       }
 
-      userCode.setEntryPoints(<Uri>[entryPoint]);
+      entryPoint = userCode.setEntryPoints(<Uri>[entryPoint]).single;
       await userCode.buildOutlines();
 
       // This is not the full component. It is the component including all
@@ -272,15 +283,21 @@
           : componentWithDill.mainMethod;
 
       List<Library> outputLibraries;
+      Set<Library> allLibraries;
       if (data.includeUserLoadedLibraries || fullComponent) {
         outputLibraries = computeTransitiveClosure(compiledLibraries,
-            mainMethod, entryPoint, reusedLibraries, hierarchy);
+            entryPoint, reusedLibraries, hierarchy, uriTranslator);
+        allLibraries = outputLibraries.toSet();
       } else {
         outputLibraries = new List<Library>();
-        computeTransitiveClosure(compiledLibraries, mainMethod, entryPoint,
-            reusedLibraries, hierarchy, outputLibraries);
+        allLibraries = computeTransitiveClosure(compiledLibraries, entryPoint,
+                reusedLibraries, hierarchy, uriTranslator, outputLibraries)
+            .toSet();
       }
 
+      List<String> problemsAsJson = reissueComponentProblems(componentWithDill);
+      reissueLibraryProblems(allLibraries, compiledLibraries);
+
       if (componentWithDill == null) {
         userCode.loader.builders.clear();
         userCode = userCodeOld;
@@ -289,17 +306,83 @@
       // This is the incremental component.
       return context.options.target.configureComponent(new Component(
           libraries: outputLibraries,
-          uriToSource: componentWithDill.uriToSource))
-        ..mainMethod = mainMethod;
+          uriToSource: componentWithDill?.uriToSource))
+        ..mainMethod = mainMethod
+        ..problemsAsJson = problemsAsJson;
     });
   }
 
+  void reissueLibraryProblems(
+      Set<Library> allLibraries, List<Library> compiledLibraries) {
+    // The newly-compiled libraries have issued problems already. Re-issue
+    // problems for the libraries that weren't re-compiled.
+    allLibraries.removeAll(compiledLibraries);
+    for (Library library in allLibraries) {
+      if (library.problemsAsJson?.isNotEmpty == true) {
+        for (String jsonString in library.problemsAsJson) {
+          DiagnosticMessageFromJson message =
+              new DiagnosticMessageFromJson.fromJson(jsonString);
+          context.options.reportDiagnosticMessage(message);
+        }
+      }
+    }
+  }
+
+  /// Re-issue problems on the component and return the filtered list.
+  List<String> reissueComponentProblems(Component componentWithDill) {
+    // These problems have already been reported.
+    Set<String> issuedProblems = new Set<String>();
+    if (componentWithDill.problemsAsJson != null) {
+      issuedProblems.addAll(componentWithDill.problemsAsJson);
+    }
+
+    // Report old problems that wasn't reported again.
+    for (List<DiagnosticMessageFromJson> messages
+        in remainingComponentProblems.values) {
+      for (int i = 0; i < messages.length; i++) {
+        DiagnosticMessageFromJson message = messages[i];
+        if (issuedProblems.add(message.toJsonString())) {
+          context.options.reportDiagnosticMessage(message);
+        }
+      }
+    }
+
+    // Save any new component-problems.
+    if (componentWithDill.problemsAsJson != null) {
+      for (String jsonString in componentWithDill.problemsAsJson) {
+        DiagnosticMessageFromJson message =
+            new DiagnosticMessageFromJson.fromJson(jsonString);
+        List<DiagnosticMessageFromJson> messages =
+            remainingComponentProblems[message.uri] ??=
+                new List<DiagnosticMessageFromJson>();
+        messages.add(message);
+      }
+    }
+    return new List<String>.from(issuedProblems);
+  }
+
+  Uri getPartFileUri(
+      Uri parentFileUri, LibraryPart part, UriTranslator uriTranslator) {
+    Uri fileUri = parentFileUri.resolve(part.partUri);
+    if (fileUri.scheme == "package") {
+      // Part was specified via package URI and the resolve above thus
+      // did not go as expected. Translate the package URI to get the
+      // actual file URI.
+      fileUri = uriTranslator.translate(fileUri, false);
+    }
+    return fileUri;
+  }
+
+  /// Compute the transitive closure.
+  ///
+  /// As a side-effect, this also cleans-up now-unreferenced builders as well as
+  /// any saved component problems for such builders.
   List<Library> computeTransitiveClosure(
       List<Library> inputLibraries,
-      Procedure mainMethod,
       Uri entry,
       List<LibraryBuilder> reusedLibraries,
       ClassHierarchy hierarchy,
+      UriTranslator uriTranslator,
       [List<Library> inputLibrariesFiltered]) {
     List<Library> result = new List<Library>();
     Map<Uri, Library> libraryMap = <Uri, Library>{};
@@ -317,12 +400,11 @@
     }
 
     List<Uri> worklist = new List<Uri>();
-    Uri mainMethodUri = mainMethod?.enclosingLibrary?.importUri;
-    if (mainMethodUri != null) worklist.add(mainMethodUri);
-    if (entry != null) worklist.add(entry);
-
+    worklist.add(entry);
     for (LibraryBuilder library in reusedLibraries) {
-      if (library.uri.scheme == "dart") continue;
+      if (library.uri.scheme == "dart" && !library.isSynthetic) {
+        continue;
+      }
       Library lib = library.target;
       potentiallyReferencedLibraries[library.uri] = lib;
       libraryMap[library.uri] = lib;
@@ -355,6 +437,7 @@
         removedLibraries.add(lib);
         dillLoadedData.loader.builders.remove(uri);
         userBuilders?.remove(uri);
+        removeLibraryFromRemainingComponentProblems(lib, uriTranslator);
       }
     }
     hierarchy?.applyTreeChanges(removedLibraries, const []);
@@ -362,6 +445,16 @@
     return result;
   }
 
+  void removeLibraryFromRemainingComponentProblems(
+      Library lib, UriTranslator uriTranslator) {
+    remainingComponentProblems.remove(lib.fileUri);
+    // Remove parts too.
+    for (LibraryPart part in lib.parts) {
+      Uri partFileUri = getPartFileUri(lib.fileUri, part, uriTranslator);
+      remainingComponentProblems.remove(partFileUri);
+    }
+  }
+
   int prepareSummary(List<int> summaryBytes, UriTranslator uriTranslator,
       CompilerContext c, IncrementalCompilerData data) {
     dillLoadedData = new DillTarget(ticker, uriTranslator, c.options.target);
@@ -414,11 +507,25 @@
         bytesLength += initializationBytes.length;
         data.userLoadedUriMain = data.component.mainMethod;
         data.includeUserLoadedLibraries = true;
+        saveComponentProblems(data);
       }
     }
     return bytesLength;
   }
 
+  void saveComponentProblems(IncrementalCompilerData data) {
+    if (data.component.problemsAsJson != null) {
+      for (String jsonString in data.component.problemsAsJson) {
+        DiagnosticMessageFromJson message =
+            new DiagnosticMessageFromJson.fromJson(jsonString);
+        List<DiagnosticMessageFromJson> messages =
+            remainingComponentProblems[message.uri] ??=
+                new List<DiagnosticMessageFromJson>();
+        messages.add(message);
+      }
+    }
+  }
+
   // This procedure will set up compiler from [componentToInitializeFrom].
   void initializeFromComponent(UriTranslator uriTranslator, CompilerContext c,
       IncrementalCompilerData data) {
@@ -451,6 +558,7 @@
           ..mainMethod = componentToInitializeFrom.mainMethod;
     data.userLoadedUriMain = data.component.mainMethod;
     data.includeUserLoadedLibraries = true;
+    saveComponentProblems(data);
   }
 
   void appendLibraries(IncrementalCompilerData data, int bytesLength) {
@@ -598,7 +706,7 @@
     }
 
     addBuilderAndInvalidateUris(Uri uri, LibraryBuilder library) {
-      if (uri.scheme == "dart") {
+      if (uri.scheme == "dart" && !library.isSynthetic) {
         result.add(library);
         return;
       }
@@ -616,13 +724,9 @@
       } else if (library is DillLibraryBuilder) {
         for (LibraryPart part in library.target.parts) {
           Uri partUri = library.uri.resolve(part.partUri);
-          Uri fileUri = library.library.fileUri.resolve(part.partUri);
-          if (fileUri.scheme == "package") {
-            // Part was specified via package URI and the resolve above thus
-            // did not go as expected. Translate the package URI to get the
-            // actual file URI.
-            fileUri = uriTranslator.translate(partUri, false);
-          }
+          Uri fileUri =
+              getPartFileUri(library.library.fileUri, part, uriTranslator);
+
           if (isInvalidated(partUri, fileUri)) {
             invalidatedImportUris.add(partUri);
             builders[partUri] = library;
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 b55e634..d526ee2 100644
--- a/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/body_builder.dart
@@ -2405,8 +2405,9 @@
         rightBrace);
     library.checkBoundsInSetLiteral(node, typeEnvironment);
     if (!library.loader.target.enableSetLiterals) {
-      node = wrapInProblem(node, fasta.messageSetLiteralsNotSupported,
-          lengthOfSpan(leftBrace, leftBrace.endGroup));
+      internalProblem(
+          fasta.messageSetLiteralsNotSupported, node.fileOffset, uri);
+      return;
     }
     push(node);
   }
@@ -3524,6 +3525,12 @@
       } else {
         errorName ??= debugName(type.name, name);
       }
+    } else if (type is InvalidTypeBuilder<TypeBuilder, Object>) {
+      LocatedMessage message = type.message;
+      return evaluateArgumentsBefore(
+          arguments,
+          buildProblem(message.messageObject, nameToken.charOffset,
+              nameToken.lexeme.length));
     } else {
       errorName = debugName(getNodeName(type), name);
     }
diff --git a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
index d69df1a..89f7efa 100644
--- a/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/class_hierarchy_builder.dart
@@ -5,13 +5,30 @@
 library fasta.class_hierarchy_builder;
 
 import 'package:kernel/ast.dart'
-    show Library, Member, Name, Procedure, ProcedureKind;
+    show
+        Class,
+        DartType,
+        InterfaceType,
+        TypeParameter,
+        Library,
+        Member,
+        Name,
+        Procedure,
+        ProcedureKind,
+        Supertype;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
+import 'package:kernel/core_types.dart' show CoreTypes;
+
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+import '../loader.dart' show Loader;
+
 import '../messages.dart'
     show
         LocatedMessage,
+        Message,
         messageDeclaredMemberConflictsWithInheritedMember,
         messageDeclaredMemberConflictsWithInheritedMemberCause,
         messageInheritedMembersConflict,
@@ -28,8 +45,26 @@
 
 import '../scope.dart' show Scope;
 
+import '../type_inference/standard_bounds.dart' show StandardBounds;
+
+import '../type_inference/type_constraint_gatherer.dart'
+    show TypeConstraintGatherer;
+
+import '../type_inference/type_inferrer.dart' show MixinInferrer;
+
+import '../type_inference/type_schema.dart' show UnknownType;
+
+import '../type_inference/type_schema_environment.dart' show TypeConstraint;
+
 import 'kernel_builder.dart'
-    show Declaration, LibraryBuilder, KernelClassBuilder, KernelTypeBuilder;
+    show
+        Declaration,
+        KernelClassBuilder,
+        KernelNamedTypeBuilder,
+        KernelTypeBuilder,
+        LibraryBuilder,
+        TypeBuilder,
+        TypeVariableBuilder;
 
 import 'types.dart' show Types;
 
@@ -67,19 +102,39 @@
 }
 
 class ClassHierarchyBuilder {
-  final Map<KernelClassBuilder, ClassHierarchyNode> nodes =
-      <KernelClassBuilder, ClassHierarchyNode>{};
+  final Map<Class, ClassHierarchyNode> nodes = <Class, ClassHierarchyNode>{};
 
   final KernelClassBuilder objectClass;
 
+  final Loader<Library> loader;
+
+  final Class objectKernelClass;
+
+  final Class futureKernelClass;
+
+  final Class futureOrKernelClass;
+
+  final Class functionKernelClass;
+
+  final Class nullKernelClass;
+
+  // TODO(ahe): Remove this.
+  final CoreTypes coreTypes;
+
   Types types;
 
-  ClassHierarchyBuilder(this.objectClass) {
+  ClassHierarchyBuilder(this.objectClass, this.loader, this.coreTypes)
+      : objectKernelClass = objectClass.target,
+        futureKernelClass = coreTypes.futureClass,
+        futureOrKernelClass = coreTypes.futureOrClass,
+        functionKernelClass = coreTypes.functionClass,
+        nullKernelClass = coreTypes.nullClass {
     types = new Types(this);
   }
 
   ClassHierarchyNode getNodeFromClass(KernelClassBuilder cls) {
-    return nodes[cls] ??= new ClassHierarchyNodeBuilder(this, cls).build();
+    return nodes[cls.target] ??=
+        new ClassHierarchyNodeBuilder(this, cls).build();
   }
 
   ClassHierarchyNode getNodeFromType(KernelTypeBuilder type) {
@@ -89,12 +144,67 @@
         : null;
   }
 
+  ClassHierarchyNode getNodeFromKernelClass(Class cls) {
+    return nodes[cls] ??
+        getNodeFromClass(loader.computeClassBuilderFromTargetClass(cls));
+  }
+
+  KernelTypeBuilder asSupertypeOf(Class cls, Class supertype) {
+    ClassHierarchyNode clsNode = getNodeFromKernelClass(cls);
+    if (cls == supertype) {
+      return new KernelNamedTypeBuilder(clsNode.cls.name, null)
+        ..bind(clsNode.cls);
+    }
+    ClassHierarchyNode supertypeNode = getNodeFromKernelClass(supertype);
+    List<KernelTypeBuilder> supertypes = clsNode.superclasses;
+    int depth = supertypeNode.depth;
+    Declaration supertypeDeclaration = supertypeNode.cls;
+    if (depth < supertypes.length) {
+      KernelTypeBuilder asSupertypeOf = supertypes[depth];
+      if (asSupertypeOf.declaration == supertypeDeclaration)
+        return asSupertypeOf;
+    }
+    supertypes = clsNode.interfaces;
+    for (int i = 0; i < supertypes.length; i++) {
+      KernelTypeBuilder type = supertypes[i];
+      if (type.declaration == supertypeDeclaration) return type;
+    }
+    return null;
+  }
+
+  InterfaceType getKernelTypeAsInstanceOf(
+      InterfaceType type, Class superclass) {
+    Class kernelClass = type.classNode;
+    if (kernelClass == superclass) return type;
+    if (kernelClass == nullKernelClass) {
+      if (superclass.typeParameters.isEmpty) {
+        return superclass.rawType;
+      } else {
+        // This is a safe fall-back for dealing with `Null`. It will likely be
+        // faster to check for `Null` before calling this method.
+        return new InterfaceType(
+            superclass,
+            new List<DartType>.filled(
+                superclass.typeParameters.length, nullKernelClass.rawType));
+      }
+    }
+    KernelNamedTypeBuilder supertype = asSupertypeOf(kernelClass, superclass);
+    if (supertype == null) return null;
+    if (supertype.arguments == null) return superclass.rawType;
+    return Substitution.fromInterfaceType(type)
+        .substituteType(supertype.build(null));
+  }
+
   static ClassHierarchyBuilder build(
-      KernelClassBuilder objectClass, List<KernelClassBuilder> classes) {
-    ClassHierarchyBuilder hierarchy = new ClassHierarchyBuilder(objectClass);
+      KernelClassBuilder objectClass,
+      List<KernelClassBuilder> classes,
+      Loader<Object> loader,
+      CoreTypes coreTypes) {
+    ClassHierarchyBuilder hierarchy =
+        new ClassHierarchyBuilder(objectClass, loader, coreTypes);
     for (int i = 0; i < classes.length; i++) {
       KernelClassBuilder cls = classes[i];
-      hierarchy.nodes[cls] =
+      hierarchy.nodes[cls.target] =
           new ClassHierarchyNodeBuilder(hierarchy, cls).build();
     }
     return hierarchy;
@@ -275,6 +385,7 @@
     Scope scope = cls.scope;
     if (cls.isMixinApplication) {
       Declaration mixin = cls.mixedInType.declaration;
+      inferMixinApplication();
       while (mixin.isNamedMixinApplication) {
         KernelClassBuilder named = mixin;
         mixin = named.mixedInType.declaration;
@@ -328,7 +439,8 @@
     } else {
       superclasses =
           new List<KernelTypeBuilder>(supernode.superclasses.length + 1);
-      superclasses.setRange(0, superclasses.length - 1, supernode.superclasses);
+      superclasses.setRange(0, superclasses.length - 1,
+          substSupertypes(cls.supertype, supernode.superclasses));
       superclasses[superclasses.length - 1] = cls.supertype;
 
       classMembers = merge(
@@ -360,7 +472,8 @@
         interfaceSetters = result.mergedSetters;
         interfaces = <KernelTypeBuilder>[];
         if (supernode.interfaces != null) {
-          List<KernelTypeBuilder> types = supernode.interfaces;
+          List<KernelTypeBuilder> types =
+              substSupertypes(cls.supertype, supernode.interfaces);
           for (int i = 0; i < types.length; i++) {
             addInterface(interfaces, superclasses, types[i]);
           }
@@ -370,13 +483,15 @@
           ClassHierarchyNode interfaceNode =
               hierarchy.getNodeFromType(directInterfaces[i]);
           if (interfaceNode != null) {
-            List<KernelTypeBuilder> types = interfaceNode.superclasses;
+            List<KernelTypeBuilder> types = substSupertypes(
+                directInterfaces[i], interfaceNode.superclasses);
             for (int i = 0; i < types.length; i++) {
               addInterface(interfaces, superclasses, types[i]);
             }
 
             if (interfaceNode.interfaces != null) {
-              List<KernelTypeBuilder> types = interfaceNode.interfaces;
+              List<KernelTypeBuilder> types = substSupertypes(
+                  directInterfaces[i], interfaceNode.interfaces);
               for (int i = 0; i < types.length; i++) {
                 addInterface(interfaces, superclasses, types[i]);
               }
@@ -423,6 +538,43 @@
     );
   }
 
+  List<KernelTypeBuilder> substSupertypes(
+      KernelNamedTypeBuilder supertype, List<KernelTypeBuilder> supertypes) {
+    Declaration declaration = supertype.declaration;
+    if (declaration is! KernelClassBuilder) return supertypes;
+    KernelClassBuilder cls = declaration;
+    List<TypeVariableBuilder<TypeBuilder, Object>> typeVariables =
+        cls.typeVariables;
+    if (typeVariables == null) return supertypes;
+    Map<TypeVariableBuilder<TypeBuilder, Object>, TypeBuilder> substitution =
+        <TypeVariableBuilder<TypeBuilder, Object>, TypeBuilder>{};
+    List<KernelTypeBuilder> arguments =
+        supertype.arguments ?? computeDefaultTypeArguments(supertype);
+    for (int i = 0; i < typeVariables.length; i++) {
+      substitution[typeVariables[i]] = arguments[i];
+    }
+    List<KernelTypeBuilder> result;
+    for (int i = 0; i < supertypes.length; i++) {
+      KernelTypeBuilder supertype = supertypes[i];
+      KernelTypeBuilder substed = supertype.subst(substitution);
+      if (supertype != substed) {
+        result ??= supertypes.toList();
+        result[i] = substed;
+      }
+    }
+    return result ?? supertypes;
+  }
+
+  List<KernelTypeBuilder> computeDefaultTypeArguments(KernelTypeBuilder type) {
+    KernelClassBuilder cls = type.declaration;
+    List<KernelTypeBuilder> result =
+        new List<KernelTypeBuilder>(cls.typeVariables.length);
+    for (int i = 0; i < result.length; ++i) {
+      result[i] = cls.typeVariables[i].defaultType;
+    }
+    return result;
+  }
+
   KernelTypeBuilder addInterface(List<KernelTypeBuilder> interfaces,
       List<KernelTypeBuilder> superclasses, KernelTypeBuilder type) {
     ClassHierarchyNode node = hierarchy.getNodeFromType(type);
@@ -633,6 +785,29 @@
     if (bList.isEmpty && storeIndex == aList.length) return aList;
     return result..length = storeIndex;
   }
+
+  void inferMixinApplication() {
+    if (!hierarchy.loader.target.backendTarget.legacyMode) return;
+    Class kernelClass = cls.target;
+    Supertype kernelMixedInType = kernelClass.mixedInType;
+    if (kernelMixedInType == null) return;
+    List<DartType> typeArguments = kernelMixedInType.typeArguments;
+    if (typeArguments.isEmpty || typeArguments.first is! UnknownType) return;
+    new BuilderMixinInferrer(
+            cls,
+            hierarchy.coreTypes,
+            new TypeBuilderConstraintGatherer(
+                hierarchy, kernelMixedInType.classNode.typeParameters))
+        .infer(kernelClass);
+    List<KernelTypeBuilder> inferredArguments =
+        new List<KernelTypeBuilder>(typeArguments.length);
+    for (int i = 0; i < typeArguments.length; i++) {
+      inferredArguments[i] =
+          hierarchy.loader.computeTypeBuilder(typeArguments[i]);
+    }
+    KernelNamedTypeBuilder mixedInType = cls.mixedInType;
+    mixedInType.arguments = inferredArguments;
+  }
 }
 
 class ClassHierarchyNode {
@@ -782,3 +957,90 @@
         second.fileUri, second.fileOffset, length),
   ];
 }
+
+class BuilderMixinInferrer extends MixinInferrer {
+  final KernelClassBuilder cls;
+
+  BuilderMixinInferrer(
+      this.cls, CoreTypes coreTypes, TypeBuilderConstraintGatherer gatherer)
+      : super(coreTypes, gatherer);
+
+  Supertype asInstantiationOf(Supertype type, Class superclass) {
+    InterfaceType interfaceType =
+        gatherer.getTypeAsInstanceOf(type.asInterfaceType, superclass);
+    if (interfaceType == null) return null;
+    return new Supertype(interfaceType.classNode, interfaceType.typeArguments);
+  }
+
+  void reportProblem(Message message, Class kernelClass) {
+    int length = cls.isMixinApplication ? 1 : cls.fullNameForErrors.length;
+    cls.addProblem(message, cls.charOffset, length);
+  }
+}
+
+class TypeBuilderConstraintGatherer extends TypeConstraintGatherer
+    with StandardBounds {
+  final ClassHierarchyBuilder hierarchy;
+
+  TypeBuilderConstraintGatherer(
+      this.hierarchy, Iterable<TypeParameter> typeParameters)
+      : super.subclassing(typeParameters);
+
+  @override
+  Class get objectClass => hierarchy.objectKernelClass;
+
+  @override
+  Class get functionClass => hierarchy.functionKernelClass;
+
+  @override
+  Class get futureOrClass => hierarchy.futureOrKernelClass;
+
+  @override
+  Class get nullClass => hierarchy.nullKernelClass;
+
+  @override
+  InterfaceType get nullType => nullClass.rawType;
+
+  @override
+  InterfaceType get objectType => objectClass.rawType;
+
+  @override
+  InterfaceType get rawFunctionType => functionClass.rawType;
+
+  @override
+  void addLowerBound(TypeConstraint constraint, DartType lower) {
+    constraint.lower = getStandardUpperBound(constraint.lower, lower);
+  }
+
+  @override
+  void addUpperBound(TypeConstraint constraint, DartType upper) {
+    constraint.upper = getStandardLowerBound(constraint.upper, upper);
+  }
+
+  @override
+  Member getInterfaceMember(Class class_, Name name, {bool setter: false}) {
+    return null;
+  }
+
+  @override
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+    return hierarchy.getKernelTypeAsInstanceOf(type, superclass);
+  }
+
+  @override
+  InterfaceType futureType(DartType type) {
+    return new InterfaceType(hierarchy.futureKernelClass, <DartType>[type]);
+  }
+
+  @override
+  bool isSubtypeOf(DartType subtype, DartType supertype) {
+    return hierarchy.types.isSubtypeOfKernel(subtype, supertype);
+  }
+
+  @override
+  InterfaceType getLegacyLeastUpperBound(
+      InterfaceType type1, InterfaceType type2) {
+    // TODO(ahe): Compute the actual LUB.
+    return type1;
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
index 2a65568..1434f9f 100644
--- a/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/expression_generator.dart
@@ -296,7 +296,10 @@
       Member setter,
       bool isNullAware) {
     if (helper.forest.isThisExpression(receiver)) {
-      return unsupported("ThisExpression", offsetForToken(token), helper.uri);
+      getter ??= helper.lookupInstanceMember(name);
+      setter ??= helper.lookupInstanceMember(name, isSetter: true);
+      return new ThisPropertyAccessGenerator(
+          helper, token, name, getter, setter);
     } else {
       return isNullAware
           ? new NullAwarePropertyAccessGenerator(
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
index e81a108..eb8a506 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_builder.dart
@@ -28,9 +28,6 @@
 
 export 'kernel_formal_parameter_builder.dart' show KernelFormalParameterBuilder;
 
-export 'kernel_function_type_alias_builder.dart'
-    show KernelFunctionTypeAliasBuilder;
-
 export 'kernel_function_type_builder.dart' show KernelFunctionTypeBuilder;
 
 export 'kernel_invalid_type_builder.dart' show KernelInvalidTypeBuilder;
@@ -51,6 +48,8 @@
         KernelRedirectingFactoryBuilder,
         KernelProcedureBuilder;
 
+export 'kernel_type_alias_builder.dart' show KernelTypeAliasBuilder;
+
 export 'kernel_type_builder.dart' show KernelTypeBuilder;
 
 export 'kernel_type_variable_builder.dart' show KernelTypeVariableBuilder;
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
index ffc4c2f..6cb0a71 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_constants.dart
@@ -5,24 +5,11 @@
 library fasta.kernel_constants;
 
 import 'package:kernel/ast.dart'
-    show
-        Arguments,
-        Constant,
-        DartType,
-        IntConstant,
-        Library,
-        ListConstant,
-        MapConstant,
-        Member,
-        Procedure,
-        StaticInvocation,
-        TreeNode,
-        UnevaluatedConstant;
+    show Constant, DartType, IntConstant, Library, Member, Procedure, TreeNode;
 
 import 'package:kernel/type_environment.dart' show TypeEnvironment;
 
-import 'package:kernel/transformations/constants.dart'
-    show ConstantsBackend, ErrorReporter;
+import 'package:kernel/transformations/constants.dart' show ErrorReporter;
 
 import '../fasta_codes.dart'
     show
@@ -191,41 +178,3 @@
     return addProblem(node, messageConstEvalCircularity);
   }
 }
-
-class KernelConstantsBackend extends ConstantsBackend {
-  @override
-  Constant lowerListConstant(ListConstant constant) => constant;
-
-  @override
-  Constant lowerMapConstant(MapConstant constant) => constant;
-
-  @override
-  Constant buildConstantForNative(
-      String nativeName,
-      List<DartType> typeArguments,
-      List<Constant> positionalArguments,
-      Map<String, Constant> namedArguments,
-      List<TreeNode> context,
-      StaticInvocation node,
-      ErrorReporter errorReporter,
-      Constant abortEvaluation(String message)) {
-    // VM-specific names of the fromEnvironment factory constructors.
-    if (nativeName == 'Bool_fromEnvironment' ||
-        nativeName == 'Integer_fromEnvironment' ||
-        nativeName == 'String_fromEnvironment') {
-      // Replace the evaluated arguments.
-      Arguments arguments = node.arguments;
-      for (int i = 0; i < arguments.positional.length; ++i) {
-        Constant constant = positionalArguments[i];
-        arguments.positional[i] = constant.asExpression()..parent = arguments;
-      }
-      for (int i = 0; i < arguments.named.length; ++i) {
-        Constant constant = namedArguments[arguments.named[i].name];
-        arguments.named[i].value = constant.asExpression()..parent = arguments;
-      }
-      return new UnevaluatedConstant(node);
-    }
-    return abortEvaluation(
-        errorReporter.invalidStaticInvocation(context, node, node.target));
-  }
-}
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 c4292e3..c2ca617 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
@@ -1482,7 +1482,7 @@
         super(helper, token);
 
   @override
-  Expression buildAssignment(Expression value, {bool voidContext}) {
+  Expression buildAssignment(Expression value, {bool voidContext: false}) {
     return new PropertySet(receiver, name, value)
       ..fileOffset = offsetForToken(token);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
index f67e700..08e5bce 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_expression_generator_impl.dart
@@ -302,7 +302,7 @@
   }
 
   Expression buildCompoundAssignment(Name binaryOperator, Expression value,
-      {int offset,
+      {int offset: TreeNode.noOffset,
       bool voidContext: false,
       Procedure interfaceTarget,
       bool isPreIncDec: false,
@@ -312,13 +312,17 @@
   }
 
   Expression buildPrefixIncrement(Name binaryOperator,
-      {int offset, bool voidContext: false, Procedure interfaceTarget}) {
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
     return unsupported(
         "buildPrefixIncrement", offset ?? offsetForToken(token), uri);
   }
 
   Expression buildPostfixIncrement(Name binaryOperator,
-      {int offset, bool voidContext: false, Procedure interfaceTarget}) {
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
     return unsupported(
         "buildPostfixIncrement", offset ?? offsetForToken(token), uri);
   }
@@ -372,7 +376,7 @@
   }
 
   Expression buildCompoundAssignment(Name binaryOperator, Expression value,
-      {int offset,
+      {int offset: TreeNode.noOffset,
       bool voidContext: false,
       Procedure interfaceTarget,
       bool isPreIncDec: false,
@@ -382,13 +386,17 @@
   }
 
   Expression buildPrefixIncrement(Name binaryOperator,
-      {int offset, bool voidContext: false, Procedure interfaceTarget}) {
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
     return unsupported(
         "buildPrefixIncrement", offset ?? offsetForToken(token), uri);
   }
 
   Expression buildPostfixIncrement(Name binaryOperator,
-      {int offset, bool voidContext: false, Procedure interfaceTarget}) {
+      {int offset: TreeNode.noOffset,
+      bool voidContext: false,
+      Procedure interfaceTarget}) {
     return unsupported(
         "buildPostfixIncrement", offset ?? offsetForToken(token), uri);
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
index 916dc20d..d821ca7 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_builder.dart
@@ -35,7 +35,7 @@
   KernelFunctionTypeBuilder(
       KernelTypeBuilder returnType,
       List<TypeVariableBuilder> typeVariables,
-      List<FormalParameterBuilder> formals)
+      List<FormalParameterBuilder<TypeBuilder>> formals)
       : super(returnType, typeVariables, formals);
 
   FunctionType build(LibraryBuilder library, [TypedefType origin]) {
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 4a946c1..4277b49 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
@@ -132,7 +132,7 @@
         KernelFieldBuilder,
         KernelFormalParameterBuilder,
         KernelFunctionBuilder,
-        KernelFunctionTypeAliasBuilder,
+        KernelTypeAliasBuilder,
         KernelFunctionTypeBuilder,
         KernelInvalidTypeBuilder,
         KernelMixinApplicationBuilder,
@@ -830,7 +830,7 @@
       List<TypeVariableBuilder> typeVariables,
       covariant KernelFunctionTypeBuilder type,
       int charOffset) {
-    KernelFunctionTypeAliasBuilder typedef = new KernelFunctionTypeAliasBuilder(
+    KernelTypeAliasBuilder typedef = new KernelTypeAliasBuilder(
         metadata, name, typeVariables, type, this, charOffset);
     loader.target.metadataCollector
         ?.setDocumentationComment(typedef.target, documentationComment);
@@ -891,7 +891,7 @@
       member = declaration.build(this)..isStatic = true;
     } else if (declaration is KernelProcedureBuilder) {
       member = declaration.build(this)..isStatic = true;
-    } else if (declaration is KernelFunctionTypeAliasBuilder) {
+    } else if (declaration is KernelTypeAliasBuilder) {
       typedef = declaration.build(this);
     } else if (declaration is KernelEnumBuilder) {
       cls = declaration.build(this, coreLibrary);
@@ -1013,6 +1013,7 @@
 
     if (modifyTarget == false) return library;
 
+    library.isSynthetic = isSynthetic;
     addDependencies(library, new Set<KernelLibraryBuilder>());
 
     loader.target.metadataCollector
@@ -1306,7 +1307,7 @@
                 member.typeVariables, legacyMode || issues.isNotEmpty);
           }
         });
-      } else if (declaration is KernelFunctionTypeAliasBuilder) {
+      } else if (declaration is KernelTypeAliasBuilder) {
         List<Object> issues = legacyMode
             ? const <Object>[]
             : getNonSimplicityIssuesForDeclaration(declaration,
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 eaf1c03..104f403 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_target.dart
@@ -101,8 +101,7 @@
         TypeBuilder,
         TypeDeclarationBuilder;
 
-import 'kernel_constants.dart'
-    show KernelConstantErrorReporter, KernelConstantsBackend;
+import 'kernel_constants.dart' show KernelConstantErrorReporter;
 
 import 'metadata_collector.dart' show MetadataCollector;
 
@@ -120,7 +119,7 @@
   /// The [MetadataCollector] to write metadata to.
   final MetadataCollector metadataCollector;
 
-  SourceLoader<Library> loader;
+  SourceLoader loader;
 
   Component component;
 
@@ -148,16 +147,18 @@
 
   void set builderHierarchy(ClassHierarchyBuilder o) {}
 
-  SourceLoader<Library> createLoader() =>
-      new SourceLoader<Library>(fileSystem, includeComments, this);
+  SourceLoader createLoader() =>
+      new SourceLoader(fileSystem, includeComments, this);
 
   void addSourceInformation(
       Uri uri, List<int> lineStarts, List<int> sourceCode) {
     uriToSource[uri] = new Source(lineStarts, sourceCode);
   }
 
-  void setEntryPoints(List<Uri> entryPoints) {
+  /// Return list of same size as input with possibly translated uris.
+  List<Uri> setEntryPoints(List<Uri> entryPoints) {
     Map<String, Uri> packagesMap;
+    List<Uri> result = new List<Uri>();
     for (Uri entryPoint in entryPoints) {
       String scheme = entryPoint.scheme;
       Uri fileUri;
@@ -188,8 +189,10 @@
             }
           }
       }
+      result.add(entryPoint);
       loader.read(entryPoint, -1, accessor: loader.first, fileUri: fileUri);
     }
+    return result;
   }
 
   @override
@@ -555,6 +558,7 @@
       "dart:_internal",
       "dart:async",
       "dart:core",
+      "dart:ffi",
       "dart:mirrors"
     ]) {
       Uri uri = Uri.parse(platformLibrary);
@@ -570,8 +574,8 @@
             break;
           }
         }
-        if (!found && uri.path != "mirrors") {
-          // dart:mirrors is optional.
+        if (!found && uri.path != "mirrors" && uri.path != "ffi") {
+          // dart:mirrors and dart:ffi are optional.
           throw "Can't find $uri";
         }
       } else {
@@ -752,8 +756,8 @@
           legacyMode: false);
       constants.transformLibraries(
           loader.libraries,
-          new KernelConstantsBackend(),
-          loader.coreTypes,
+          loader.target.backendTarget.constantsBackend(loader.coreTypes),
+          CompilerContext.current.options.environmentDefines,
           environment,
           new KernelConstantErrorReporter(loader, environment));
       ticker.logMs("Evaluated constants");
diff --git a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
similarity index 77%
rename from pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
rename to pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
index 1e174f4..e9c4064 100644
--- a/pkg/front_end/lib/src/fasta/kernel/kernel_function_type_alias_builder.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/kernel_type_alias_builder.dart
@@ -10,6 +10,7 @@
         DynamicType,
         FunctionType,
         InvalidType,
+        Library,
         TypeParameter,
         Typedef,
         VariableDeclaration;
@@ -24,7 +25,7 @@
 
 import 'kernel_builder.dart'
     show
-        FunctionTypeAliasBuilder,
+        TypeAliasBuilder,
         KernelFormalParameterBuilder,
         KernelFunctionTypeBuilder,
         KernelLibraryBuilder,
@@ -36,18 +37,18 @@
 
 final InvalidType cyclicTypeAliasMarker = new InvalidType();
 
-class KernelFunctionTypeAliasBuilder
-    extends FunctionTypeAliasBuilder<KernelFunctionTypeBuilder, DartType> {
+class KernelTypeAliasBuilder
+    extends TypeAliasBuilder<KernelTypeBuilder, DartType> {
   final Typedef target;
 
   DartType thisType;
 
-  KernelFunctionTypeAliasBuilder(
-      List<MetadataBuilder> metadata,
+  KernelTypeAliasBuilder(
+      List<MetadataBuilder<KernelTypeBuilder>> metadata,
       String name,
-      List<TypeVariableBuilder> typeVariables,
+      List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables,
       KernelFunctionTypeBuilder type,
-      LibraryBuilder parent,
+      LibraryBuilder<KernelTypeBuilder, Library> parent,
       int charOffset,
       [Typedef target])
       : target = target ??
@@ -59,10 +60,11 @@
               ..fileOffset = charOffset),
         super(metadata, name, typeVariables, type, parent, charOffset);
 
-  Typedef build(LibraryBuilder libraryBuilder) {
+  Typedef build(KernelLibraryBuilder libraryBuilder) {
     target..type ??= buildThisType(libraryBuilder);
 
-    if (type != null) {
+    KernelTypeBuilder type = this.type;
+    if (type is KernelFunctionTypeBuilder) {
       List<TypeParameter> typeParameters =
           new List<TypeParameter>(type.typeVariables?.length ?? 0);
       for (int i = 0; i < typeParameters.length; ++i) {
@@ -85,12 +87,14 @@
           }
         }
       }
+    } else if (type != null) {
+      unhandled("${type.fullNameForErrors}", "build", charOffset, fileUri);
     }
 
     return target;
   }
 
-  DartType buildThisType(LibraryBuilder library) {
+  DartType buildThisType(LibraryBuilder<KernelTypeBuilder, Library> library) {
     if (thisType != null) {
       if (identical(thisType, cyclicTypeAliasMarker)) {
         library.addProblem(templateCyclicTypedef.withArguments(name),
@@ -103,23 +107,32 @@
     // detect cycles by detecting recursive calls to this method using an
     // instance of InvalidType that isn't identical to `const InvalidType()`.
     thisType = cyclicTypeAliasMarker;
-    FunctionType builtType = type?.build(library, target.thisType);
-    if (builtType != null) {
-      if (typeVariables != null) {
-        for (KernelTypeVariableBuilder tv in typeVariables) {
-          // Follow bound in order to find all cycles
-          tv.bound?.build(library);
+    KernelTypeBuilder type = this.type;
+    if (type is KernelFunctionTypeBuilder) {
+      FunctionType builtType = type?.build(library, target.thisType);
+      if (builtType != null) {
+        if (typeVariables != null) {
+          for (KernelTypeVariableBuilder tv in typeVariables) {
+            // Follow bound in order to find all cycles
+            tv.bound?.build(library);
+          }
         }
+        return thisType = builtType;
+      } else {
+        return thisType = const InvalidType();
       }
-      return thisType = builtType;
-    } else {
+    } else if (type == null) {
       return thisType = const InvalidType();
+    } else {
+      return unhandled(
+          "${type.fullNameForErrors}", "buildThisType", charOffset, fileUri);
     }
   }
 
   /// [arguments] have already been built.
   DartType buildTypesWithBuiltArguments(
-      LibraryBuilder library, List<DartType> arguments) {
+      LibraryBuilder<KernelTypeBuilder, Object> library,
+      List<DartType> arguments) {
     var thisType = buildThisType(library);
     if (const DynamicType() == thisType) return thisType;
     FunctionType result = thisType;
@@ -132,7 +145,8 @@
   }
 
   List<DartType> buildTypeArguments(
-      LibraryBuilder library, List<KernelTypeBuilder> arguments) {
+      LibraryBuilder<KernelTypeBuilder, Library> library,
+      List<KernelTypeBuilder> arguments) {
     if (arguments == null && typeVariables == null) {
       return <DartType>[];
     }
@@ -174,8 +188,8 @@
   int get typeVariablesCount => typeVariables?.length ?? 0;
 
   @override
-  DartType buildType(
-      LibraryBuilder library, List<KernelTypeBuilder> arguments) {
+  DartType buildType(LibraryBuilder<KernelTypeBuilder, Object> library,
+      List<KernelTypeBuilder> arguments) {
     var thisType = buildThisType(library);
     if (thisType is InvalidType) return thisType;
     FunctionType result = thisType;
diff --git a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
index e32f179..abc2f4d 100644
--- a/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/transform_set_literals.dart
@@ -55,8 +55,7 @@
     return coreTypes.index.getMember('dart:core', 'Set', 'add');
   }
 
-  static Constructor _findUnmodifiableSetConstructor(
-      SourceLoader<Library> loader) {
+  static Constructor _findUnmodifiableSetConstructor(SourceLoader loader) {
     // We should not generally dig into libraries like this, and we should
     // avoid dependencies on libraries other than the ones indexed by
     // CoreTypes. This is a temporary solution until all backends have
@@ -77,7 +76,7 @@
     return null;
   }
 
-  SetLiteralTransformer(SourceLoader<Library> loader)
+  SetLiteralTransformer(SourceLoader loader)
       : coreTypes = loader.coreTypes,
         nullType = new InterfaceType(loader.coreTypes.nullClass, []),
         setFactory = _findSetFactory(loader.coreTypes),
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
index eae7bf1..d05e0d8 100644
--- a/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/type_algorithms.dart
@@ -25,7 +25,7 @@
     show
         ClassBuilder,
         FormalParameterBuilder,
-        FunctionTypeAliasBuilder,
+        TypeAliasBuilder,
         FunctionTypeBuilder,
         KernelClassBuilder,
         KernelFormalParameterBuilder,
@@ -40,7 +40,7 @@
 
 import '../dill/dill_class_builder.dart' show DillClassBuilder;
 
-import '../dill/dill_typedef_builder.dart' show DillFunctionTypeAliasBuilder;
+import '../dill/dill_type_alias_builder.dart' show DillTypeAliasBuilder;
 
 import '../fasta_codes.dart'
     show
@@ -362,7 +362,7 @@
           typesAndDependencies.add(type);
           typesAndDependencies.add(const <Object>[]);
         }
-      } else if (declaration is DillFunctionTypeAliasBuilder) {
+      } else if (declaration is DillTypeAliasBuilder) {
         bool hasInbound = false;
         List<TypeParameter> typeParameters = declaration.target.typeParameters;
         for (int i = 0; i < typeParameters.length && !hasInbound; ++i) {
@@ -383,7 +383,7 @@
           typesAndDependencies.add(type);
           typesAndDependencies.add(dependencies);
         }
-      } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object>) {
+      } else if (declaration is TypeAliasBuilder<TypeBuilder, Object>) {
         if (declaration.typeVariables != null) {
           List<Object> dependencies =
               findInboundReferences(declaration.typeVariables);
@@ -518,8 +518,7 @@
               }
             }
           }
-        } else if (declaration
-            is FunctionTypeAliasBuilder<TypeBuilder, Object>) {
+        } else if (declaration is TypeAliasBuilder<TypeBuilder, Object>) {
           if (declaration.typeVariables != null) {
             for (TypeVariableBuilder<TypeBuilder, Object> variable
                 in declaration.typeVariables) {
@@ -604,7 +603,7 @@
         }
       }
     }
-  } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object>) {
+  } else if (declaration is TypeAliasBuilder<TypeBuilder, Object>) {
     if (declaration.typeVariables != null) {
       for (TypeVariableBuilder<TypeBuilder, Object> variable
           in declaration.typeVariables) {
@@ -709,7 +708,7 @@
   if (declaration is ClassBuilder<TypeBuilder, Object> &&
       declaration.typeVariables != null) {
     issues.addAll(getInboundReferenceIssues(declaration.typeVariables));
-  } else if (declaration is FunctionTypeAliasBuilder<TypeBuilder, Object> &&
+  } else if (declaration is TypeAliasBuilder<TypeBuilder, Object> &&
       declaration.typeVariables != null) {
     issues.addAll(getInboundReferenceIssues(declaration.typeVariables));
   }
diff --git a/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
new file mode 100644
index 0000000..390f4e4
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/kernel/type_builder_computer.dart
@@ -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.
+
+library fasta.type_builder_computer;
+
+import 'package:kernel/ast.dart'
+    show
+        BottomType,
+        Class,
+        DartType,
+        DartTypeVisitor,
+        DynamicType,
+        FunctionType,
+        InterfaceType,
+        InvalidType,
+        Library,
+        TypeParameter,
+        TypeParameterType,
+        TypedefType,
+        VoidType;
+
+import '../kernel/kernel_builder.dart'
+    show
+        DynamicTypeBuilder,
+        KernelClassBuilder,
+        KernelNamedTypeBuilder,
+        KernelTypeBuilder,
+        KernelTypeVariableBuilder,
+        LibraryBuilder,
+        VoidTypeBuilder;
+
+import '../loader.dart' show Loader;
+
+class TypeBuilderComputer implements DartTypeVisitor<KernelTypeBuilder> {
+  final Loader<Library> loader;
+
+  const TypeBuilderComputer(this.loader);
+
+  KernelTypeBuilder defaultDartType(DartType node) {
+    throw "Unsupported";
+  }
+
+  KernelTypeBuilder visitInvalidType(InvalidType node) {
+    throw "Not implemented";
+  }
+
+  KernelTypeBuilder visitDynamicType(DynamicType node) {
+    return new KernelNamedTypeBuilder("dynamic", null)
+      ..bind(new DynamicTypeBuilder<KernelTypeBuilder, DartType>(
+          const DynamicType(), loader.coreLibrary, -1));
+  }
+
+  KernelTypeBuilder visitVoidType(VoidType node) {
+    return new KernelNamedTypeBuilder("void", null)
+      ..bind(new VoidTypeBuilder<KernelTypeBuilder, VoidType>(
+          const VoidType(), loader.coreLibrary, -1));
+  }
+
+  KernelTypeBuilder visitBottomType(BottomType node) {
+    throw "Not implemented";
+  }
+
+  KernelTypeBuilder visitInterfaceType(InterfaceType node) {
+    KernelClassBuilder cls =
+        loader.computeClassBuilderFromTargetClass(node.classNode);
+    List<KernelTypeBuilder> arguments;
+    List<DartType> kernelArguments = node.typeArguments;
+    if (kernelArguments.isNotEmpty) {
+      arguments = new List<KernelTypeBuilder>(kernelArguments.length);
+      for (int i = 0; i < kernelArguments.length; i++) {
+        arguments[i] = kernelArguments[i].accept(this);
+      }
+    }
+    return new KernelNamedTypeBuilder(cls.name, arguments)..bind(cls);
+  }
+
+  KernelTypeBuilder visitFunctionType(FunctionType node) {
+    throw "Not implemented";
+  }
+
+  KernelTypeBuilder visitTypeParameterType(TypeParameterType node) {
+    TypeParameter parameter = node.parameter;
+    Class kernelClass = parameter.parent;
+    Library kernelLibrary = kernelClass.enclosingLibrary;
+    LibraryBuilder<KernelTypeBuilder, Library> library =
+        loader.builders[kernelLibrary.importUri];
+    return new KernelNamedTypeBuilder(parameter.name, null)
+      ..bind(new KernelTypeVariableBuilder.fromKernel(parameter, library));
+  }
+
+  KernelTypeBuilder visitTypedefType(TypedefType node) {
+    throw "Not implemented";
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/kernel/types.dart b/pkg/front_end/lib/src/fasta/kernel/types.dart
index 555fa60..d7207b5 100644
--- a/pkg/front_end/lib/src/fasta/kernel/types.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/types.dart
@@ -7,26 +7,31 @@
 import 'package:kernel/ast.dart'
     show
         BottomType,
+        Class,
         DartType,
         DynamicType,
         FunctionType,
         InterfaceType,
         InvalidType,
+        NamedType,
+        TypeParameter,
         TypeParameterType,
         TypedefType,
         VoidType;
 
-import 'class_hierarchy_builder.dart' show ClassHierarchyBuilder;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+import 'kernel_builder.dart' show ClassHierarchyBuilder;
 
 class Types {
   final ClassHierarchyBuilder hierarchy;
 
-  const Types(this.hierarchy);
+  Types(this.hierarchy);
 
   /// Returns true if [s] is a subtype of [t].
   bool isSubtypeOfKernel(DartType s, DartType t) {
     if (s is BottomType) {
-      return true;
+      return true; // Rule 3.
     }
     if (s is InvalidType) {
       // InvalidType is also a bottom type.
@@ -36,30 +41,57 @@
       return false;
     }
     if (t is DynamicType) {
-      // A top type.
-      return true;
+      return true; // Rule 2.
     }
     if (t is VoidType) {
-      // A top type.
-      return true;
+      return true; // Rule 2.
     }
     if (t is BottomType) {
       return false;
     }
     if (t is InterfaceType) {
-      const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
-      if (s is DynamicType) {
-        return relation.isDynamicRelated(s, t, this);
-      } else if (s is VoidType) {
-        return relation.isVoidRelated(s, t, this);
-      } else if (s is InterfaceType) {
-        return relation.isInterfaceRelated(s, t, this);
-      } else if (s is FunctionType) {
-        return relation.isFunctionRelated(s, t, this);
-      } else if (s is TypeParameterType) {
-        return relation.isTypeParameterRelated(s, t, this);
-      } else if (s is TypedefType) {
-        return relation.isTypedefRelated(s, t, this);
+      Class cls = t.classNode;
+      if (cls == hierarchy.objectKernelClass) {
+        return true; // Rule 2.
+      }
+      if (cls == hierarchy.futureOrKernelClass) {
+        const IsFutureOrSubtypeOf relation = const IsFutureOrSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.futureOrKernelClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      } else {
+        const IsInterfaceSubtypeOf relation = const IsInterfaceSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.futureOrKernelClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
       }
     } else if (t is FunctionType) {
       const IsFunctionSubtypeOf relation = const IsFunctionSubtypeOf();
@@ -68,29 +100,59 @@
       } else if (s is VoidType) {
         return relation.isVoidRelated(s, t, this);
       } else if (s is InterfaceType) {
-        return relation.isInterfaceRelated(s, t, this);
+        return s.classNode == hierarchy.futureOrKernelClass
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
       } else if (s is FunctionType) {
         return relation.isFunctionRelated(s, t, this);
       } else if (s is TypeParameterType) {
-        return relation.isTypeParameterRelated(s, t, this);
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
       } else if (s is TypedefType) {
         return relation.isTypedefRelated(s, t, this);
       }
     } else if (t is TypeParameterType) {
-      const IsTypeParameterSubtypeOf relation =
-          const IsTypeParameterSubtypeOf();
-      if (s is DynamicType) {
-        return relation.isDynamicRelated(s, t, this);
-      } else if (s is VoidType) {
-        return relation.isVoidRelated(s, t, this);
-      } else if (s is InterfaceType) {
-        return relation.isInterfaceRelated(s, t, this);
-      } else if (s is FunctionType) {
-        return relation.isFunctionRelated(s, t, this);
-      } else if (s is TypeParameterType) {
-        return relation.isTypeParameterRelated(s, t, this);
-      } else if (s is TypedefType) {
-        return relation.isTypedefRelated(s, t, this);
+      if (t.promotedBound == null) {
+        const IsTypeParameterSubtypeOf relation =
+            const IsTypeParameterSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.futureOrKernelClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
+      } else {
+        const IsIntersectionSubtypeOf relation =
+            const IsIntersectionSubtypeOf();
+        if (s is DynamicType) {
+          return relation.isDynamicRelated(s, t, this);
+        } else if (s is VoidType) {
+          return relation.isVoidRelated(s, t, this);
+        } else if (s is InterfaceType) {
+          return s.classNode == hierarchy.futureOrKernelClass
+              ? relation.isFutureOrRelated(s, t, this)
+              : relation.isInterfaceRelated(s, t, this);
+        } else if (s is FunctionType) {
+          return relation.isFunctionRelated(s, t, this);
+        } else if (s is TypeParameterType) {
+          return s.promotedBound == null
+              ? relation.isTypeParameterRelated(s, t, this)
+              : relation.isIntersectionRelated(s, t, this);
+        } else if (s is TypedefType) {
+          return relation.isTypedefRelated(s, t, this);
+        }
       }
     } else if (t is TypedefType) {
       const IsTypedefSubtypeOf relation = const IsTypedefSubtypeOf();
@@ -99,11 +161,15 @@
       } else if (s is VoidType) {
         return relation.isVoidRelated(s, t, this);
       } else if (s is InterfaceType) {
-        return relation.isInterfaceRelated(s, t, this);
+        return s.classNode == hierarchy.futureOrKernelClass
+            ? relation.isFutureOrRelated(s, t, this)
+            : relation.isInterfaceRelated(s, t, this);
       } else if (s is FunctionType) {
         return relation.isFunctionRelated(s, t, this);
       } else if (s is TypeParameterType) {
-        return relation.isTypeParameterRelated(s, t, this);
+        return s.promotedBound == null
+            ? relation.isTypeParameterRelated(s, t, this)
+            : relation.isIntersectionRelated(s, t, this);
       } else if (s is TypedefType) {
         return relation.isTypedefRelated(s, t, this);
       }
@@ -112,6 +178,21 @@
     }
     throw "Unhandled type combination: ${t.runtimeType} ${s.runtimeType}";
   }
+
+  /// Returns true if all types in [s] and [t] pairwise are subtypes.
+  bool areSubtypesOfKernel(List<DartType> s, List<DartType> t) {
+    if (s.length != t.length) {
+      throw "Numbers of type arguments don't match $s $t.";
+    }
+    for (int i = 0; i < s.length; i++) {
+      if (!isSubtypeOfKernel(s[i], t[i])) return false;
+    }
+    return true;
+  }
+
+  bool isSameTypeKernel(DartType s, DartType t) {
+    return isSubtypeOfKernel(s, t) && isSubtypeOfKernel(t, s);
+  }
 }
 
 abstract class TypeRelation<T extends DartType> {
@@ -123,8 +204,12 @@
 
   bool isInterfaceRelated(InterfaceType s, T t, Types types);
 
+  bool isIntersectionRelated(TypeParameterType intersection, T t, Types types);
+
   bool isFunctionRelated(FunctionType s, T t, Types types);
 
+  bool isFutureOrRelated(InterfaceType futureOr, T t, Types types);
+
   bool isTypeParameterRelated(TypeParameterType s, T t, Types types);
 
   bool isTypedefRelated(TypedefType s, T t, Types types);
@@ -133,27 +218,336 @@
 class IsInterfaceSubtypeOf extends TypeRelation<InterfaceType> {
   const IsInterfaceSubtypeOf();
 
-  // TODO(ahe): Remove this method.
-  noSuchMethod(invocation) => super.noSuchMethod(invocation);
+  @override
+  bool isInterfaceRelated(InterfaceType s, InterfaceType t, Types types) {
+    if (s.classNode == types.hierarchy.nullKernelClass) {
+      // This is an optimization, to avoid instantating unnecessary type
+      // arguments in getKernelTypeAsInstanceOf.
+      return true;
+    }
+    InterfaceType asSupertype =
+        types.hierarchy.getKernelTypeAsInstanceOf(s, t.classNode);
+    if (asSupertype == null) {
+      return false;
+    } else {
+      return types.areSubtypesOfKernel(
+          asSupertype.typeArguments, t.typeArguments);
+    }
+  }
+
+  @override
+  bool isTypeParameterRelated(
+      TypeParameterType s, InterfaceType t, Types types) {
+    return types.isSubtypeOfKernel(s.parameter.bound, t);
+  }
+
+  @override
+  bool isFutureOrRelated(InterfaceType futureOr, InterfaceType t, Types types) {
+    List<DartType> arguments = futureOr.typeArguments;
+    if (!types.isSubtypeOfKernel(arguments.single, t)) {
+      return false; // Rule 7.1
+    }
+    if (!types.isSubtypeOfKernel(
+        new InterfaceType(types.hierarchy.futureKernelClass, arguments), t)) {
+      return false; // Rule 7.2
+    }
+    return true;
+  }
+
+  @override
+  bool isIntersectionRelated(
+      TypeParameterType intersection, InterfaceType t, Types types) {
+    return types.isSubtypeOfKernel(intersection.promotedBound, t); // Rule 12.
+  }
+
+  @override
+  bool isDynamicRelated(DynamicType s, InterfaceType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isFunctionRelated(FunctionType s, InterfaceType t, Types types) {
+    return t.classNode == types.hierarchy.functionKernelClass; // Rule 14.
+  }
+
+  @override
+  bool isTypedefRelated(TypedefType s, InterfaceType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isVoidRelated(VoidType s, InterfaceType t, Types types) {
+    return false;
+  }
 }
 
 class IsFunctionSubtypeOf extends TypeRelation<FunctionType> {
   const IsFunctionSubtypeOf();
 
-  // TODO(ahe): Remove this method.
-  noSuchMethod(invocation) => super.noSuchMethod(invocation);
+  @override
+  bool isFunctionRelated(FunctionType s, FunctionType t, Types types) {
+    List<TypeParameter> sTypeVariables = s.typeParameters;
+    List<TypeParameter> tTypeVariables = t.typeParameters;
+    if (sTypeVariables.length != tTypeVariables.length) return false;
+    if (sTypeVariables.isNotEmpty) {
+      // If the function types have type variables, we alpha-rename the type
+      // variables of [s] to use those of [t].
+      List<DartType> typeVariableSubstitution = <DartType>[];
+      bool secondBoundsCheckNeeded = false;
+      for (int i = 0; i < sTypeVariables.length; i++) {
+        TypeParameter sTypeVariable = sTypeVariables[i];
+        TypeParameter tTypeVariable = tTypeVariables[i];
+        if (!types.isSameTypeKernel(sTypeVariable.bound, tTypeVariable.bound)) {
+          // If the bounds aren't the same, we need to try again after
+          // computing the substitution of type variables.
+          secondBoundsCheckNeeded = true;
+        }
+        typeVariableSubstitution.add(new TypeParameterType(tTypeVariable));
+      }
+      Substitution substitution =
+          Substitution.fromPairs(sTypeVariables, typeVariableSubstitution);
+      if (secondBoundsCheckNeeded) {
+        for (int i = 0; i < sTypeVariables.length; i++) {
+          TypeParameter sTypeVariable = sTypeVariables[i];
+          TypeParameter tTypeVariable = tTypeVariables[i];
+          if (!types.isSameTypeKernel(
+              substitution.substituteType(sTypeVariable.bound),
+              tTypeVariable.bound)) {
+            return false;
+          }
+        }
+      }
+      s = substitution.substituteType(s.withoutTypeParameters);
+    }
+    if (!types.isSubtypeOfKernel(s.returnType, t.returnType)) return false;
+    List<DartType> sPositional = s.positionalParameters;
+    List<DartType> tPositional = t.positionalParameters;
+    if (s.requiredParameterCount > t.requiredParameterCount) {
+      // Rule 15, n1 <= n2.
+      return false;
+    }
+    if (sPositional.length < tPositional.length) {
+      // Rule 15, n1 + k1 >= n2 + k2.
+      return false;
+    }
+    for (int i = 0; i < tPositional.length; i++) {
+      if (!types.isSubtypeOfKernel(tPositional[i], sPositional[i])) {
+        // Rule 15, Tj <: Sj.
+        return false;
+      }
+    }
+    List<NamedType> sNamed = s.namedParameters;
+    List<NamedType> tNamed = t.namedParameters;
+    if (sNamed.isNotEmpty || tNamed.isNotEmpty) {
+      // Rule 16, the number of positional parameters must be the same.
+      if (sPositional.length != tPositional.length) return false;
+      if (s.requiredParameterCount != t.requiredParameterCount) return false;
+
+      // Rule 16, the parameter names of [t] must be a subset of those of
+      // [s]. Also, for the intersection, the type of the parameter of [t] must
+      // be a subtype of the type of the parameter of [s].
+      int sCount = 0;
+      for (int tCount = 0; tCount < tNamed.length; tCount++) {
+        String name = tNamed[tCount].name;
+        for (; sCount < sNamed.length; sCount++) {
+          if (sNamed[sCount].name == name) break;
+        }
+        if (sCount == sNamed.length) return false;
+        if (!types.isSubtypeOfKernel(
+            tNamed[tCount].type, sNamed[sCount].type)) {
+          return false;
+        }
+      }
+    }
+    return true;
+  }
+
+  @override
+  bool isInterfaceRelated(InterfaceType s, FunctionType t, Types types) {
+    return s.classNode == types.hierarchy.nullKernelClass; // Rule 4.
+  }
+
+  @override
+  bool isDynamicRelated(DynamicType s, FunctionType t, Types types) => false;
+
+  @override
+  bool isFutureOrRelated(InterfaceType futureOr, FunctionType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isIntersectionRelated(
+      TypeParameterType intersection, FunctionType t, Types types) {
+    // Rule 12.
+    return types.isSubtypeOfKernel(intersection.promotedBound, t);
+  }
+
+  @override
+  bool isTypeParameterRelated(
+      TypeParameterType s, FunctionType t, Types types) {
+    // Rule 13.
+    return types.isSubtypeOfKernel(s.parameter.bound, t);
+  }
+
+  @override
+  bool isTypedefRelated(TypedefType s, FunctionType t, Types types) {
+    // Rule 5.
+    return types.isSubtypeOfKernel(s.unalias, t);
+  }
+
+  @override
+  bool isVoidRelated(VoidType s, FunctionType t, Types types) {
+    return false;
+  }
 }
 
 class IsTypeParameterSubtypeOf extends TypeRelation<TypeParameterType> {
   const IsTypeParameterSubtypeOf();
 
-  // TODO(ahe): Remove this method.
-  noSuchMethod(invocation) => super.noSuchMethod(invocation);
+  @override
+  bool isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType t, Types types) {
+    return s.parameter == t.parameter;
+  }
+
+  @override
+  bool isIntersectionRelated(
+      TypeParameterType intersection, TypeParameterType t, Types types) {
+    return intersection.parameter == t.parameter; // Rule 8.
+  }
+
+  @override
+  bool isInterfaceRelated(InterfaceType s, TypeParameterType t, Types types) {
+    return s.classNode == types.hierarchy.nullKernelClass; // Rule 4.
+  }
+
+  @override
+  bool isDynamicRelated(DynamicType s, TypeParameterType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isFunctionRelated(FunctionType s, TypeParameterType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isFutureOrRelated(
+      InterfaceType futureOr, TypeParameterType t, Types types) {
+    return false;
+  }
+
+  @override
+  bool isTypedefRelated(TypedefType s, TypeParameterType t, Types types) {
+    return types.isSubtypeOfKernel(s.unalias, t);
+  }
+
+  @override
+  bool isVoidRelated(VoidType s, TypeParameterType t, Types types) {
+    return false;
+  }
 }
 
 class IsTypedefSubtypeOf extends TypeRelation<TypedefType> {
   const IsTypedefSubtypeOf();
 
+  @override
+  bool isInterfaceRelated(InterfaceType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s, t.unalias);
+  }
+
+  @override
+  bool isDynamicRelated(DynamicType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s, t.unalias);
+  }
+
+  @override
+  bool isFunctionRelated(FunctionType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s, t.unalias);
+  }
+
+  @override
+  bool isFutureOrRelated(InterfaceType futureOr, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(futureOr, t.unalias);
+  }
+
+  @override
+  bool isIntersectionRelated(
+      TypeParameterType intersection, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(intersection, t.unalias);
+  }
+
+  @override
+  bool isTypeParameterRelated(TypeParameterType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s, t.unalias);
+  }
+
+  @override
+  bool isTypedefRelated(TypedefType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s.unalias, t.unalias);
+  }
+
+  @override
+  bool isVoidRelated(VoidType s, TypedefType t, Types types) {
+    return types.isSubtypeOfKernel(s, t.unalias);
+  }
+}
+
+class IsFutureOrSubtypeOf extends TypeRelation<InterfaceType> {
+  const IsFutureOrSubtypeOf();
+
+  @override
+  bool isInterfaceRelated(
+      InterfaceType s, InterfaceType futureOr, Types types) {
+    List<DartType> arguments = futureOr.typeArguments;
+    if (types.isSubtypeOfKernel(s, arguments.single)) {
+      return true; // Rule 11.
+    }
+    // Rule 10.
+    return types.isSubtypeOfKernel(
+        s, new InterfaceType(types.hierarchy.futureKernelClass, arguments));
+  }
+
+  @override
+  bool isFutureOrRelated(
+      InterfaceType sFutureOr, InterfaceType tFutureOr, Types types) {
+    //return types.isSubtypeOfKernel(
+    //    sFutureOr.typeArguments.single, futureOr.typeArguments.single);
+    // TODO(ahe): Not tested yet.
+    return true;
+  }
+
+  // TODO(ahe): Remove this method.
+  noSuchMethod(invocation) => super.noSuchMethod(invocation);
+}
+
+class IsIntersectionSubtypeOf extends TypeRelation<TypeParameterType> {
+  const IsIntersectionSubtypeOf();
+
+  @override
+  bool isIntersectionRelated(TypeParameterType sIntersection,
+      TypeParameterType tIntersection, Types types) {
+    // Rule 9.
+    return const IsTypeParameterSubtypeOf()
+            .isIntersectionRelated(sIntersection, tIntersection, types) &&
+        types.isSubtypeOfKernel(sIntersection, tIntersection.promotedBound);
+  }
+
+  @override
+  bool isTypeParameterRelated(
+      TypeParameterType s, TypeParameterType intersection, Types types) {
+    // Rule 9.
+    return const IsTypeParameterSubtypeOf()
+            .isTypeParameterRelated(s, intersection, types) &&
+        types.isSubtypeOfKernel(s, intersection.promotedBound);
+  }
+
+  @override
+  bool isInterfaceRelated(
+      InterfaceType s, TypeParameterType intersection, Types types) {
+    return s.classNode == types.hierarchy.nullKernelClass; // Rule 4.
+  }
+
   // TODO(ahe): Remove this method.
   noSuchMethod(invocation) => super.noSuchMethod(invocation);
 }
diff --git a/pkg/front_end/lib/src/fasta/kernel/utils.dart b/pkg/front_end/lib/src/fasta/kernel/utils.dart
index 80118b6..8709bb4 100644
--- a/pkg/front_end/lib/src/fasta/kernel/utils.dart
+++ b/pkg/front_end/lib/src/fasta/kernel/utils.dart
@@ -97,9 +97,12 @@
     }
 
     fakeClass.parent = fakeLibrary;
-    fakeClass.supertype = new Supertype.byReference(
-        realClass.supertype.className,
-        realClass.supertype.typeArguments.map(cloner.visitType).toList());
+    if (realClass.supertype != null) {
+      // supertype is null for Object.
+      fakeClass.supertype = new Supertype.byReference(
+          realClass.supertype.className,
+          realClass.supertype.typeArguments.map(cloner.visitType).toList());
+    }
 
     // Rebind the type parameters in the procedure.
     procedure = procedure.accept(cloner);
diff --git a/pkg/front_end/lib/src/fasta/library_graph.dart b/pkg/front_end/lib/src/fasta/library_graph.dart
index 0d7ab6f..acf183f 100644
--- a/pkg/front_end/lib/src/fasta/library_graph.dart
+++ b/pkg/front_end/lib/src/fasta/library_graph.dart
@@ -4,7 +4,8 @@
 
 library fasta.library_graph;
 
-import 'package:kernel/kernel.dart' show Library, LibraryDependency;
+import 'package:kernel/kernel.dart'
+    show Library, LibraryDependency, LibraryPart;
 
 import 'package:kernel/util/graph.dart' show Graph;
 
@@ -21,7 +22,7 @@
       throw "Library not found: $vertex";
     }
 
-    // Imports and exports
+    // Imports and exports.
     for (LibraryDependency dependency in library.dependencies) {
       Uri uri1 = dependency.targetLibrary.importUri;
       Uri uri2 = dependency.targetLibrary.fileUri;
@@ -33,5 +34,18 @@
         }
       }
     }
+
+    // Parts.
+    // Normally there won't be libraries for these, but if, for instance,
+    // the part didn't exist there will be a synthetic library.
+    for (LibraryPart part in library.parts) {
+      Uri partUri = library.importUri.resolve(part.partUri);
+      Uri fileUri = library.fileUri.resolve(part.partUri);
+      if (libraries.containsKey(partUri)) {
+        yield partUri;
+      } else if (fileUri != partUri && libraries.containsKey(fileUri)) {
+        yield fileUri;
+      }
+    }
   }
 }
diff --git a/pkg/front_end/lib/src/fasta/loader.dart b/pkg/front_end/lib/src/fasta/loader.dart
index 1e5f762..da5a124 100644
--- a/pkg/front_end/lib/src/fasta/loader.dart
+++ b/pkg/front_end/lib/src/fasta/loader.dart
@@ -8,7 +8,8 @@
 
 import 'dart:collection' show Queue;
 
-import 'builder/builder.dart' show Declaration, LibraryBuilder;
+import 'builder/builder.dart'
+    show ClassBuilder, Declaration, LibraryBuilder, TypeBuilder;
 
 import 'crash.dart' show firstSourceUri;
 
@@ -303,4 +304,9 @@
   void recordMessage(Severity severity, Message message, int charOffset,
       int length, Uri fileUri,
       {List<LocatedMessage> context}) {}
+
+  ClassBuilder<TypeBuilder, Object> computeClassBuilderFromTargetClass(
+      covariant Object cls);
+
+  TypeBuilder computeTypeBuilder(covariant Object type);
 }
diff --git a/pkg/front_end/lib/src/fasta/rewrite_severity.dart b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
index f2dc2fe..5d521bb 100644
--- a/pkg/front_end/lib/src/fasta/rewrite_severity.dart
+++ b/pkg/front_end/lib/src/fasta/rewrite_severity.dart
@@ -60,17 +60,14 @@
       case "builder/dynamic_type_builder.dart":
       case "builder/field_builder.dart":
       case "builder/formal_parameter_builder.dart":
-      case "builder/function_type_alias_builder.dart":
       case "builder/function_type_builder.dart":
       case "builder/library_builder.dart":
       case "builder/member_builder.dart":
-      case "builder/metadata_builder.dart":
       case "builder/mixin_application_builder.dart":
       case "builder/named_type_builder.dart":
       case "builder/prefix_builder.dart":
       case "builder/procedure_builder.dart":
       case "builder/type_builder.dart":
-      case "builder/type_declaration_builder.dart":
       case "builder/type_variable_builder.dart":
       case "builder/unresolved_type.dart":
       case "builder/void_type_builder.dart":
@@ -80,7 +77,6 @@
       case "dill/dill_library_builder.dart":
       case "dill/dill_loader.dart":
       case "dill/dill_target.dart":
-      case "dill/dill_typedef_builder.dart":
       case "entry_points.dart":
       case "export.dart":
       case "fasta_codes.dart":
@@ -96,7 +92,6 @@
       case "kernel/kernel_expression_generator_impl.dart":
       case "kernel/kernel_field_builder.dart":
       case "kernel/kernel_formal_parameter_builder.dart":
-      case "kernel/kernel_function_type_alias_builder.dart":
       case "kernel/kernel_function_type_builder.dart":
       case "kernel/kernel_invalid_type_builder.dart":
       case "kernel/kernel_library_builder.dart":
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 276b0c3..88edaba 100644
--- a/pkg/front_end/lib/src/fasta/source/diet_listener.dart
+++ b/pkg/front_end/lib/src/fasta/source/diet_listener.dart
@@ -39,15 +39,17 @@
 
 import '../kernel/kernel_body_builder.dart' show KernelBodyBuilder;
 
-import '../kernel/kernel_formal_parameter_builder.dart'
-    show KernelFormalParameterBuilder;
-
-import '../kernel/kernel_function_type_alias_builder.dart'
-    show KernelFunctionTypeAliasBuilder;
+import '../kernel/kernel_builder.dart'
+    show
+        KernelFormalParameterBuilder,
+        KernelFunctionTypeBuilder,
+        KernelTypeAliasBuilder,
+        KernelTypeBuilder;
 
 import '../parser.dart' show Assert, MemberKind, Parser, optional;
 
-import '../problems.dart' show DebugAbort, internalProblem, unexpected;
+import '../problems.dart'
+    show DebugAbort, internalProblem, unexpected, unhandled;
 
 import '../type_inference/type_inference_engine.dart' show TypeInferenceEngine;
 
@@ -241,37 +243,44 @@
 
     Declaration typedefBuilder = lookupBuilder(typedefKeyword, null, name);
     parseMetadata(typedefBuilder, metadata, typedefBuilder.target);
-    if (typedefBuilder is KernelFunctionTypeAliasBuilder &&
-        typedefBuilder.type != null &&
-        typedefBuilder.type.formals != null) {
-      for (int i = 0; i < typedefBuilder.type.formals.length; ++i) {
-        KernelFormalParameterBuilder formal = typedefBuilder.type.formals[i];
-        List<MetadataBuilder> metadata = formal.metadata;
-        if (metadata != null && metadata.length > 0) {
-          // [parseMetadata] is using [Parser.parseMetadataStar] under the hood,
-          // so we only need the offset of the first annotation.
-          Token metadataToken =
-              tokenForOffset(typedefKeyword, endToken, metadata[0].charOffset);
-          List<Expression> annotations =
-              parseMetadata(typedefBuilder, metadataToken, null);
-          if (formal.isPositional) {
-            VariableDeclaration parameter =
-                typedefBuilder.target.positionalParameters[i];
-            for (Expression annotation in annotations) {
-              parameter.addAnnotation(annotation);
-            }
-          } else {
-            for (VariableDeclaration named
-                in typedefBuilder.target.namedParameters) {
-              if (named.name == formal.name) {
+    if (typedefBuilder is KernelTypeAliasBuilder) {
+      KernelTypeBuilder type = typedefBuilder.type;
+      if (type is KernelFunctionTypeBuilder) {
+        List<FormalParameterBuilder<TypeBuilder>> formals = type.formals;
+        if (formals != null) {
+          for (int i = 0; i < formals.length; ++i) {
+            KernelFormalParameterBuilder formal = formals[i];
+            List<MetadataBuilder> metadata = formal.metadata;
+            if (metadata != null && metadata.length > 0) {
+              // [parseMetadata] is using [Parser.parseMetadataStar] under the
+              // hood, so we only need the offset of the first annotation.
+              Token metadataToken = tokenForOffset(
+                  typedefKeyword, endToken, metadata[0].charOffset);
+              List<Expression> annotations =
+                  parseMetadata(typedefBuilder, metadataToken, null);
+              if (formal.isPositional) {
+                VariableDeclaration parameter =
+                    typedefBuilder.target.positionalParameters[i];
                 for (Expression annotation in annotations) {
-                  named.addAnnotation(annotation);
+                  parameter.addAnnotation(annotation);
+                }
+              } else {
+                for (VariableDeclaration named
+                    in typedefBuilder.target.namedParameters) {
+                  if (named.name == formal.name) {
+                    for (Expression annotation in annotations) {
+                      named.addAnnotation(annotation);
+                    }
+                  }
                 }
               }
             }
           }
         }
       }
+    } else if (typedefBuilder != null) {
+      unhandled("${typedefBuilder.fullNameForErrors}", "endFunctionTypeAlias",
+          typedefKeyword.charOffset, uri);
     }
 
     checkEmpty(typedefKeyword.charOffset);
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 d5c1cd8..362b102 100644
--- a/pkg/front_end/lib/src/fasta/source/outline_builder.dart
+++ b/pkg/front_end/lib/src/fasta/source/outline_builder.dart
@@ -4,12 +4,10 @@
 
 library fasta.outline_builder;
 
-import 'package:kernel/ast.dart' show ProcedureKind;
+import 'package:kernel/ast.dart' show DartType, Library, ProcedureKind;
 
 import '../builder/builder.dart';
 
-import '../builder/metadata_builder.dart' show ExpressionMetadataBuilder;
-
 import '../combinator.dart' show Combinator;
 
 import '../configuration.dart' show Configuration;
@@ -98,7 +96,7 @@
 }
 
 class OutlineBuilder extends StackListener {
-  final SourceLibraryBuilder library;
+  final SourceLibraryBuilder<KernelTypeBuilder, Library> library;
 
   final bool enableNative;
   final bool stringExpectedAfterNative;
@@ -108,7 +106,7 @@
 
   String nativeMethodName;
 
-  OutlineBuilder(SourceLibraryBuilder library)
+  OutlineBuilder(SourceLibraryBuilder<KernelTypeBuilder, Library> library)
       : library = library,
         enableNative =
             library.loader.target.backendTarget.enableNative(library.uri),
@@ -146,7 +144,7 @@
     if (arguments == null) {
       pop(); // charOffset
       Object expression = pop();
-      push(new MetadataBuilder.fromExpression(
+      push(new MetadataBuilder<KernelTypeBuilder>.fromExpression(
           expression, postfix, library, beginToken.charOffset));
     } else {
       int charOffset = pop();
@@ -154,7 +152,7 @@
       if (typeName is ParserRecovery) {
         push(typeName);
       } else {
-        push(new MetadataBuilder.fromConstructor(
+        push(new MetadataBuilder<KernelTypeBuilder>.fromConstructor(
             library.addConstructorReference(
                 typeName, typeArguments, postfix, charOffset),
             arguments,
@@ -167,7 +165,7 @@
   @override
   void endMetadataStar(int count) {
     debugEvent("MetadataStar");
-    push(const FixedNullableList<ExpressionMetadataBuilder<TypeBuilder>>()
+    push(const FixedNullableList<MetadataBuilder<KernelTypeBuilder>>()
             .pop(stack, count) ??
         NullValue.Metadata);
   }
@@ -214,7 +212,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     library.addExport(metadata, uri, configurations, combinators,
         exportKeyword.charOffset, uriOffset);
     checkEmpty(exportKeyword.charOffset);
@@ -242,7 +240,7 @@
     List<Configuration> configurations = pop();
     int uriOffset = popCharOffset();
     String uri = pop(); // For a conditional import, this is the default URI.
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(importKeyword.charOffset);
     if (prefix is ParserRecovery) return;
     library.addImport(
@@ -306,7 +304,7 @@
     debugEvent("Part");
     int charOffset = popCharOffset();
     String uri = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     library.addPart(metadata, uri, charOffset);
     checkEmpty(partKeyword.charOffset);
   }
@@ -329,7 +327,7 @@
   void handleIdentifier(Token token, IdentifierContext context) {
     if (context == IdentifierContext.enumValueDeclaration) {
       debugEvent("handleIdentifier");
-      List<MetadataBuilder> metadata = pop();
+      List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
       if (token.isSynthetic) {
         push(new ParserRecovery(token.charOffset));
       } else {
@@ -437,7 +435,7 @@
     popCharOffset();
     String documentationComment = getDocumentationComment(libraryKeyword);
     Object name = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     library.documentationComment = documentationComment;
     if (name is! ParserRecovery) {
       library.name = flattenName(name, offsetForToken(libraryKeyword), uri);
@@ -454,7 +452,8 @@
   @override
   void beginClassDeclaration(Token begin, Token abstractToken, Token name) {
     debugEvent("beginNamedMixinApplication");
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     push(typeVariables ?? NullValue.TypeVariables);
     library.currentDeclaration
       ..name = name.lexeme
@@ -466,7 +465,8 @@
   @override
   void beginMixinDeclaration(Token mixinKeyword, Token name) {
     debugEvent("beginMixinDeclaration");
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     push(typeVariables ?? NullValue.TypeVariables);
     library.currentDeclaration
       ..name = name.lexeme
@@ -488,7 +488,8 @@
   void beginNamedMixinApplication(
       Token begin, Token abstractToken, Token name) {
     debugEvent("beginNamedMixinApplication");
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     push(typeVariables ?? NullValue.TypeVariables);
     library.currentDeclaration
       ..name = name.lexeme
@@ -543,13 +544,14 @@
     int supertypeOffset = pop();
     TypeBuilder supertype = nullIfParserRecovery(pop());
     int modifiers = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     int charOffset = pop();
     Object name = pop();
     if (typeVariables != null && supertype is MixinApplicationBuilder) {
       supertype.typeVariables = typeVariables;
     }
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -583,10 +585,11 @@
     String documentationComment = getDocumentationComment(mixinToken);
     List<TypeBuilder> interfaces = pop(NullValue.TypeBuilderList);
     List<KernelTypeBuilder> supertypeConstraints = nullIfParserRecovery(pop());
-    List<TypeVariableBuilder> typeVariables = pop(NullValue.TypeVariables);
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop(NullValue.TypeVariables);
     int nameOffset = pop();
     Object name = pop();
-    List<MetadataBuilder> metadata = pop(NullValue.Metadata);
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop(NullValue.Metadata);
     checkEmpty(mixinToken.charOffset);
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -637,7 +640,8 @@
     MethodBody kind = pop();
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     int charOffset = pop();
     Object name = pop();
     TypeBuilder returnType = pop();
@@ -653,7 +657,7 @@
     if (isAbstract) {
       modifiers |= abstractMask;
     }
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(beginToken.charOffset);
     library
         .endNestedDeclaration("#method")
@@ -772,7 +776,8 @@
     }
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     int charOffset = pop();
     Object nameOrOperator = pop();
     if (Operator.subtract == nameOrOperator && formals == null) {
@@ -838,7 +843,7 @@
     }
     bool isConst = (modifiers & constMask) != 0;
     int varFinalOrConstOffset = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     String documentationComment = getDocumentationComment(beginToken);
     library
         .endNestedDeclaration("#method")
@@ -929,10 +934,11 @@
     List<TypeBuilder> interfaces = popIfNotNull(implementsKeyword);
     Object mixinApplication = pop();
     int modifiers = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     int charOffset = pop();
     Object name = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (name is ParserRecovery || mixinApplication is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
@@ -1008,7 +1014,7 @@
     Object name = pop();
     TypeBuilder type = nullIfParserRecovery(pop());
     int modifiers = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     if (name is ParserRecovery) {
       push(name);
     } else {
@@ -1159,7 +1165,7 @@
         const FixedNullableList<EnumConstantInfo>().pop(stack, count);
     int charOffset = pop();
     Object name = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(enumKeyword.charOffset);
     if (name is ParserRecovery) return;
     library.addEnum(documentationComment, metadata, name, enumConstantInfos,
@@ -1190,7 +1196,8 @@
     List<FormalParameterBuilder> formals = pop();
     pop(); // formals offset
     TypeBuilder returnType = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     push(library.addFunctionType(
         returnType, typeVariables, formals, functionToken.charOffset));
   }
@@ -1201,7 +1208,8 @@
     List<FormalParameterBuilder> formals = pop();
     int formalsOffset = pop();
     TypeBuilder returnType = pop();
-    List<TypeVariableBuilder> typeVariables = pop();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables =
+        pop();
     push(library.addFunctionType(
         returnType, typeVariables, formals, formalsOffset));
   }
@@ -1211,7 +1219,7 @@
       Token typedefKeyword, Token equals, Token endToken) {
     debugEvent("endFunctionTypeAlias");
     String documentationComment = getDocumentationComment(typedefKeyword);
-    List<TypeVariableBuilder> typeVariables;
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeVariables;
     Object name;
     int charOffset;
     FunctionTypeBuilder functionType;
@@ -1254,7 +1262,7 @@
         addProblem(messageTypedefNotFunction, equals.charOffset, equals.length);
       }
     }
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(typedefKeyword.charOffset);
     library.addFunctionTypeAlias(documentationComment, metadata, name,
         typeVariables, functionType, charOffset);
@@ -1269,7 +1277,7 @@
     int modifiers = (staticToken != null ? staticMask : 0) |
         (covariantToken != null ? covariantMask : 0) |
         Modifier.validateVarFinalOrConst(varFinalOrConst?.lexeme);
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     checkEmpty(beginToken.charOffset);
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
@@ -1293,7 +1301,7 @@
           varFinalOrConst.length);
       modifiers &= ~constMask;
     }
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     if (fieldInfos == null) return;
     String documentationComment = getDocumentationComment(beginToken);
     library.addFields(
@@ -1327,7 +1335,7 @@
     Object name = pop();
     // TODO(paulberry): type variable metadata should not be ignored.  See
     // dartbug.com/28981.
-    /* List<MetadataBuilder> metadata = */ pop();
+    /* List<MetadataBuilder<KernelTypeBuilder>> metadata = */ pop();
     if (name is ParserRecovery) {
       push(name);
     } else {
@@ -1339,7 +1347,9 @@
   void handleTypeVariablesDefined(Token token, int count) {
     debugEvent("TypeVariablesDefined");
     assert(count > 0);
-    push(const FixedNullableList<TypeVariableBuilder>().pop(stack, count) ??
+    push(const FixedNullableList<
+                TypeVariableBuilder<KernelTypeBuilder, DartType>>()
+            .pop(stack, count) ??
         NullValue.TypeVariables);
   }
 
@@ -1348,7 +1358,8 @@
     debugEvent("endTypeVariable");
     TypeBuilder bound = nullIfParserRecovery(pop());
     // Peek to leave type parameters on top of stack.
-    List<TypeVariableBuilder> typeParameters = peek();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeParameters =
+        peek();
     if (typeParameters != null) {
       typeParameters[index].bound = bound;
     }
@@ -1359,7 +1370,8 @@
     debugEvent("endTypeVariables");
 
     // Peek to leave type parameters on top of stack.
-    List<TypeVariableBuilder> typeParameters = peek();
+    List<TypeVariableBuilder<KernelTypeBuilder, DartType>> typeParameters =
+        peek();
 
     Map<String, TypeVariableBuilder> typeVariablesByName;
     if (typeParameters != null) {
@@ -1419,7 +1431,7 @@
     debugEvent("endPartOf");
     int charOffset = popCharOffset();
     Object containingLibrary = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     if (hasName) {
       library.addPartOf(metadata,
           flattenName(containingLibrary, charOffset, uri), null, charOffset);
@@ -1469,7 +1481,7 @@
     int charOffset = pop();
     Object name = pop();
     int modifiers = pop();
-    List<MetadataBuilder> metadata = pop();
+    List<MetadataBuilder<KernelTypeBuilder>> metadata = pop();
     if (name is ParserRecovery) {
       library.endNestedDeclaration("<syntax-error>");
       return;
diff --git a/pkg/front_end/lib/src/fasta/source/source_loader.dart b/pkg/front_end/lib/src/fasta/source/source_loader.dart
index 5943e16..05cc836 100644
--- a/pkg/front_end/lib/src/fasta/source/source_loader.dart
+++ b/pkg/front_end/lib/src/fasta/source/source_loader.dart
@@ -79,8 +79,10 @@
         ClassHierarchyBuilder,
         Declaration,
         EnumBuilder,
+        KernelClassBuilder,
         KernelFieldBuilder,
         KernelProcedureBuilder,
+        KernelTypeBuilder,
         LibraryBuilder,
         NamedTypeBuilder,
         TypeBuilder;
@@ -91,6 +93,8 @@
 
 import '../kernel/transform_set_literals.dart' show SetLiteralTransformer;
 
+import '../kernel/type_builder_computer.dart' show TypeBuilderComputer;
+
 import '../loader.dart' show Loader, untranslatableUriScheme;
 
 import '../parser/class_member_parser.dart' show ClassMemberParser;
@@ -106,7 +110,7 @@
 import '../type_inference/interface_resolver.dart' show InterfaceResolver;
 
 import '../type_inference/type_inferrer.dart'
-    show LegacyModeMixinInferrer, StrongModeMixinInferrer;
+    show KernelHierarchyMixinInferrerCallback;
 
 import 'diet_listener.dart' show DietListener;
 
@@ -118,7 +122,7 @@
 
 import 'source_library_builder.dart' show SourceLibraryBuilder;
 
-class SourceLoader<L> extends Loader<L> {
+class SourceLoader extends Loader<Library> {
   /// The [FileSystem] which should be used to access files.
   final FileSystem fileSystem;
 
@@ -753,8 +757,8 @@
     builders.forEach((Uri uri, LibraryBuilder library) {
       if (library.loader == this) {
         SourceLibraryBuilder sourceLibrary = library;
-        L target = sourceLibrary.build(coreLibrary);
-        if (!library.isPatch && !library.isSynthetic) {
+        Library target = sourceLibrary.build(coreLibrary);
+        if (!library.isPatch) {
           libraries.add(target);
         }
       }
@@ -795,11 +799,12 @@
     if (hierarchy == null) {
       hierarchy = new ClassHierarchy(computeFullComponent(),
           onAmbiguousSupertypes: onAmbiguousSupertypes,
-          mixinInferrer: target.legacyMode
-              ? new LegacyModeMixinInferrer()
-              : new StrongModeMixinInferrer(this));
+          mixinInferrer: new KernelHierarchyMixinInferrerCallback(
+              this, target.legacyMode));
     } else {
       hierarchy.onAmbiguousSupertypes = onAmbiguousSupertypes;
+      hierarchy.mixinInferrer =
+          new KernelHierarchyMixinInferrerCallback(this, target.legacyMode);
       Component component = computeFullComponent();
       hierarchy.applyTreeChanges(const [], component.libraries,
           reissueAmbiguousSupertypesFor: component);
@@ -928,8 +933,8 @@
 
   ClassHierarchyBuilder buildClassHierarchy(
       List<SourceClassBuilder> sourceClasses, ClassBuilder objectClass) {
-    ClassHierarchyBuilder hierarchy =
-        ClassHierarchyBuilder.build(objectClass, sourceClasses);
+    ClassHierarchyBuilder hierarchy = ClassHierarchyBuilder.build(
+        objectClass, sourceClasses, this, coreTypes);
     ticker.logMs("Built class hierarchy");
     return hierarchy;
   }
@@ -1106,6 +1111,18 @@
     hierarchy = null;
     typeInferenceEngine = null;
   }
+
+  @override
+  KernelClassBuilder computeClassBuilderFromTargetClass(Class cls) {
+    Library kernelLibrary = cls.enclosingLibrary;
+    LibraryBuilder library = builders[kernelLibrary.importUri];
+    return library[cls.name];
+  }
+
+  @override
+  KernelTypeBuilder computeTypeBuilder(DartType type) {
+    return type.accept(new TypeBuilderComputer(this));
+  }
 }
 
 /// A minimal implementation of dart:core that is sufficient to create an
@@ -1165,6 +1182,8 @@
   var _current;
   var _yieldEachIterable;
 }
+
+class Function {}
 """;
 
 /// A minimal implementation of dart:async that is sufficient to create an
diff --git a/pkg/front_end/lib/src/fasta/target_implementation.dart b/pkg/front_end/lib/src/fasta/target_implementation.dart
index 85a5843..037e74e 100644
--- a/pkg/front_end/lib/src/fasta/target_implementation.dart
+++ b/pkg/front_end/lib/src/fasta/target_implementation.dart
@@ -48,14 +48,20 @@
   Declaration cachedNativeAnnotation;
   Declaration cachedNativeExtensionAnnotation;
 
-  bool enableSetLiterals;
   bool enableConstantUpdate2018;
+  bool enableControlFlowCollections;
+  bool enableSetLiterals;
+  bool enableSpreadCollections;
 
   TargetImplementation(Ticker ticker, this.uriTranslator, this.backendTarget)
-      : enableSetLiterals = CompilerContext.current.options
-            .isExperimentEnabled(ExperimentalFlag.setLiterals),
-        enableConstantUpdate2018 = CompilerContext.current.options
+      : enableConstantUpdate2018 = CompilerContext.current.options
             .isExperimentEnabled(ExperimentalFlag.constantUpdate2018),
+        enableControlFlowCollections = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.controlFlowCollections),
+        enableSetLiterals = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.setLiterals),
+        enableSpreadCollections = CompilerContext.current.options
+            .isExperimentEnabled(ExperimentalFlag.spreadCollections),
         super(ticker);
 
   /// Creates a [LibraryBuilder] corresponding to [uri], if one doesn't exist
diff --git a/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
new file mode 100644
index 0000000..2d5cb3a
--- /dev/null
+++ b/pkg/front_end/lib/src/fasta/type_inference/standard_bounds.dart
@@ -0,0 +1,446 @@
+// Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+// 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.
+
+import 'dart:math' as math;
+
+import 'package:kernel/ast.dart'
+    show
+        BottomType,
+        Class,
+        DartType,
+        DynamicType,
+        FunctionType,
+        InterfaceType,
+        NamedType,
+        TypeParameterType,
+        VoidType;
+
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+import 'type_schema.dart' show UnknownType;
+
+abstract class StandardBounds {
+  Class get functionClass;
+  InterfaceType get nullType;
+  InterfaceType get objectType;
+  InterfaceType get rawFunctionType;
+
+  bool isSubtypeOf(DartType subtype, DartType supertype);
+
+  InterfaceType getLegacyLeastUpperBound(
+      InterfaceType type1, InterfaceType type2);
+
+  /// Computes the standard lower bound of [type1] and [type2].
+  ///
+  /// Standard lower bound is a lower bound function that imposes an
+  /// ordering on the top types `void`, `dynamic`, and `object`.  This function
+  /// additionally handles the unknown type that appears during type inference.
+  DartType getStandardLowerBound(DartType type1, DartType type2) {
+    // For all types T, SLB(T,T) = T.  Note that we don't test for equality
+    // because we don't want to make the algorithm quadratic.  This is ok
+    // because the check is not needed for correctness; it's just a speed
+    // optimization.
+    if (identical(type1, type2)) {
+      return type1;
+    }
+
+    // For any type T, SLB(?, T) = SLB(T, ?) = T.
+    if (type1 is UnknownType) {
+      return type2;
+    }
+    if (type2 is UnknownType) {
+      return type1;
+    }
+
+    // SLB(void, T) = SLB(T, void) = T.
+    if (type1 is VoidType) {
+      return type2;
+    }
+    if (type2 is VoidType) {
+      return type1;
+    }
+
+    // SLB(dynamic, T) = SLB(T, dynamic) = T if T is not void.
+    if (type1 is DynamicType) {
+      return type2;
+    }
+    if (type2 is DynamicType) {
+      return type1;
+    }
+
+    // SLB(Object, T) = SLB(T, Object) = T if T is not void or dynamic.
+    if (type1 == objectType) {
+      return type2;
+    }
+    if (type2 == objectType) {
+      return type1;
+    }
+
+    // SLB(bottom, T) = SLB(T, bottom) = bottom.
+    if (type1 is BottomType) return type1;
+    if (type2 is BottomType) return type2;
+    if (type1 == nullType) return type1;
+    if (type2 == nullType) return type2;
+
+    // Function types have structural lower bounds.
+    if (type1 is FunctionType && type2 is FunctionType) {
+      return _functionStandardLowerBound(type1, type2);
+    }
+
+    // Otherwise, the lower bounds  of two types is one of them it if it is a
+    // subtype of the other.
+    if (isSubtypeOf(type1, type2)) {
+      return type1;
+    }
+
+    if (isSubtypeOf(type2, type1)) {
+      return type2;
+    }
+
+    // No subtype relation, so the lower bound is bottom.
+    return const BottomType();
+  }
+
+  /// Computes the standard upper bound of two types.
+  ///
+  /// Standard upper bound is an upper bound function that imposes an ordering
+  /// on the top types 'void', 'dynamic', and `object`.  This function
+  /// additionally handles the unknown type that appears during type inference.
+  DartType getStandardUpperBound(DartType type1, DartType type2) {
+    // For all types T, SUB(T,T) = T.  Note that we don't test for equality
+    // because we don't want to make the algorithm quadratic.  This is ok
+    // because the check is not needed for correctness; it's just a speed
+    // optimization.
+    if (identical(type1, type2)) {
+      return type1;
+    }
+
+    // For any type T, SUB(?, T) = SUB(T, ?) = T.
+    if (type1 is UnknownType) {
+      return type2;
+    }
+    if (type2 is UnknownType) {
+      return type1;
+    }
+
+    // SUB(void, T) = SUB(T, void) = void.
+    if (type1 is VoidType) {
+      return type1;
+    }
+    if (type2 is VoidType) {
+      return type2;
+    }
+
+    // SUB(dynamic, T) = SUB(T, dynamic) = dynamic if T is not void.
+    if (type1 is DynamicType) {
+      return type1;
+    }
+    if (type2 is DynamicType) {
+      return type2;
+    }
+
+    // SUB(Obect, T) = SUB(T, Object) = Object if T is not void or dynamic.
+    if (type1 == objectType) {
+      return type1;
+    }
+    if (type2 == objectType) {
+      return type2;
+    }
+
+    // SUB(bottom, T) = SUB(T, bottom) = T.
+    if (type1 is BottomType) return type2;
+    if (type2 is BottomType) return type1;
+    if (type1 == nullType) return type2;
+    if (type2 == nullType) return type1;
+
+    if (type1 is TypeParameterType || type2 is TypeParameterType) {
+      return _typeParameterStandardUpperBound(type1, type2);
+    }
+
+    // The standard upper bound of a function type and an interface type T is
+    // the standard upper bound of Function and T.
+    if (type1 is FunctionType && type2 is InterfaceType) {
+      type1 = rawFunctionType;
+    }
+    if (type2 is FunctionType && type1 is InterfaceType) {
+      type2 = rawFunctionType;
+    }
+
+    // At this point type1 and type2 should both either be interface types or
+    // function types.
+    if (type1 is InterfaceType && type2 is InterfaceType) {
+      return _interfaceStandardUpperBound(type1, type2);
+    }
+
+    if (type1 is FunctionType && type2 is FunctionType) {
+      return _functionStandardUpperBound(type1, type2);
+    }
+
+    // Should never happen. As a defensive measure, return the dynamic type.
+    assert(false);
+    return const DynamicType();
+  }
+
+  /// Compute the standard lower bound of function types [f] and [g].
+  ///
+  /// The spec rules for SLB on function types, informally, are pretty simple:
+  ///
+  /// - If a parameter is required in both, it stays required.
+  ///
+  /// - If a positional parameter is optional or missing in one, it becomes
+  ///   optional.  (This is because we're trying to build a function type which
+  ///   is a subtype of both [f] and [g], meaning it accepts all possible inputs
+  ///   that [f] and [g] accept.)
+  ///
+  /// - Named parameters are unioned together.
+  ///
+  /// - For any parameter that exists in both functions, use the SUB of them as
+  ///   the resulting parameter type.
+  ///
+  /// - Use the SLB of their return types.
+  DartType _functionStandardLowerBound(FunctionType f, FunctionType g) {
+    // TODO(rnystrom,paulberry): Right now, this assumes f and g do not have any
+    // type parameters. Revisit that in the presence of generic methods.
+
+    // Calculate the SUB of each corresponding pair of parameters.
+    int totalPositional =
+        math.max(f.positionalParameters.length, g.positionalParameters.length);
+    var positionalParameters = new List<DartType>(totalPositional);
+    for (int i = 0; i < totalPositional; i++) {
+      if (i < f.positionalParameters.length) {
+        var fType = f.positionalParameters[i];
+        if (i < g.positionalParameters.length) {
+          var gType = g.positionalParameters[i];
+          positionalParameters[i] = getStandardUpperBound(fType, gType);
+        } else {
+          positionalParameters[i] = fType;
+        }
+      } else {
+        positionalParameters[i] = g.positionalParameters[i];
+      }
+    }
+
+    // Parameters that are required in both functions are required in the
+    // result.  Parameters that are optional or missing in either end up
+    // optional.
+    int requiredParameterCount =
+        math.min(f.requiredParameterCount, g.requiredParameterCount);
+    bool hasPositional = requiredParameterCount < totalPositional;
+
+    // Union the named parameters together.
+    List<NamedType> namedParameters = [];
+    {
+      int i = 0;
+      int j = 0;
+      while (true) {
+        if (i < f.namedParameters.length) {
+          if (j < g.namedParameters.length) {
+            var fName = f.namedParameters[i].name;
+            var gName = g.namedParameters[j].name;
+            int order = fName.compareTo(gName);
+            if (order < 0) {
+              namedParameters.add(f.namedParameters[i++]);
+            } else if (order > 0) {
+              namedParameters.add(g.namedParameters[j++]);
+            } else {
+              namedParameters.add(new NamedType(
+                  fName,
+                  getStandardUpperBound(f.namedParameters[i++].type,
+                      g.namedParameters[j++].type)));
+            }
+          } else {
+            namedParameters.addAll(f.namedParameters.skip(i));
+            break;
+          }
+        } else {
+          namedParameters.addAll(g.namedParameters.skip(j));
+          break;
+        }
+      }
+    }
+    bool hasNamed = namedParameters.isNotEmpty;
+
+    // Edge case. Dart does not support functions with both optional positional
+    // and named parameters. If we would synthesize that, give up.
+    if (hasPositional && hasNamed) return const BottomType();
+
+    // Calculate the SLB of the return type.
+    DartType returnType = getStandardLowerBound(f.returnType, g.returnType);
+    return new FunctionType(positionalParameters, returnType,
+        namedParameters: namedParameters,
+        requiredParameterCount: requiredParameterCount);
+  }
+
+  /// Compute the standard upper bound of function types [f] and [g].
+  ///
+  /// The rules for SUB on function types, informally, are pretty simple:
+  ///
+  /// - If the functions don't have the same number of required parameters,
+  ///   always return `Function`.
+  ///
+  /// - Discard any optional named or positional parameters the two types do not
+  ///   have in common.
+  ///
+  /// - Compute the SLB of each corresponding pair of parameter types, and the
+  ///   SUB of the return types.  Return a function type with those types.
+  DartType _functionStandardUpperBound(FunctionType f, FunctionType g) {
+    // TODO(rnystrom): Right now, this assumes f and g do not have any type
+    // parameters. Revisit that in the presence of generic methods.
+
+    // If F and G differ in their number of required parameters, then the
+    // standard upper bound of F and G is Function.
+    // TODO(paulberry): We could do better here, e.g.:
+    //   SUB(([int]) -> void, (int) -> void) = (int) -> void
+    if (f.requiredParameterCount != g.requiredParameterCount) {
+      return functionClass.rawType;
+    }
+    int requiredParameterCount = f.requiredParameterCount;
+
+    // Calculate the SLB of each corresponding pair of parameters.
+    // Ignore any extra optional positional parameters if one has more than the
+    // other.
+    int totalPositional =
+        math.min(f.positionalParameters.length, g.positionalParameters.length);
+    var positionalParameters = new List<DartType>(totalPositional);
+    for (int i = 0; i < totalPositional; i++) {
+      positionalParameters[i] = getStandardLowerBound(
+          f.positionalParameters[i], g.positionalParameters[i]);
+    }
+
+    // Intersect the named parameters.
+    List<NamedType> namedParameters = [];
+    {
+      int i = 0;
+      int j = 0;
+      while (true) {
+        if (i < f.namedParameters.length) {
+          if (j < g.namedParameters.length) {
+            var fName = f.namedParameters[i].name;
+            var gName = g.namedParameters[j].name;
+            int order = fName.compareTo(gName);
+            if (order < 0) {
+              i++;
+            } else if (order > 0) {
+              j++;
+            } else {
+              namedParameters.add(new NamedType(
+                  fName,
+                  getStandardLowerBound(f.namedParameters[i++].type,
+                      g.namedParameters[j++].type)));
+            }
+          } else {
+            break;
+          }
+        } else {
+          break;
+        }
+      }
+    }
+
+    // Calculate the SUB of the return type.
+    DartType returnType = getStandardUpperBound(f.returnType, g.returnType);
+    return new FunctionType(positionalParameters, returnType,
+        namedParameters: namedParameters,
+        requiredParameterCount: requiredParameterCount);
+  }
+
+  DartType _interfaceStandardUpperBound(
+      InterfaceType type1, InterfaceType type2) {
+    // This currently does not implement a very complete standard upper bound
+    // algorithm, but handles a couple of the very common cases that are
+    // causing pain in real code.  The current algorithm is:
+    // 1. If either of the types is a supertype of the other, return it.
+    //    This is in fact the best result in this case.
+    // 2. If the two types have the same class element, then take the
+    //    pointwise standard upper bound of the type arguments.  This is again
+    //    the best result, except that the recursive calls may not return
+    //    the true standard upper bounds.  The result is guaranteed to be a
+    //    well-formed type under the assumption that the input types were
+    //    well-formed (and assuming that the recursive calls return
+    //    well-formed types).
+    // 3. Otherwise return the spec-defined standard upper bound.  This will
+    //    be an upper bound, might (or might not) be least, and might
+    //    (or might not) be a well-formed type.
+    if (isSubtypeOf(type1, type2)) {
+      return type2;
+    }
+    if (isSubtypeOf(type2, type1)) {
+      return type1;
+    }
+    if (type1 is InterfaceType &&
+        type2 is InterfaceType &&
+        identical(type1.classNode, type2.classNode)) {
+      List<DartType> tArgs1 = type1.typeArguments;
+      List<DartType> tArgs2 = type2.typeArguments;
+
+      assert(tArgs1.length == tArgs2.length);
+      List<DartType> tArgs = new List(tArgs1.length);
+      for (int i = 0; i < tArgs1.length; i++) {
+        tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
+      }
+      return new InterfaceType(type1.classNode, tArgs);
+    }
+    return getLegacyLeastUpperBound(type1, type2);
+  }
+
+  DartType _typeParameterStandardUpperBound(DartType type1, DartType type2) {
+    // This currently just implements a simple standard upper bound to
+    // handle some common cases.  It also avoids some termination issues
+    // with the naive spec algorithm.  The standard upper bound of two types
+    // (at least one of which is a type parameter) is computed here as:
+    // 1. If either type is a supertype of the other, return it.
+    // 2. If the first type is a type parameter, replace it with its bound,
+    //    with recursive occurrences of itself replaced with Object.
+    //    The second part of this should ensure termination.  Informally,
+    //    each type variable instantiation in one of the arguments to the
+    //    standard upper bound algorithm now strictly reduces the number
+    //    of bound variables in scope in that argument position.
+    // 3. If the second type is a type parameter, do the symmetric operation
+    //    to #2.
+    //
+    // It's not immediately obvious why this is symmetric in the case that both
+    // of them are type parameters.  For #1, symmetry holds since subtype
+    // is antisymmetric.  For #2, it's clearly not symmetric if upper bounds of
+    // bottom are allowed.  Ignoring this (for various reasons, not least
+    // of which that there's no way to write it), there's an informal
+    // argument (that might even be right) that you will always either
+    // end up expanding both of them or else returning the same result no matter
+    // which order you expand them in.  A key observation is that
+    // identical(expand(type1), type2) => subtype(type1, type2)
+    // and hence the contra-positive.
+    //
+    // TODO(leafp): Think this through and figure out what's the right
+    // definition.  Be careful about termination.
+    //
+    // I suspect in general a reasonable algorithm is to expand the innermost
+    // type variable first.  Alternatively, you could probably choose to treat
+    // it as just an instance of the interface type upper bound problem, with
+    // the "inheritance" chain extended by the bounds placed on the variables.
+    if (isSubtypeOf(type1, type2)) {
+      return type2;
+    }
+    if (isSubtypeOf(type2, type1)) {
+      return type1;
+    }
+    if (type1 is TypeParameterType) {
+      // TODO(paulberry): Analyzer collapses simple bounds in one step, i.e. for
+      // C<T extends U, U extends List>, T gets resolved directly to List.  Do
+      // we need to replicate that behavior?
+      return getStandardUpperBound(
+          Substitution.fromMap({type1.parameter: objectType})
+              .substituteType(type1.parameter.bound),
+          type2);
+    } else if (type2 is TypeParameterType) {
+      return getStandardUpperBound(
+          type1,
+          Substitution.fromMap({type2.parameter: objectType})
+              .substituteType(type2.parameter.bound));
+    } else {
+      // We should only be called when at least one of the types is a
+      // TypeParameterType
+      assert(false);
+      return const DynamicType();
+    }
+  }
+}
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
index 91df6f16..a10dea0 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_constraint_gatherer.dart
@@ -4,10 +4,13 @@
 
 import 'package:kernel/ast.dart'
     show
+        Class,
         DartType,
         DynamicType,
         FunctionType,
         InterfaceType,
+        Member,
+        Name,
         NamedType,
         Procedure,
         TypeParameter,
@@ -29,19 +32,39 @@
 
 /// Creates a collection of [TypeConstraint]s corresponding to type parameters,
 /// based on an attempt to make one type schema a subtype of another.
-class TypeConstraintGatherer {
-  final TypeSchemaEnvironment environment;
-
+abstract class TypeConstraintGatherer {
   final _protoConstraints = <_ProtoConstraint>[];
 
   final List<TypeParameter> _parametersToConstrain;
 
   /// Creates a [TypeConstraintGatherer] which is prepared to gather type
   /// constraints for the given [typeParameters].
-  TypeConstraintGatherer(
-      this.environment, Iterable<TypeParameter> typeParameters)
+  TypeConstraintGatherer.subclassing(Iterable<TypeParameter> typeParameters)
       : _parametersToConstrain = typeParameters.toList();
 
+  factory TypeConstraintGatherer(TypeSchemaEnvironment environment,
+      Iterable<TypeParameter> typeParameters) {
+    return new TypeSchemaConstraintGatherer(environment, typeParameters);
+  }
+
+  Class get objectClass;
+
+  Class get functionClass;
+
+  Class get futureOrClass;
+
+  Class get nullClass;
+
+  void addUpperBound(TypeConstraint constraint, DartType upper);
+
+  void addLowerBound(TypeConstraint constraint, DartType lower);
+
+  Member getInterfaceMember(Class class_, Name name, {bool setter: false});
+
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass);
+
+  InterfaceType futureType(DartType type);
+
   /// Returns the set of type constraints that was gathered.
   Map<TypeParameter, TypeConstraint> computeConstraints() {
     var result = <TypeParameter, TypeConstraint>{};
@@ -50,11 +73,9 @@
     }
     for (var protoConstraint in _protoConstraints) {
       if (protoConstraint.isUpper) {
-        environment.addUpperBound(
-            result[protoConstraint.parameter], protoConstraint.bound);
+        addUpperBound(result[protoConstraint.parameter], protoConstraint.bound);
       } else {
-        environment.addLowerBound(
-            result[protoConstraint.parameter], protoConstraint.bound);
+        addLowerBound(result[protoConstraint.parameter], protoConstraint.bound);
       }
     }
     return result;
@@ -181,7 +202,7 @@
     // above is irrelevant; we just need to find the matched superclass,
     // substitute, and then iterate through type variables.
     var matchingSupertypeOfSubtype =
-        environment.getTypeAsInstanceOf(subtype, supertype.classNode);
+        getTypeAsInstanceOf(subtype, supertype.classNode);
     if (matchingSupertypeOfSubtype == null) return false;
     for (int i = 0; i < supertype.classNode.typeParameters.length; i++) {
       if (!_isSubtypeMatch(matchingSupertypeOfSubtype.typeArguments[i],
@@ -197,8 +218,7 @@
     // it return `true` for both Null and bottom types?  Revisit this once
     // enough functionality is implemented that we can compare the behavior with
     // the old analyzer-based implementation.
-    return type is InterfaceType &&
-        identical(type.classNode, environment.coreTypes.nullClass);
+    return type is InterfaceType && identical(type.classNode, nullClass);
   }
 
   /// Attempts to match [subtype] as a subtype of [supertype], gathering any
@@ -245,10 +265,10 @@
 
     // Handle FutureOr<T> union type.
     if (subtype is InterfaceType &&
-        identical(subtype.classNode, environment.futureOrClass)) {
+        identical(subtype.classNode, futureOrClass)) {
       var subtypeArg = subtype.typeArguments[0];
       if (supertype is InterfaceType &&
-          identical(supertype.classNode, environment.futureOrClass)) {
+          identical(supertype.classNode, futureOrClass)) {
         // `FutureOr<P>` is a subtype match for `FutureOr<Q>` with respect to
         // `L` under constraints `C`:
         // - If `P` is a subtype match for `Q` with respect to `L` under
@@ -263,13 +283,13 @@
       //   constraints `C0`.
       // - And `P` is a subtype match for `Q` with respect to `L` under
       //   constraints `C1`.
-      var subtypeFuture = environment.futureType(subtypeArg);
+      var subtypeFuture = futureType(subtypeArg);
       return _isSubtypeMatch(subtypeFuture, supertype) &&
           _isSubtypeMatch(subtypeArg, supertype);
     }
 
     if (supertype is InterfaceType &&
-        identical(supertype.classNode, environment.futureOrClass)) {
+        identical(supertype.classNode, futureOrClass)) {
       // `P` is a subtype match for `FutureOr<Q>` with respect to `L` under
       // constraints `C`:
       // - If `P` is a subtype match for `Future<Q>` with respect to `L` under
@@ -279,7 +299,7 @@
       //   - And `P` is a subtype match for `Q` with respect to `L` under
       //     constraints `C`
       var supertypeArg = supertype.typeArguments[0];
-      var supertypeFuture = environment.futureType(supertypeArg);
+      var supertypeFuture = futureType(supertypeArg);
       return trySubtypeMatch(subtype, supertypeFuture) ||
           _isSubtypeMatch(subtype, supertypeArg);
     }
@@ -310,9 +330,8 @@
     }
     if (subtype is FunctionType) {
       if (supertype is InterfaceType) {
-        return identical(
-                supertype.classNode, environment.coreTypes.functionClass) ||
-            identical(supertype.classNode, environment.coreTypes.objectClass);
+        return identical(supertype.classNode, functionClass) ||
+            identical(supertype.classNode, objectClass);
       } else if (supertype is FunctionType) {
         return _isFunctionSubtypeMatch(subtype, supertype);
       }
@@ -323,8 +342,7 @@
     //   and `F` is a subtype match for a type `Q` with respect to `L` under
     //   constraints `C`.
     if (subtype is InterfaceType) {
-      var callMember =
-          environment.hierarchy.getInterfaceMember(subtype.classNode, callName);
+      var callMember = getInterfaceMember(subtype.classNode, callName);
       if (callMember is Procedure && !callMember.isGetter) {
         var callType = callMember.getterType;
         if (callType != null) {
@@ -346,8 +364,7 @@
   bool _isTop(DartType type) =>
       type is DynamicType ||
       type is VoidType ||
-      (type is InterfaceType &&
-          identical(type.classNode, environment.coreTypes.objectClass));
+      (type is InterfaceType && identical(type.classNode, objectClass));
 
   /// Given two lists of function type formal parameters, checks that their
   /// bounds are compatible.
@@ -382,6 +399,52 @@
   }
 }
 
+class TypeSchemaConstraintGatherer extends TypeConstraintGatherer {
+  final TypeSchemaEnvironment environment;
+
+  TypeSchemaConstraintGatherer(
+      this.environment, Iterable<TypeParameter> typeParameters)
+      : super.subclassing(typeParameters);
+
+  @override
+  Class get objectClass => environment.coreTypes.objectClass;
+
+  @override
+  Class get functionClass => environment.coreTypes.functionClass;
+
+  @override
+  Class get futureOrClass => environment.coreTypes.futureOrClass;
+
+  @override
+  Class get nullClass => environment.coreTypes.nullClass;
+
+  @override
+  void addUpperBound(TypeConstraint constraint, DartType upper) {
+    environment.addUpperBound(constraint, upper);
+  }
+
+  @override
+  void addLowerBound(TypeConstraint constraint, DartType lower) {
+    environment.addLowerBound(constraint, lower);
+  }
+
+  @override
+  Member getInterfaceMember(Class class_, Name name, {bool setter: false}) {
+    return environment.hierarchy
+        .getInterfaceMember(class_, name, setter: setter);
+  }
+
+  @override
+  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
+    return environment.getTypeAsInstanceOf(type, superclass);
+  }
+
+  @override
+  InterfaceType futureType(DartType type) {
+    return environment.futureType(type);
+  }
+}
+
 /// Tracks a single constraint on a single type variable.
 ///
 /// This is called "_ProtoConstraint" to distinguish from [TypeConstraint],
@@ -397,4 +460,10 @@
   _ProtoConstraint.lower(this.parameter, this.bound) : isUpper = false;
 
   _ProtoConstraint.upper(this.parameter, this.bound) : isUpper = true;
+
+  String toString() {
+    return isUpper
+        ? "${parameter.name} <: $bound"
+        : "$bound <: ${parameter.name}";
+  }
 }
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
index 28b1db4..d719e07 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_inferrer.dart
@@ -35,6 +35,7 @@
         PropertyGet,
         PropertySet,
         ReturnStatement,
+        SetLiteral,
         Statement,
         StaticGet,
         SuperMethodInvocation,
@@ -49,7 +50,9 @@
         VariableGet,
         VoidType;
 
-import 'package:kernel/class_hierarchy.dart' show ClassHierarchy, MixinInferrer;
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+
+import 'package:kernel/class_hierarchy.dart' as kernel show MixinInferrer;
 
 import 'package:kernel/core_types.dart' show CoreTypes;
 
@@ -83,6 +86,7 @@
         templateInvalidCastFunctionExpr,
         templateInvalidCastLiteralList,
         templateInvalidCastLiteralMap,
+        templateInvalidCastLiteralSet,
         templateInvalidCastLocalFunction,
         templateInvalidCastNewExpr,
         templateInvalidCastStaticMethod,
@@ -109,14 +113,14 @@
         getExplicitTypeArguments,
         getInferredType;
 
+import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
+
 import '../names.dart' show callName, unaryMinusName;
 
 import '../problems.dart' show internalProblem, unexpected, unhandled;
 
 import '../source/source_loader.dart' show SourceLoader;
 
-import '../kernel/type_algorithms.dart' show hasAnyTypeVariables;
-
 import 'inference_helper.dart' show InferenceHelper;
 
 import 'interface_resolver.dart' show ForwardingNode, SyntheticAccessor;
@@ -1860,6 +1864,9 @@
     if (expression is MapLiteral) {
       return templateInvalidCastLiteralMap;
     }
+    if (expression is SetLiteral) {
+      return templateInvalidCastLiteralSet;
+    }
     if (expression is FunctionExpression) {
       return templateInvalidCastFunctionExpr;
     }
@@ -1902,28 +1909,41 @@
   }
 }
 
-class LegacyModeMixinInferrer implements MixinInferrer {
+// TODO(ahe): I'm working on removing this.
+class KernelHierarchyMixinInferrerCallback implements kernel.MixinInferrer {
+  final SourceLoader loader;
+  final bool legacyMode;
+
+  KernelHierarchyMixinInferrerCallback(this.loader, this.legacyMode);
+
+  @override
   void infer(ClassHierarchy hierarchy, Class classNode) {
+    if (legacyMode) return;
     Supertype mixedInType = classNode.mixedInType;
-    if (mixedInType.typeArguments.isNotEmpty &&
-        mixedInType.typeArguments.first == const UnknownType()) {
-      assert(mixedInType.typeArguments.every((t) => t == const UnknownType()));
-      for (int i = 0; i < mixedInType.typeArguments.length; ++i) {
-        mixedInType.typeArguments[i] = const DynamicType();
-      }
-    }
+    List<DartType> typeArguments = mixedInType.typeArguments;
+    if (typeArguments.isEmpty || typeArguments.first is! UnknownType) return;
+    new KernelHierarchyMixinInferrer(
+            hierarchy,
+            loader,
+            new TypeConstraintGatherer(
+                new TypeSchemaEnvironment(loader.coreTypes, hierarchy),
+                mixedInType.classNode.typeParameters))
+        .infer(classNode);
   }
 }
 
-class StrongModeMixinInferrer implements MixinInferrer {
+abstract class MixinInferrer {
   final CoreTypes coreTypes;
-  final SourceLoader loader;
-  TypeConstraintGatherer gatherer;
+  final TypeConstraintGatherer gatherer;
 
-  StrongModeMixinInferrer(this.loader) : coreTypes = loader.coreTypes;
+  MixinInferrer(this.coreTypes, this.gatherer);
 
-  void generateConstraints(ClassHierarchy hierarchy, Class mixinClass,
-      Supertype baseType, Supertype mixinSupertype) {
+  Supertype asInstantiationOf(Supertype type, Class superclass);
+
+  void reportProblem(Message message, Class cls);
+
+  void generateConstraints(
+      Class mixinClass, Supertype baseType, Supertype mixinSupertype) {
     if (mixinSupertype.typeArguments.isEmpty) {
       // The supertype constraint isn't generic; it doesn't constrain anything.
     } else if (mixinSupertype.classNode.isAnonymousMixin) {
@@ -1981,20 +2001,18 @@
       }
       s0 = substitution.substituteSupertype(s0);
       s1 = substitution.substituteSupertype(s1);
-      generateConstraints(hierarchy, mixinClass, baseType, s0);
-      generateConstraints(hierarchy, mixinClass, baseType, s1);
+      generateConstraints(mixinClass, baseType, s0);
+      generateConstraints(mixinClass, baseType, s1);
     } else {
       // Find the type U0 which is baseType as an instance of mixinSupertype's
       // class.
       Supertype supertype =
-          hierarchy.asInstantiationOf(baseType, mixinSupertype.classNode);
+          asInstantiationOf(baseType, mixinSupertype.classNode);
       if (supertype == null) {
-        loader.addProblem(
+        reportProblem(
             templateMixinInferenceNoMatchingClass.withArguments(mixinClass.name,
                 baseType.classNode.name, mixinSupertype.asInterfaceType),
-            mixinClass.fileOffset,
-            noLength,
-            mixinClass.fileUri);
+            mixinClass);
         return;
       }
       InterfaceType u0 = Substitution.fromSupertype(baseType)
@@ -2009,62 +2027,70 @@
     }
   }
 
-  void infer(ClassHierarchy hierarchy, Class classNode) {
+  void infer(Class classNode) {
     Supertype mixedInType = classNode.mixedInType;
-    if (mixedInType.typeArguments.isNotEmpty &&
-        mixedInType.typeArguments.first == const UnknownType()) {
-      assert(mixedInType.typeArguments.every((t) => t == const UnknownType()));
-      // Note that we have no anonymous mixin applications, they have all
-      // been named.  Note also that mixin composition has been translated
-      // so that we only have mixin applications of the form `S with M`.
-      Supertype baseType = classNode.supertype;
-      Class mixinClass = mixedInType.classNode;
-      Supertype mixinSupertype = mixinClass.supertype;
-      gatherer = new TypeConstraintGatherer(
-          new TypeSchemaEnvironment(loader.coreTypes, hierarchy),
-          mixinClass.typeParameters);
-      // Generate constraints based on the mixin's supertype.
-      generateConstraints(hierarchy, mixinClass, baseType, mixinSupertype);
-      // Solve them to get a map from type parameters to upper and lower
-      // bounds.
-      var result = gatherer.computeConstraints();
-      // Generate new type parameters with the solution as bounds.
-      List<TypeParameter> parameters = mixinClass.typeParameters.map((p) {
-        var constraint = result[p];
-        // Because we solved for equality, a valid solution has a parameter
-        // either unconstrained or else with identical upper and lower bounds.
-        if (constraint != null && constraint.upper != constraint.lower) {
-          loader.addProblem(
-              templateMixinInferenceNoMatchingClass.withArguments(
-                  mixinClass.name,
-                  baseType.classNode.name,
-                  mixinSupertype.asInterfaceType),
-              mixinClass.fileOffset,
-              noLength,
-              mixinClass.fileUri);
-          return p;
-        }
-        assert(constraint == null || constraint.upper == constraint.lower);
-        bool exact =
-            constraint != null && constraint.upper != const UnknownType();
-        return new TypeParameter(
-            p.name, exact ? constraint.upper : p.bound, p.defaultType);
-      }).toList();
-      // Bounds might mention the mixin class's type parameters so we have to
-      // substitute them before calling instantiate to bounds.
-      var substitution = Substitution.fromPairs(mixinClass.typeParameters,
-          parameters.map((p) => new TypeParameterType(p)).toList());
-      for (var p in parameters) {
-        p.bound = substitution.substituteType(p.bound);
+    assert(mixedInType.typeArguments.every((t) => t == const UnknownType()));
+    // Note that we have no anonymous mixin applications, they have all
+    // been named.  Note also that mixin composition has been translated
+    // so that we only have mixin applications of the form `S with M`.
+    Supertype baseType = classNode.supertype;
+    Class mixinClass = mixedInType.classNode;
+    Supertype mixinSupertype = mixinClass.supertype;
+    // Generate constraints based on the mixin's supertype.
+    generateConstraints(mixinClass, baseType, mixinSupertype);
+    // Solve them to get a map from type parameters to upper and lower
+    // bounds.
+    var result = gatherer.computeConstraints();
+    // Generate new type parameters with the solution as bounds.
+    List<TypeParameter> parameters = mixinClass.typeParameters.map((p) {
+      var constraint = result[p];
+      // Because we solved for equality, a valid solution has a parameter
+      // either unconstrained or else with identical upper and lower bounds.
+      if (constraint != null && constraint.upper != constraint.lower) {
+        reportProblem(
+            templateMixinInferenceNoMatchingClass.withArguments(mixinClass.name,
+                baseType.classNode.name, mixinSupertype.asInterfaceType),
+            mixinClass);
+        return p;
       }
-      // Use instantiate to bounds.
-      List<DartType> bounds =
-          calculateBounds(parameters, loader.coreTypes.objectClass);
-      for (int i = 0; i < mixedInType.typeArguments.length; ++i) {
-        mixedInType.typeArguments[i] = bounds[i];
-      }
-      gatherer = null;
+      assert(constraint == null || constraint.upper == constraint.lower);
+      bool exact =
+          constraint != null && constraint.upper != const UnknownType();
+      return new TypeParameter(
+          p.name, exact ? constraint.upper : p.bound, p.defaultType);
+    }).toList();
+    // Bounds might mention the mixin class's type parameters so we have to
+    // substitute them before calling instantiate to bounds.
+    var substitution = Substitution.fromPairs(mixinClass.typeParameters,
+        parameters.map((p) => new TypeParameterType(p)).toList());
+    for (var p in parameters) {
+      p.bound = substitution.substituteType(p.bound);
     }
+    // Use instantiate to bounds.
+    List<DartType> bounds = calculateBounds(parameters, coreTypes.objectClass);
+    for (int i = 0; i < mixedInType.typeArguments.length; ++i) {
+      mixedInType.typeArguments[i] = bounds[i];
+    }
+  }
+}
+
+// TODO(ahe): I'm working on removing this.
+class KernelHierarchyMixinInferrer extends MixinInferrer {
+  final ClassHierarchy hierarchy;
+  final SourceLoader loader;
+
+  KernelHierarchyMixinInferrer(
+      this.hierarchy, this.loader, TypeConstraintGatherer gatherer)
+      : super(loader.coreTypes, gatherer);
+
+  @override
+  Supertype asInstantiationOf(Supertype type, Class superclass) {
+    return hierarchy.asInstantiationOf(type, superclass);
+  }
+
+  @override
+  void reportProblem(Message message, Class cls) {
+    loader.addProblem(message, cls.fileOffset, noLength, cls.fileUri);
   }
 }
 
diff --git a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
index a1e8259..46d023e 100644
--- a/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
+++ b/pkg/front_end/lib/src/fasta/type_inference/type_schema_environment.dart
@@ -2,20 +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.md file.
 
-import 'dart:math' as math;
-
 import 'package:kernel/ast.dart'
     show
-        BottomType,
+        Class,
         DartType,
         DynamicType,
         FunctionType,
         InterfaceType,
         NamedType,
         Procedure,
-        TypeParameter,
-        TypeParameterType,
-        VoidType;
+        TypeParameter;
 
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 
@@ -26,6 +22,8 @@
 import 'package:kernel/src/hierarchy_based_type_environment.dart'
     show HierarchyBasedTypeEnvironment;
 
+import 'standard_bounds.dart' show StandardBounds;
+
 import 'type_constraint_gatherer.dart' show TypeConstraintGatherer;
 
 import 'type_schema.dart' show UnknownType, typeSchemaToString, isKnown;
@@ -90,10 +88,18 @@
       '${typeSchemaToString(lower)} <: <type> <: ${typeSchemaToString(upper)}';
 }
 
-class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment {
+class TypeSchemaEnvironment extends HierarchyBasedTypeEnvironment
+    with StandardBounds {
   TypeSchemaEnvironment(CoreTypes coreTypes, ClassHierarchy hierarchy)
       : super(coreTypes, hierarchy);
 
+  Class get functionClass => coreTypes.functionClass;
+
+  InterfaceType getLegacyLeastUpperBound(
+      InterfaceType type1, InterfaceType type2) {
+    return hierarchy.getLegacyLeastUpperBound(type1, type2);
+  }
+
   /// Modify the given [constraint]'s lower bound to include [lower].
   void addLowerBound(TypeConstraint constraint, DartType lower) {
     constraint.lower = getStandardUpperBound(constraint.lower, lower);
@@ -104,157 +110,6 @@
     constraint.upper = getStandardLowerBound(constraint.upper, upper);
   }
 
-  /// Computes the standard lower bound of [type1] and [type2].
-  ///
-  /// Standard lower bound is a lower bound function that imposes an
-  /// ordering on the top types `void`, `dynamic`, and `object`.  This function
-  /// additionally handles the unknown type that appears during type inference.
-  DartType getStandardLowerBound(DartType type1, DartType type2) {
-    // For all types T, SLB(T,T) = T.  Note that we don't test for equality
-    // because we don't want to make the algorithm quadratic.  This is ok
-    // because the check is not needed for correctness; it's just a speed
-    // optimization.
-    if (identical(type1, type2)) {
-      return type1;
-    }
-
-    // For any type T, SLB(?, T) = SLB(T, ?) = T.
-    if (type1 is UnknownType) {
-      return type2;
-    }
-    if (type2 is UnknownType) {
-      return type1;
-    }
-
-    // SLB(void, T) = SLB(T, void) = T.
-    if (type1 is VoidType) {
-      return type2;
-    }
-    if (type2 is VoidType) {
-      return type1;
-    }
-
-    // SLB(dynamic, T) = SLB(T, dynamic) = T if T is not void.
-    if (type1 is DynamicType) {
-      return type2;
-    }
-    if (type2 is DynamicType) {
-      return type1;
-    }
-
-    // SLB(Object, T) = SLB(T, Object) = T if T is not void or dynamic.
-    if (type1 == objectType) {
-      return type2;
-    }
-    if (type2 == objectType) {
-      return type1;
-    }
-
-    // SLB(bottom, T) = SLB(T, bottom) = bottom.
-    if (type1 is BottomType) return type1;
-    if (type2 is BottomType) return type2;
-    if (type1 == nullType) return type1;
-    if (type2 == nullType) return type2;
-
-    // Function types have structural lower bounds.
-    if (type1 is FunctionType && type2 is FunctionType) {
-      return _functionStandardLowerBound(type1, type2);
-    }
-
-    // Otherwise, the lower bounds  of two types is one of them it if it is a
-    // subtype of the other.
-    if (isSubtypeOf(type1, type2)) {
-      return type1;
-    }
-
-    if (isSubtypeOf(type2, type1)) {
-      return type2;
-    }
-
-    // No subtype relation, so the lower bound is bottom.
-    return const BottomType();
-  }
-
-  /// Computes the standard upper bound of two types.
-  ///
-  /// Standard upper bound is an upper bound function that imposes an ordering
-  /// on the top types 'void', 'dynamic', and `object`.  This function
-  /// additionally handles the unknown type that appears during type inference.
-  DartType getStandardUpperBound(DartType type1, DartType type2) {
-    // For all types T, SUB(T,T) = T.  Note that we don't test for equality
-    // because we don't want to make the algorithm quadratic.  This is ok
-    // because the check is not needed for correctness; it's just a speed
-    // optimization.
-    if (identical(type1, type2)) {
-      return type1;
-    }
-
-    // For any type T, SUB(?, T) = SUB(T, ?) = T.
-    if (type1 is UnknownType) {
-      return type2;
-    }
-    if (type2 is UnknownType) {
-      return type1;
-    }
-
-    // SUB(void, T) = SUB(T, void) = void.
-    if (type1 is VoidType) {
-      return type1;
-    }
-    if (type2 is VoidType) {
-      return type2;
-    }
-
-    // SUB(dynamic, T) = SUB(T, dynamic) = dynamic if T is not void.
-    if (type1 is DynamicType) {
-      return type1;
-    }
-    if (type2 is DynamicType) {
-      return type2;
-    }
-
-    // SUB(Obect, T) = SUB(T, Object) = Object if T is not void or dynamic.
-    if (type1 == objectType) {
-      return type1;
-    }
-    if (type2 == objectType) {
-      return type2;
-    }
-
-    // SUB(bottom, T) = SUB(T, bottom) = T.
-    if (type1 is BottomType) return type2;
-    if (type2 is BottomType) return type1;
-    if (type1 == nullType) return type2;
-    if (type2 == nullType) return type1;
-
-    if (type1 is TypeParameterType || type2 is TypeParameterType) {
-      return _typeParameterStandardUpperBound(type1, type2);
-    }
-
-    // The standard upper bound of a function type and an interface type T is
-    // the standard upper bound of Function and T.
-    if (type1 is FunctionType && type2 is InterfaceType) {
-      type1 = rawFunctionType;
-    }
-    if (type2 is FunctionType && type1 is InterfaceType) {
-      type2 = rawFunctionType;
-    }
-
-    // At this point type1 and type2 should both either be interface types or
-    // function types.
-    if (type1 is InterfaceType && type2 is InterfaceType) {
-      return _interfaceStandardUpperBound(type1, type2);
-    }
-
-    if (type1 is FunctionType && type2 is FunctionType) {
-      return _functionStandardUpperBound(type1, type2);
-    }
-
-    // Should never happen. As a defensive measure, return the dynamic type.
-    assert(false);
-    return const DynamicType();
-  }
-
   @override
   DartType getTypeOfOverloadedArithmetic(DartType type1, DartType type2) {
     // TODO(paulberry): this matches what is defined in the spec.  It would be
@@ -502,169 +357,6 @@
         isSubtypeOf(type, constraint.upper);
   }
 
-  /// Compute the standard lower bound of function types [f] and [g].
-  ///
-  /// The spec rules for SLB on function types, informally, are pretty simple:
-  ///
-  /// - If a parameter is required in both, it stays required.
-  ///
-  /// - If a positional parameter is optional or missing in one, it becomes
-  ///   optional.  (This is because we're trying to build a function type which
-  ///   is a subtype of both [f] and [g], meaning it accepts all possible inputs
-  ///   that [f] and [g] accept.)
-  ///
-  /// - Named parameters are unioned together.
-  ///
-  /// - For any parameter that exists in both functions, use the SUB of them as
-  ///   the resulting parameter type.
-  ///
-  /// - Use the SLB of their return types.
-  DartType _functionStandardLowerBound(FunctionType f, FunctionType g) {
-    // TODO(rnystrom,paulberry): Right now, this assumes f and g do not have any
-    // type parameters. Revisit that in the presence of generic methods.
-
-    // Calculate the SUB of each corresponding pair of parameters.
-    int totalPositional =
-        math.max(f.positionalParameters.length, g.positionalParameters.length);
-    var positionalParameters = new List<DartType>(totalPositional);
-    for (int i = 0; i < totalPositional; i++) {
-      if (i < f.positionalParameters.length) {
-        var fType = f.positionalParameters[i];
-        if (i < g.positionalParameters.length) {
-          var gType = g.positionalParameters[i];
-          positionalParameters[i] = getStandardUpperBound(fType, gType);
-        } else {
-          positionalParameters[i] = fType;
-        }
-      } else {
-        positionalParameters[i] = g.positionalParameters[i];
-      }
-    }
-
-    // Parameters that are required in both functions are required in the
-    // result.  Parameters that are optional or missing in either end up
-    // optional.
-    int requiredParameterCount =
-        math.min(f.requiredParameterCount, g.requiredParameterCount);
-    bool hasPositional = requiredParameterCount < totalPositional;
-
-    // Union the named parameters together.
-    List<NamedType> namedParameters = [];
-    {
-      int i = 0;
-      int j = 0;
-      while (true) {
-        if (i < f.namedParameters.length) {
-          if (j < g.namedParameters.length) {
-            var fName = f.namedParameters[i].name;
-            var gName = g.namedParameters[j].name;
-            int order = fName.compareTo(gName);
-            if (order < 0) {
-              namedParameters.add(f.namedParameters[i++]);
-            } else if (order > 0) {
-              namedParameters.add(g.namedParameters[j++]);
-            } else {
-              namedParameters.add(new NamedType(
-                  fName,
-                  getStandardUpperBound(f.namedParameters[i++].type,
-                      g.namedParameters[j++].type)));
-            }
-          } else {
-            namedParameters.addAll(f.namedParameters.skip(i));
-            break;
-          }
-        } else {
-          namedParameters.addAll(g.namedParameters.skip(j));
-          break;
-        }
-      }
-    }
-    bool hasNamed = namedParameters.isNotEmpty;
-
-    // Edge case. Dart does not support functions with both optional positional
-    // and named parameters. If we would synthesize that, give up.
-    if (hasPositional && hasNamed) return const BottomType();
-
-    // Calculate the SLB of the return type.
-    DartType returnType = getStandardLowerBound(f.returnType, g.returnType);
-    return new FunctionType(positionalParameters, returnType,
-        namedParameters: namedParameters,
-        requiredParameterCount: requiredParameterCount);
-  }
-
-  /// Compute the standard upper bound of function types [f] and [g].
-  ///
-  /// The rules for SUB on function types, informally, are pretty simple:
-  ///
-  /// - If the functions don't have the same number of required parameters,
-  ///   always return `Function`.
-  ///
-  /// - Discard any optional named or positional parameters the two types do not
-  ///   have in common.
-  ///
-  /// - Compute the SLB of each corresponding pair of parameter types, and the
-  ///   SUB of the return types.  Return a function type with those types.
-  DartType _functionStandardUpperBound(FunctionType f, FunctionType g) {
-    // TODO(rnystrom): Right now, this assumes f and g do not have any type
-    // parameters. Revisit that in the presence of generic methods.
-
-    // If F and G differ in their number of required parameters, then the
-    // standard upper bound of F and G is Function.
-    // TODO(paulberry): We could do better here, e.g.:
-    //   SUB(([int]) -> void, (int) -> void) = (int) -> void
-    if (f.requiredParameterCount != g.requiredParameterCount) {
-      return coreTypes.functionClass.rawType;
-    }
-    int requiredParameterCount = f.requiredParameterCount;
-
-    // Calculate the SLB of each corresponding pair of parameters.
-    // Ignore any extra optional positional parameters if one has more than the
-    // other.
-    int totalPositional =
-        math.min(f.positionalParameters.length, g.positionalParameters.length);
-    var positionalParameters = new List<DartType>(totalPositional);
-    for (int i = 0; i < totalPositional; i++) {
-      positionalParameters[i] = getStandardLowerBound(
-          f.positionalParameters[i], g.positionalParameters[i]);
-    }
-
-    // Intersect the named parameters.
-    List<NamedType> namedParameters = [];
-    {
-      int i = 0;
-      int j = 0;
-      while (true) {
-        if (i < f.namedParameters.length) {
-          if (j < g.namedParameters.length) {
-            var fName = f.namedParameters[i].name;
-            var gName = g.namedParameters[j].name;
-            int order = fName.compareTo(gName);
-            if (order < 0) {
-              i++;
-            } else if (order > 0) {
-              j++;
-            } else {
-              namedParameters.add(new NamedType(
-                  fName,
-                  getStandardLowerBound(f.namedParameters[i++].type,
-                      g.namedParameters[j++].type)));
-            }
-          } else {
-            break;
-          }
-        } else {
-          break;
-        }
-      }
-    }
-
-    // Calculate the SUB of the return type.
-    DartType returnType = getStandardUpperBound(f.returnType, g.returnType);
-    return new FunctionType(positionalParameters, returnType,
-        namedParameters: namedParameters,
-        requiredParameterCount: requiredParameterCount);
-  }
-
   DartType _inferTypeParameterFromAll(DartType typeFromContextInference,
       TypeConstraint constraint, DartType extendsConstraint) {
     // See if we already fixed this type from downwards inference.
@@ -702,105 +394,6 @@
     }
     return t;
   }
-
-  DartType _interfaceStandardUpperBound(
-      InterfaceType type1, InterfaceType type2) {
-    // This currently does not implement a very complete standard upper bound
-    // algorithm, but handles a couple of the very common cases that are
-    // causing pain in real code.  The current algorithm is:
-    // 1. If either of the types is a supertype of the other, return it.
-    //    This is in fact the best result in this case.
-    // 2. If the two types have the same class element, then take the
-    //    pointwise standard upper bound of the type arguments.  This is again
-    //    the best result, except that the recursive calls may not return
-    //    the true standard upper bounds.  The result is guaranteed to be a
-    //    well-formed type under the assumption that the input types were
-    //    well-formed (and assuming that the recursive calls return
-    //    well-formed types).
-    // 3. Otherwise return the spec-defined standard upper bound.  This will
-    //    be an upper bound, might (or might not) be least, and might
-    //    (or might not) be a well-formed type.
-    if (isSubtypeOf(type1, type2)) {
-      return type2;
-    }
-    if (isSubtypeOf(type2, type1)) {
-      return type1;
-    }
-    if (type1 is InterfaceType &&
-        type2 is InterfaceType &&
-        identical(type1.classNode, type2.classNode)) {
-      List<DartType> tArgs1 = type1.typeArguments;
-      List<DartType> tArgs2 = type2.typeArguments;
-
-      assert(tArgs1.length == tArgs2.length);
-      List<DartType> tArgs = new List(tArgs1.length);
-      for (int i = 0; i < tArgs1.length; i++) {
-        tArgs[i] = getStandardUpperBound(tArgs1[i], tArgs2[i]);
-      }
-      return new InterfaceType(type1.classNode, tArgs);
-    }
-    return hierarchy.getLegacyLeastUpperBound(type1, type2);
-  }
-
-  DartType _typeParameterStandardUpperBound(DartType type1, DartType type2) {
-    // This currently just implements a simple standard upper bound to
-    // handle some common cases.  It also avoids some termination issues
-    // with the naive spec algorithm.  The standard upper bound of two types
-    // (at least one of which is a type parameter) is computed here as:
-    // 1. If either type is a supertype of the other, return it.
-    // 2. If the first type is a type parameter, replace it with its bound,
-    //    with recursive occurrences of itself replaced with Object.
-    //    The second part of this should ensure termination.  Informally,
-    //    each type variable instantiation in one of the arguments to the
-    //    standard upper bound algorithm now strictly reduces the number
-    //    of bound variables in scope in that argument position.
-    // 3. If the second type is a type parameter, do the symmetric operation
-    //    to #2.
-    //
-    // It's not immediately obvious why this is symmetric in the case that both
-    // of them are type parameters.  For #1, symmetry holds since subtype
-    // is antisymmetric.  For #2, it's clearly not symmetric if upper bounds of
-    // bottom are allowed.  Ignoring this (for various reasons, not least
-    // of which that there's no way to write it), there's an informal
-    // argument (that might even be right) that you will always either
-    // end up expanding both of them or else returning the same result no matter
-    // which order you expand them in.  A key observation is that
-    // identical(expand(type1), type2) => subtype(type1, type2)
-    // and hence the contra-positive.
-    //
-    // TODO(leafp): Think this through and figure out what's the right
-    // definition.  Be careful about termination.
-    //
-    // I suspect in general a reasonable algorithm is to expand the innermost
-    // type variable first.  Alternatively, you could probably choose to treat
-    // it as just an instance of the interface type upper bound problem, with
-    // the "inheritance" chain extended by the bounds placed on the variables.
-    if (isSubtypeOf(type1, type2)) {
-      return type2;
-    }
-    if (isSubtypeOf(type2, type1)) {
-      return type1;
-    }
-    if (type1 is TypeParameterType) {
-      // TODO(paulberry): Analyzer collapses simple bounds in one step, i.e. for
-      // C<T extends U, U extends List>, T gets resolved directly to List.  Do
-      // we need to replicate that behavior?
-      return getStandardUpperBound(
-          Substitution.fromMap({type1.parameter: objectType})
-              .substituteType(type1.parameter.bound),
-          type2);
-    } else if (type2 is TypeParameterType) {
-      return getStandardUpperBound(
-          type1,
-          Substitution.fromMap({type2.parameter: objectType})
-              .substituteType(type2.parameter.bound));
-    } else {
-      // We should only be called when at least one of the types is a
-      // TypeParameterType
-      assert(false);
-      return const DynamicType();
-    }
-  }
 }
 
 class TypeVariableEliminator extends Substitution {
diff --git a/pkg/front_end/messages.status b/pkg/front_end/messages.status
index 762dc4f..9303b17 100644
--- a/pkg/front_end/messages.status
+++ b/pkg/front_end/messages.status
@@ -173,10 +173,13 @@
 FastaUsageLong/example: Fail
 FastaUsageShort/analyzerCode: Fail
 FastaUsageShort/example: Fail
-FfiAnnotationMissing/analyzerCode : Fail
+FfiFieldAnnotation/analyzerCode: Fail
+FfiFieldInitializer/analyzerCode: Fail
+FfiNotStatic/analyzerCode: Fail
+FfiStructAnnotation/analyzerCode: Fail
 FfiTypeInvalid/analyzerCode: Fail
 FfiTypeMismatch/analyzerCode: Fail
-FfiTypeOpaque/analyzerCode: Fail
+FfiTypeUnsized/analyzerCode: Fail
 FieldInitializedOutsideDeclaringClass/script1: Fail
 FieldInitializerOutsideConstructor/script1: Fail
 FinalAndCovariant/script2: Fail
@@ -218,6 +221,7 @@
 InvalidCastFunctionExpr/example: Fail
 InvalidCastLiteralList/example: Fail
 InvalidCastLiteralMap/example: Fail
+InvalidCastLiteralSet/example: Fail
 InvalidCastLocalFunction/example: Fail
 InvalidCastNewExpr/example: Fail
 InvalidCastStaticMethod/example: Fail
@@ -321,6 +325,7 @@
 SetLiteralTooManyTypeArguments/analyzerCode: Fail
 SetLiteralTooManyTypeArguments/example: Fail
 SetLiteralsNotSupported/analyzerCode: Fail
+SetLiteralsNotSupported/example: Fail
 SetOrMapLiteralTooManyTypeArguments/analyzerCode: Fail
 SetOrMapLiteralTooManyTypeArguments/example: Fail
 SetterNotFound/example: Fail
diff --git a/pkg/front_end/messages.yaml b/pkg/front_end/messages.yaml
index 847b9cb..023e1d2 100644
--- a/pkg/front_end/messages.yaml
+++ b/pkg/front_end/messages.yaml
@@ -1459,7 +1459,6 @@
 
 SetLiteralsNotSupported:
   template: "Set literals are not supported yet."
-  script: "var s = { 24 };"
 
 LoadLibraryTakesNoArguments:
   template: "'loadLibrary' takes no arguments."
@@ -2834,6 +2833,11 @@
   tip: "Change the type of the map literal or the context in which it is used."
   analyzerCode: INVALID_CAST_LITERAL_MAP
 
+InvalidCastLiteralSet:
+  template: "The set literal type '#type' isn't of expected type '#type2'."
+  tip: "Change the type of the set literal or the context in which it is used."
+  analyzerCode: INVALID_CAST_LITERAL_SET
+
 InvalidCastLocalFunction:
   template: "The local function has type '#type' that isn't of expected type '#type2'."
   tip: "Change the type of the function or the context in which it is used."
@@ -3006,7 +3010,9 @@
 InitializeFromDillUnknownProblem:
   template: |
     Tried to initialize from a previous compilation (#string), but couldn't.
-    Error message was '#string2'. This might be a bug.
+    Error message was '#string2'.
+    Stacktrace included '#string3'.
+    This might be a bug.
 
     The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
     If you are comfortable with it, it would improve the chances of fixing any bug if you included the file #uri in your error report, but be aware that this file includes your source code.
@@ -3019,7 +3025,9 @@
 InitializeFromDillUnknownProblemNoDump:
   template: |
     Tried to initialize from a previous compilation (#string), but couldn't.
-    Error message was '#string2'. This might be a bug.
+    Error message was '#string2'.
+    Stacktrace included '#string3'.
+    This might be a bug.
 
     The Dart team would greatly appreciate it if you would take a moment to report this problem at http://dartbug.com/new.
 
@@ -3426,15 +3434,30 @@
 
 FfiTypeInvalid:
   # Used by dart:ffi
-  template: "Expected type '#type' to be a valid and instantiated subtype of '_NativeType'."
+  template: "Expected type '#type' to be a valid and instantiated subtype of 'NativeType'."
   external: test/ffi_test.dart
 
-FfiTypeOpaque:
+FfiTypeUnsized:
   # Used by dart:ffi
-  template: "Method '#name' cannot be called on something of type '#type' as this type is opaque."
+  template: "Method '#name' cannot be called on something of type '#type' as this type is unsized."
   external: test/ffi_test.dart
 
-FfiAnnotationMissing:
+FfiFieldAnnotation:
   # Used by dart:ffi
-  template: "Field '#name' is missing an annotation to declare its C++ type,dart:ffi structs (Pointer<Void>) cannot have regular Dart fields."
+  template: "Field '#name' requires exactly one annotation to declare its C++ type, which cannot be Void. dart:ffi structs (Pointer<Void>) cannot have regular Dart fields."
+  external: test/ffi_test.dart
+
+FfiNotStatic:
+  # Used by dart:ffi
+  template: "#name expects a static function as parameter. dart:ffi only supports calling static Dart functions from c."
+  external: test/ffi_test.dart
+
+FfiFieldInitializer:
+  # Used by dart:ffi
+  template: "Field '#name' is a dart:ffi Pointer to a struct field and therefore cannot be initialized before constructor execution."
+  external: test/ffi_test.dart
+
+FfiStructAnnotation:
+  # Used by dart:ffi
+  template: "Class '#name' is a dart:ffi Pointer but has no struct annotation. Only struct Pointers can have fields."
   external: test/ffi_test.dart
diff --git a/pkg/front_end/pubspec.yaml b/pkg/front_end/pubspec.yaml
index cfc582b..4928c97 100644
--- a/pkg/front_end/pubspec.yaml
+++ b/pkg/front_end/pubspec.yaml
@@ -1,7 +1,7 @@
 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.9
+version: 0.1.11
 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
@@ -11,14 +11,14 @@
   charcode: '^1.1.1'
   convert: '^2.0.1'
   crypto: '^2.0.2'
-  kernel: 0.3.9
+  kernel: 0.3.11
   meta: '^1.1.1'
   package_config: '^1.0.1'
   path: '^1.3.9'
   source_span: '^1.2.3'
   yaml: '^2.1.12'
 dev_dependencies:
-  analyzer: 0.34.2
+  analyzer: 0.35.1
   args: '>=0.13.0 <2.0.0'
   build_integration:
     path: ../build_integration
diff --git a/pkg/front_end/test/fasta/types/fasta_types_test.dart b/pkg/front_end/test/fasta/types/fasta_types_test.dart
new file mode 100644
index 0000000..7f50ad6
--- /dev/null
+++ b/pkg/front_end/test/fasta/types/fasta_types_test.dart
@@ -0,0 +1,85 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import "package:async_helper/async_helper.dart" show asyncTest;
+
+import "package:kernel/ast.dart" show Component, DartType;
+
+import "package:kernel/core_types.dart" show CoreTypes;
+
+import "package:kernel/target/targets.dart" show NoneTarget, TargetFlags;
+
+import "package:front_end/src/api_prototype/compiler_options.dart"
+    show CompilerOptions;
+
+import "package:front_end/src/base/processed_options.dart"
+    show ProcessedOptions;
+
+import "package:front_end/src/fasta/compiler_context.dart" show CompilerContext;
+
+import "package:front_end/src/fasta/dill/dill_loader.dart" show DillLoader;
+
+import "package:front_end/src/fasta/dill/dill_target.dart" show DillTarget;
+
+import "package:front_end/src/fasta/kernel/kernel_builder.dart"
+    show ClassHierarchyBuilder, KernelClassBuilder;
+
+import "package:front_end/src/fasta/ticker.dart" show Ticker;
+
+import "kernel_type_parser.dart" show KernelEnvironment, KernelFromParsedType;
+
+import "kernel_type_parser_test.dart" show parseSdk;
+
+import "shared_type_tests.dart" show SubtypeTest;
+
+import "type_parser.dart" as type_parser show parse, parseTypeVariables;
+
+main() {
+  final Ticker ticker = Ticker();
+  final CompilerContext context = new CompilerContext(new ProcessedOptions(
+      options: new CompilerOptions()
+        ..packagesFileUri = Uri.base.resolve(".packages")));
+  final Uri uri = Uri.parse("dart:core");
+  final KernelEnvironment environment = new KernelEnvironment(uri, uri);
+  final Component sdk = parseSdk(uri, environment);
+  Future<void> doIt(_) async {
+    DillTarget target = new DillTarget(
+        ticker,
+        await context.options.getUriTranslator(),
+        new NoneTarget(new TargetFlags()));
+    final DillLoader loader = target.loader;
+    loader.appendLibraries(sdk);
+    await target.buildOutlines();
+    KernelClassBuilder objectClass = loader.coreLibrary["Object"];
+    ClassHierarchyBuilder hierarchy =
+        new ClassHierarchyBuilder(objectClass, loader, new CoreTypes(sdk));
+    new FastaTypesTest(hierarchy, environment).run();
+  }
+
+  asyncTest(() => context.runInContext<void>(doIt));
+}
+
+class FastaTypesTest extends SubtypeTest<DartType, KernelEnvironment> {
+  final ClassHierarchyBuilder hierarchy;
+
+  final KernelEnvironment environment;
+
+  FastaTypesTest(this.hierarchy, this.environment);
+
+  DartType toType(String text, KernelEnvironment environment) {
+    return environment.kernelFromParsedType(type_parser.parse(text).single);
+  }
+
+  bool isSubtypeImpl(DartType subtype, DartType supertype) {
+    return hierarchy.types.isSubtypeOfKernel(subtype, supertype);
+  }
+
+  KernelEnvironment extend(String typeParameters) {
+    if (typeParameters?.isEmpty ?? true) return environment;
+    return const KernelFromParsedType()
+        .computeTypeParameterEnvironment(
+            type_parser.parseTypeVariables("<$typeParameters>"), environment)
+        .environment;
+  }
+}
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser.dart b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
index 208728d..86f8a68 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser.dart
@@ -4,6 +4,7 @@
 
 import "package:kernel/ast.dart"
     show
+        BottomType,
         Class,
         DartType,
         DynamicType,
@@ -17,9 +18,12 @@
         TypeParameter,
         TypeParameterType,
         Typedef,
+        TypedefType,
         VoidType,
         setParents;
 
+import "package:kernel/src/bounds_checks.dart" show calculateBounds;
+
 import "type_parser.dart" as type_parser show parse;
 
 import "type_parser.dart"
@@ -44,6 +48,8 @@
     Node node = environment.kernelFromParsedType(type);
     if (node is Class) {
       library.addClass(node);
+    } else if (node is Typedef) {
+      library.addTypedef(node);
     } else {
       throw "Unsupported: $node";
     }
@@ -93,7 +99,21 @@
 
   DartType visitInterfaceType(
       ParsedInterfaceType node, KernelEnvironment environment) {
-    TreeNode declaration = environment[node.name];
+    String name = node.name;
+    if (name == "dynamic") {
+      // Don't return a const object to ensure we test implementations that use
+      // identical.
+      return new DynamicType();
+    } else if (name == "void") {
+      // Don't return a const object to ensure we test implementations that use
+      // identical.
+      return new VoidType();
+    } else if (name == "bottom") {
+      // Don't return a const object to ensure we test implementations that use
+      // identical.
+      return new BottomType();
+    }
+    TreeNode declaration = environment[name];
     List<ParsedType> arguments = node.arguments;
     List<DartType> kernelArguments =
         new List<DartType>.filled(arguments.length, null);
@@ -102,12 +122,23 @@
           arguments[i].accept<Node, KernelEnvironment>(this, environment);
     }
     if (declaration is Class) {
+      List<TypeParameter> typeVariables = declaration.typeParameters;
+      if (kernelArguments.isEmpty && typeVariables.isNotEmpty) {
+        kernelArguments = new List<DartType>.filled(typeVariables.length, null);
+        for (int i = 0; i < typeVariables.length; i++) {
+          kernelArguments[i] = typeVariables[i].defaultType;
+        }
+      } else if (kernelArguments.length != typeVariables.length) {
+        throw "Expected ${typeVariables.length} type arguments: $node";
+      }
       return new InterfaceType(declaration, kernelArguments);
     } else if (declaration is TypeParameter) {
       if (arguments.isNotEmpty) {
         throw "Type variable can't have arguments (${node.name})";
       }
       return new TypeParameterType(declaration);
+    } else if (declaration is Typedef) {
+      return new TypedefType(declaration, kernelArguments);
     } else {
       throw "Unhandled ${declaration.runtimeType}";
     }
@@ -143,7 +174,26 @@
   }
 
   Typedef visitTypedef(ParsedTypedef node, KernelEnvironment environment) {
-    throw "not implemented: $node";
+    String name = node.name;
+    Typedef def = environment[name] =
+        new Typedef(name, null, fileUri: environment.fileUri);
+    ParameterEnvironment parameterEnvironment =
+        computeTypeParameterEnvironment(node.typeVariables, environment);
+    def.typeParameters.addAll(parameterEnvironment.parameters);
+    DartType type;
+    {
+      KernelEnvironment environment = parameterEnvironment.environment;
+      type = node.type.accept<Node, KernelEnvironment>(this, environment);
+      if (type is FunctionType) {
+        FunctionType f = type;
+        type = new FunctionType(f.positionalParameters, f.returnType,
+            namedParameters: f.namedParameters,
+            typeParameters: f.typeParameters,
+            requiredParameterCount: f.requiredParameterCount,
+            typedefType: def.thisType);
+      }
+    }
+    return def..type = type;
   }
 
   FunctionType visitFunctionType(
@@ -173,6 +223,7 @@
         }
       }
     }
+    namedParameters.sort();
     return new FunctionType(positionalParameters, returnType,
         namedParameters: namedParameters,
         requiredParameterCount: node.arguments.required.length,
@@ -211,22 +262,29 @@
     }
     KernelEnvironment nestedEnvironment =
         environment.extend(typeParametersByName);
+    Class objectClass = environment.objectClass;
     for (int i = 0; i < typeVariables.length; i++) {
       ParsedType bound = typeVariables[i].bound;
       TypeParameter typeParameter = typeParameters[i];
       if (bound == null) {
         typeParameter
-          ..bound = environment.objectClass.rawType
+          ..bound = objectClass.rawType
           ..defaultType = const DynamicType();
       } else {
         DartType type =
             bound.accept<Node, KernelEnvironment>(this, nestedEnvironment);
         typeParameter
           ..bound = type
-          ..defaultType = type; // TODO(ahe): Is this correct?
-
+          // The default type will be overridden below, but we need to set it
+          // so [calculateBounds] can destinquish between explicit and implicit
+          // bounds.
+          ..defaultType = type;
       }
     }
+    List<DartType> defaultTypes = calculateBounds(typeParameters, objectClass);
+    for (int i = 0; i < typeParameters.length; i++) {
+      typeParameters[i].defaultType = defaultTypes[i];
+    }
     return new ParameterEnvironment(typeParameters, nestedEnvironment);
   }
 }
diff --git a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart b/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
index 21c9a4d..ea220ac 100644
--- a/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
+++ b/pkg/front_end/test/fasta/types/kernel_type_parser_test.dart
@@ -22,23 +22,34 @@
 import "type_parser.dart" as type_parser show parse, parseTypeVariables;
 
 const String testSdk = """
-  class Object;
-  class Comparable<T>;
-  class num implements Comparable<num>;
-  class int extends num;
-  class double extends num;
-  class Iterable<T>;
-  class List<T> extends Iterable<T>;
-  class Future<T>;
-  class FutureOr<T>;
-  class Null;
-  class Function;
+class Object;
+class Comparable<T>;
+class num implements Comparable<num>;
+class int extends num;
+class double extends num;
+class Iterable<T>;
+class List<T> extends Iterable<T>;
+class Future<T>;
+class FutureOr<T>;
+class Null;
+class Function;
+typedef Typedef<T> <S>(T) -> S;
+typedef VoidFunction () -> void;
+class DefaultTypes<S, T extends Object, U extends List<S>, V extends List<T>, W extends Comparable<W>, X extends (W) -> void, Y extends () -> W>;
+typedef TestDefaultTypes () -> DefaultTypes;
+typedef Id<T> T;
+typedef TestSorting ({int c, int b, int a}) -> void;
 """;
 
 const String expectedSdk = """
 library core;
 import self as self;
 
+typedef Typedef<T extends self::Object = dynamic> = <S extends self::Object = dynamic>(T) → S;
+typedef VoidFunction = () → void;
+typedef TestDefaultTypes = () → self::DefaultTypes<dynamic, self::Object, self::List<dynamic>, self::List<self::Object>, self::Comparable<dynamic>, (<BottomType>) → void, () → self::Comparable<dynamic>>;
+typedef Id<T extends self::Object = dynamic> = T;
+typedef TestSorting = ({a: self::int, b: self::int, c: self::int}) → void;
 class Object {
 }
 class Comparable<T extends self::Object = dynamic> extends self::Object {
@@ -61,17 +72,23 @@
 }
 class Function extends self::Object {
 }
+class DefaultTypes<S extends self::Object = dynamic, T extends self::Object = self::Object, U extends self::List<self::DefaultTypes::S> = self::List<dynamic>, V extends self::List<self::DefaultTypes::T> = self::List<self::Object>, W extends self::Comparable<self::DefaultTypes::W> = self::Comparable<dynamic>, X extends (self::DefaultTypes::W) → void = (<BottomType>) → void, Y extends () → self::DefaultTypes::W = () → self::Comparable<dynamic>> extends self::Object {
+}
 """;
 
-main() {
-  Uri uri = Uri.parse("dart:core");
-  KernelEnvironment environment = new KernelEnvironment(uri, uri);
+Component parseSdk(Uri uri, KernelEnvironment environment) {
   Library library = parseLibrary(uri, testSdk, environment: environment);
   StringBuffer sb = new StringBuffer();
   Printer printer = new Printer(sb);
   printer.writeLibraryFile(library);
   Expect.stringEquals(expectedSdk, "$sb");
-  Component component = new Component(libraries: <Library>[library]);
+  return new Component(libraries: <Library>[library]);
+}
+
+main() {
+  Uri uri = Uri.parse("dart:core");
+  KernelEnvironment environment = new KernelEnvironment(uri, uri);
+  Component component = parseSdk(uri, environment);
   ClassHierarchy hierarchy = new ClassHierarchy(component);
   CoreTypes coreTypes = new CoreTypes(component);
   new KernelSubtypeTest(coreTypes, hierarchy, environment).run();
@@ -90,8 +107,8 @@
     return environment.kernelFromParsedType(type_parser.parse(text).single);
   }
 
-  bool isSubtypeImpl(DartType subtype, DartType supertype, bool legacyMode) {
-    return new TypeEnvironment(coreTypes, hierarchy, legacyMode: legacyMode)
+  bool isSubtypeImpl(DartType subtype, DartType supertype) {
+    return new TypeEnvironment(coreTypes, hierarchy)
         .isSubtypeOf(subtype, supertype);
   }
 
diff --git a/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
new file mode 100644
index 0000000..24b04d2
--- /dev/null
+++ b/pkg/front_end/test/fasta/types/legacy_upper_bound_test.dart
@@ -0,0 +1,292 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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/matchers_lite.dart";
+
+import "package:kernel/ast.dart";
+import "package:kernel/class_hierarchy.dart";
+import "package:kernel/core_types.dart";
+import "package:kernel/testing/mock_sdk_component.dart";
+import "package:kernel/text/ast_to_text.dart";
+import "package:kernel/type_algebra.dart";
+
+main() {
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_expansive();
+
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_generic();
+
+  new LegacyUpperBoundTest().test_getLegacyLeastUpperBound_nonGeneric();
+}
+
+class LegacyUpperBoundTest {
+  final Component component = createMockSdkComponent();
+
+  CoreTypes coreTypes;
+
+  final Library library =
+      new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
+
+  ClassHierarchy _hierarchy;
+
+  LegacyUpperBoundTest() {
+    coreTypes = new CoreTypes(component);
+    library.parent = component;
+    component.libraries.add(library);
+  }
+
+  Class get objectClass => coreTypes.objectClass;
+
+  Supertype get objectSuper => coreTypes.objectClass.asThisSupertype;
+
+  ClassHierarchy get hierarchy {
+    return _hierarchy ??= createClassHierarchy(component);
+  }
+
+  Class addClass(Class c) {
+    if (_hierarchy != null) {
+      fail('The classs hierarchy has already been created.');
+    }
+    library.addClass(c);
+    return c;
+  }
+
+  /// Assert that the test [library] has the [expectedText] presentation.
+  /// The presentation is close, but not identical to the normal Kernel one.
+  void _assertTestLibraryText(String expectedText) {
+    _assertLibraryText(library, expectedText);
+  }
+
+  void _assertLibraryText(Library lib, String expectedText) {
+    StringBuffer sb = new StringBuffer();
+    Printer printer = new Printer(sb);
+    printer.writeLibraryFile(lib);
+
+    String actualText = sb.toString();
+
+    // Clean up the text a bit.
+    const oftenUsedPrefix = '''
+library test;
+import self as self;
+import "dart:core" as core;
+
+''';
+    if (actualText.startsWith(oftenUsedPrefix)) {
+      actualText = actualText.substring(oftenUsedPrefix.length);
+    }
+    actualText = actualText.replaceAll('{\n}', '{}');
+    actualText = actualText.replaceAll(' extends core::Object', '');
+
+    if (actualText != expectedText) {
+      print('-------- Actual --------');
+      print(actualText + '------------------------');
+    }
+
+    expect(actualText, expectedText);
+  }
+
+  ClassHierarchy createClassHierarchy(Component component) {
+    return new ClassHierarchy(component);
+  }
+
+  /// Add a new generic class with the given [name] and [typeParameterNames].
+  /// The [TypeParameterType]s corresponding to [typeParameterNames] are
+  /// passed to optional [extends_] and [implements_] callbacks.
+  Class addGenericClass(String name, List<String> typeParameterNames,
+      {Supertype extends_(List<DartType> typeParameterTypes),
+      List<Supertype> implements_(List<DartType> typeParameterTypes)}) {
+    var typeParameters = typeParameterNames
+        .map((name) => new TypeParameter(name, objectClass.rawType))
+        .toList();
+    var typeParameterTypes = typeParameters
+        .map((parameter) => new TypeParameterType(parameter))
+        .toList();
+    var supertype =
+        extends_ != null ? extends_(typeParameterTypes) : objectSuper;
+    var implementedTypes =
+        implements_ != null ? implements_(typeParameterTypes) : <Supertype>[];
+    return addClass(new Class(
+        name: name,
+        typeParameters: typeParameters,
+        supertype: supertype,
+        implementedTypes: implementedTypes));
+  }
+
+  /// Add a new class with the given [name] that extends `Object` and
+  /// [implements_] the given classes.
+  Class addImplementsClass(String name, List<Class> implements_) {
+    return addClass(new Class(
+        name: name,
+        supertype: objectSuper,
+        implementedTypes: implements_.map((c) => c.asThisSupertype).toList()));
+  }
+
+  /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
+  void test_getLegacyLeastUpperBound_expansive() {
+    var int = coreTypes.intClass.rawType;
+    var string = coreTypes.stringClass.rawType;
+
+    // class N<T> {}
+    var NT = new TypeParameter('T', objectClass.rawType);
+    var N = addClass(
+        new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
+
+    // class C1<T> extends N<N<C1<T>>> {}
+    Class C1;
+    {
+      var T = new TypeParameter('T', objectClass.rawType);
+      C1 = addClass(
+          new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
+      DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
+          .substituteType(C1.thisType);
+      DartType N_C1_T =
+          Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
+      Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
+          .substituteSupertype(N.asThisSupertype);
+      C1.supertype = N_N_C1_T;
+    }
+
+    // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
+    Class C2;
+    {
+      var T = new TypeParameter('T', objectClass.rawType);
+      C2 = addClass(
+          new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
+      DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
+          .substituteType(C2.thisType);
+      DartType N_C2_T =
+          Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
+      DartType C2_N_C2_T =
+          Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
+      DartType N_C2_N_C2_T =
+          Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
+      Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
+          .substituteSupertype(N.asThisSupertype);
+      C2.supertype = N_N_C2_N_C2_T;
+    }
+
+    _assertTestLibraryText('''
+class N<T> {}
+class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
+class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
+''');
+
+    // The least upper bound of C1<int> and N<C1<String>> is Object since the
+    // supertypes are
+    //     {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
+    //     {N<C1<String>>, Object} for N<C1<String>> and
+    // Object is the most specific type in the intersection of the supertypes.
+    expect(
+        hierarchy.getLegacyLeastUpperBound(
+            new InterfaceType(C1, [int]),
+            new InterfaceType(N, [
+              new InterfaceType(C1, [string])
+            ])),
+        objectClass.thisType);
+
+    // The least upper bound of C2<int> and N<C2<String>> is Object since the
+    // supertypes are
+    //     {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
+    //     {N<C2<String>>, Object} for N<C2<String>> and
+    // Object is the most specific type in the intersection of the supertypes.
+    expect(
+        hierarchy.getLegacyLeastUpperBound(
+            new InterfaceType(C2, [int]),
+            new InterfaceType(N, [
+              new InterfaceType(C2, [string])
+            ])),
+        objectClass.thisType);
+  }
+
+  void test_getLegacyLeastUpperBound_generic() {
+    var int = coreTypes.intClass.rawType;
+    var double = coreTypes.doubleClass.rawType;
+    var bool = coreTypes.boolClass.rawType;
+
+    var a = addGenericClass('A', []);
+    var b =
+        addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]);
+    var c =
+        addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]);
+    var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) {
+      var t = typeParameterTypes[0];
+      var u = typeParameterTypes[1];
+      return [
+        new Supertype(b, [t]),
+        new Supertype(c, [u])
+      ];
+    });
+    var e = addGenericClass('E', [],
+        implements_: (_) => [
+              new Supertype(d, [int, double])
+            ]);
+    var f = addGenericClass('F', [],
+        implements_: (_) => [
+              new Supertype(d, [int, bool])
+            ]);
+
+    _assertTestLibraryText('''
+class A {}
+class B<T> implements self::A {}
+class C<U> implements self::A {}
+class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
+class E implements self::D<core::int, core::double> {}
+class F implements self::D<core::int, core::bool> {}
+''');
+
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [int, double])),
+        new InterfaceType(d, [int, double]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [int, bool])),
+        new InterfaceType(b, [int]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [bool, double])),
+        new InterfaceType(c, [double]));
+    expect(
+        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
+            new InterfaceType(d, [bool, int])),
+        a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
+        new InterfaceType(b, [int]));
+  }
+
+  void test_getLegacyLeastUpperBound_nonGeneric() {
+    var a = addImplementsClass('A', []);
+    var b = addImplementsClass('B', []);
+    var c = addImplementsClass('C', [a]);
+    var d = addImplementsClass('D', [a]);
+    var e = addImplementsClass('E', [a]);
+    var f = addImplementsClass('F', [c, d]);
+    var g = addImplementsClass('G', [c, d]);
+    var h = addImplementsClass('H', [c, d, e]);
+    var i = addImplementsClass('I', [c, d, e]);
+
+    _assertTestLibraryText('''
+class A {}
+class B {}
+class C implements self::A {}
+class D implements self::A {}
+class E implements self::A {}
+class F implements self::C, self::D {}
+class G implements self::C, self::D {}
+class H implements self::C, self::D, self::E {}
+class I implements self::C, self::D, self::E {}
+''');
+
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
+        objectClass.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
+    expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
+  }
+}
diff --git a/pkg/front_end/test/fasta/types/shared_type_tests.dart b/pkg/front_end/test/fasta/types/shared_type_tests.dart
index 4d81dcf..38093c4 100644
--- a/pkg/front_end/test/fasta/types/shared_type_tests.dart
+++ b/pkg/front_end/test/fasta/types/shared_type_tests.dart
@@ -6,126 +6,102 @@
 
 abstract class SubtypeTest<T, E> {
   void isSubtype(String subtypeString, String supertypeString,
-      {bool legacyMode: false, String typeParameters}) {
+      {String typeParameters}) {
     E environment = extend(typeParameters);
     T subtype = toType(subtypeString, environment);
     T supertype = toType(supertypeString, environment);
-    String mode = legacyMode ? " (legacy)" : "";
-    Expect.isTrue(isSubtypeImpl(subtype, supertype, legacyMode),
-        "$subtypeString should be a subtype of $supertypeString$mode.");
+    Expect.isTrue(isSubtypeImpl(subtype, supertype),
+        "$subtypeString should be a subtype of $supertypeString.");
   }
 
   void isNotSubtype(String subtypeString, String supertypeString,
-      {bool legacyMode: false, String typeParameters}) {
+      {String typeParameters}) {
     E environment = extend(typeParameters);
     T subtype = toType(subtypeString, environment);
     T supertype = toType(supertypeString, environment);
-    String mode = legacyMode ? " (legacy)" : "";
-    Expect.isFalse(isSubtypeImpl(subtype, supertype, legacyMode),
-        "$subtypeString shouldn't be a subtype of $supertypeString$mode.");
+    Expect.isFalse(isSubtypeImpl(subtype, supertype),
+        "$subtypeString shouldn't be a subtype of $supertypeString.");
   }
 
   T toType(String text, E environment);
 
-  bool isSubtypeImpl(T subtype, T supertype, bool legacyMode);
+  bool isSubtypeImpl(T subtype, T supertype);
 
   E extend(String typeParameters);
 
   void run() {
-    isSubtype('int', 'num', legacyMode: true);
-    isSubtype('int', 'Comparable<num>', legacyMode: true);
-    isSubtype('int', 'Comparable<Object>', legacyMode: true);
-    isSubtype('int', 'Object', legacyMode: true);
-    isSubtype('double', 'num', legacyMode: true);
+    isSubtype('int', 'num');
+    isSubtype('int', 'Comparable<num>');
+    isSubtype('int', 'Comparable<Object>');
+    isSubtype('int', 'Object');
+    isSubtype('double', 'num');
 
-    isNotSubtype('int', 'double', legacyMode: true);
-    isNotSubtype('int', 'Comparable<int>', legacyMode: true);
-    isNotSubtype('int', 'Iterable<int>', legacyMode: true);
-    isNotSubtype('Comparable<int>', 'Iterable<int>', legacyMode: true);
+    isNotSubtype('int', 'double');
+    isNotSubtype('int', 'Comparable<int>');
+    isNotSubtype('int', 'Iterable<int>');
+    isNotSubtype('Comparable<int>', 'Iterable<int>');
 
-    isSubtype('List<int>', 'List<int>', legacyMode: true);
-    isSubtype('List<int>', 'Iterable<int>', legacyMode: true);
-    isSubtype('List<int>', 'List<num>', legacyMode: true);
-    isSubtype('List<int>', 'Iterable<num>', legacyMode: true);
-    isSubtype('List<int>', 'List<Object>', legacyMode: true);
-    isSubtype('List<int>', 'Iterable<Object>', legacyMode: true);
-    isSubtype('List<int>', 'Object', legacyMode: true);
-    isSubtype('List<int>', 'List<Comparable<Object>>', legacyMode: true);
-    isSubtype('List<int>', 'List<Comparable<num>>', legacyMode: true);
-    isSubtype('List<int>', 'List<Comparable<Comparable<num>>>',
-        legacyMode: true);
+    isSubtype('List<int>', 'List<int>');
+    isSubtype('List<int>', 'Iterable<int>');
+    isSubtype('List<int>', 'List<num>');
+    isSubtype('List<int>', 'Iterable<num>');
+    isSubtype('List<int>', 'List<Object>');
+    isSubtype('List<int>', 'Iterable<Object>');
+    isSubtype('List<int>', 'Object');
+    isSubtype('List<int>', 'List<Comparable<Object>>');
+    isSubtype('List<int>', 'List<Comparable<num>>');
+    isSubtype('List<int>', 'List<Comparable<Comparable<num>>>');
 
-    isNotSubtype('List<int>', 'List<double>', legacyMode: true);
-    isNotSubtype('List<int>', 'Iterable<double>', legacyMode: true);
-    isNotSubtype('List<int>', 'Comparable<int>', legacyMode: true);
-    isNotSubtype('List<int>', 'List<Comparable<int>>', legacyMode: true);
-    isNotSubtype('List<int>', 'List<Comparable<Comparable<int>>>',
-        legacyMode: true);
+    isNotSubtype('List<int>', 'List<double>');
+    isNotSubtype('List<int>', 'Iterable<double>');
+    isNotSubtype('List<int>', 'Comparable<int>');
+    isNotSubtype('List<int>', 'List<Comparable<int>>');
+    isNotSubtype('List<int>', 'List<Comparable<Comparable<int>>>');
 
-    isSubtype('(num) -> num', '(int) -> num', legacyMode: true);
-    isSubtype('(num) -> int', '(num) -> num', legacyMode: true);
-    isSubtype('(num) -> int', '(int) -> num', legacyMode: true);
-    isNotSubtype('(int) -> int', '(num) -> num', legacyMode: true);
+    isSubtype('(num) -> num', '(int) -> num');
+    isSubtype('(num) -> int', '(num) -> num');
+    isSubtype('(num) -> int', '(int) -> num');
+    isNotSubtype('(int) -> int', '(num) -> num');
+    isSubtype('Null', '(int) -> num');
 
-    isSubtype('(num) -> (num) -> num', '(num) -> (int) -> num',
-        legacyMode: true);
-    isNotSubtype('(num) -> (int) -> int', '(num) -> (num) -> num',
-        legacyMode: true);
+    isSubtype('(num) -> (num) -> num', '(num) -> (int) -> num');
+    isNotSubtype('(num) -> (int) -> int', '(num) -> (num) -> num');
 
-    isSubtype('({num x}) -> num', '({int x}) -> num',
-        legacyMode: true); // named parameters
-    isSubtype('(num, {num x}) -> num', '(int, {int x}) -> num',
-        legacyMode: true);
-    isSubtype('({num x}) -> int', '({num x}) -> num', legacyMode: true);
-    isNotSubtype('({int x}) -> int', '({num x}) -> num', legacyMode: true);
+    isSubtype('({num x}) -> num', '({int x}) -> num'); // named parameters
+    isSubtype('(num, {num x}) -> num', '(int, {int x}) -> num');
+    isSubtype('({num x}) -> int', '({num x}) -> num');
+    isNotSubtype('({int x}) -> int', '({num x}) -> num');
 
-    isSubtype('<E>(E) -> int', '<E>(E) -> num',
-        legacyMode: true); // type parameters
-    isSubtype('<E>(num) -> E', '<E>(int) -> E', legacyMode: true);
-    isSubtype('<E>(E,num) -> E', '<E>(E,int) -> E', legacyMode: true);
-    isNotSubtype('<E>(E,num) -> E', '<E>(E,E) -> E', legacyMode: true);
+    isSubtype('<E>(E) -> int', '<E>(E) -> num'); // type parameters
+    isSubtype('<E>(num) -> E', '<E>(int) -> E');
+    isSubtype('<E>(E,num) -> E', '<E>(E,int) -> E');
+    isNotSubtype('<E>(E,num) -> E', '<E>(E,E) -> E');
 
-    isSubtype('<E>(E) -> (E) -> E', '<F>(F) -> (F) -> F', legacyMode: true);
-    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (int,E) -> E) -> E',
-        legacyMode: true);
-    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (num,E) -> E) -> E',
-        legacyMode: true);
-    isNotSubtype('<E,F>(E) -> (F) -> E', '<E>(E) -> <F>(F) -> E',
-        legacyMode: true);
-    isNotSubtype('<E,F>(E) -> (F) -> E', '<F,E>(E) -> (F) -> E',
-        legacyMode: true);
+    isSubtype('<E>(E) -> (E) -> E', '<F>(F) -> (F) -> F');
+    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (int,E) -> E) -> E');
+    isSubtype('<E>(E, (int,E) -> E) -> E', '<E>(E, (num,E) -> E) -> E');
+    isNotSubtype('<E,F>(E) -> (F) -> E', '<E>(E) -> <F>(F) -> E');
+    isNotSubtype('<E,F>(E) -> (F) -> E', '<F,E>(E) -> (F) -> E');
 
-    isNotSubtype('<E>(E,num) -> E', '<E extends num>(E,E) -> E',
-        legacyMode: true);
-    isNotSubtype('<E extends num>(E) -> int', '<E extends int>(E) -> int',
-        legacyMode: true);
-    isNotSubtype('<E extends num>(E) -> E', '<E extends int>(E) -> E',
-        legacyMode: true);
-    isNotSubtype('<E extends num>(int) -> E', '<E extends int>(int) -> E',
-        legacyMode: true);
-    isSubtype('<E extends num>(E) -> E', '<F extends num>(F) -> num',
-        legacyMode: true);
-    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> num',
-        legacyMode: true);
-    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> int',
-        legacyMode: true);
-    isNotSubtype('<E>(int) -> int', '(int) -> int', legacyMode: true);
-    isNotSubtype('<E,F>(int) -> int', '<E>(int) -> int', legacyMode: true);
+    isNotSubtype('<E>(E,num) -> E', '<E extends num>(E,E) -> E');
+    isNotSubtype('<E extends num>(E) -> int', '<E extends int>(E) -> int');
+    isNotSubtype('<E extends num>(E) -> E', '<E extends int>(E) -> E');
+    isNotSubtype('<E extends num>(int) -> E', '<E extends int>(int) -> E');
+    isSubtype('<E extends num>(E) -> E', '<F extends num>(F) -> num');
+    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> num');
+    isSubtype('<E extends int>(E) -> E', '<F extends int>(F) -> int');
+    isNotSubtype('<E>(int) -> int', '(int) -> int');
+    isNotSubtype('<E,F>(int) -> int', '<E>(int) -> int');
 
-    isSubtype('<E extends List<E>>(E) -> E', '<F extends List<F>>(F) -> F',
-        legacyMode: true);
+    isSubtype('<E extends List<E>>(E) -> E', '<F extends List<F>>(F) -> F');
     isNotSubtype(
-        '<E extends Iterable<E>>(E) -> E', '<F extends List<F>>(F) -> F',
-        legacyMode: true);
-    isNotSubtype('<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> F',
-        legacyMode: true);
+        '<E extends Iterable<E>>(E) -> E', '<F extends List<F>>(F) -> F');
+    isNotSubtype('<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> F');
     isNotSubtype(
-        '<E>(E,List<Object>) -> List<E>', '<F extends List<F>>(F,F) -> F',
-        legacyMode: true);
-    isNotSubtype('<E>(E,List<Object>) -> int', '<F extends List<F>>(F,F) -> F',
-        legacyMode: true);
-    isNotSubtype('<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> void',
-        legacyMode: true);
+        '<E>(E,List<Object>) -> List<E>', '<F extends List<F>>(F,F) -> F');
+    isNotSubtype('<E>(E,List<Object>) -> int', '<F extends List<F>>(F,F) -> F');
+    isNotSubtype(
+        '<E>(E,List<Object>) -> E', '<F extends List<F>>(F,F) -> void');
 
     isSubtype('int', 'FutureOr<int>');
     isSubtype('int', 'FutureOr<num>');
@@ -139,53 +115,237 @@
     isNotSubtype('FutureOr<double>', 'int');
     isNotSubtype('FutureOr<int>', 'Future<num>');
     isNotSubtype('FutureOr<int>', 'num');
+    isSubtype('Null', 'FutureOr<int>');
+    isSubtype('Null', 'Future<int>');
 
     // T & B <: T & A if B <: A
-    isSubtype('T & int', 'T & int', legacyMode: true, typeParameters: 'T');
-    isSubtype('T & int', 'T & num', legacyMode: true, typeParameters: 'T');
-    isSubtype('T & num', 'T & num', legacyMode: true, typeParameters: 'T');
-    isNotSubtype('T & num', 'T & int', legacyMode: true, typeParameters: 'T');
+    isSubtype('T & int', 'T & int', typeParameters: 'T');
+    isSubtype('T & int', 'T & num', typeParameters: 'T');
+    isSubtype('T & num', 'T & num', typeParameters: 'T');
+    isNotSubtype('T & num', 'T & int', typeParameters: 'T');
+    isSubtype('Null', 'T & num', typeParameters: 'T');
 
     // T & B <: T extends A if B <: A
     // (Trivially satisfied since promoted bounds are always a isSubtype of the
     // original bound)
-    isSubtype('T & int', 'T',
-        legacyMode: true, typeParameters: 'T extends int');
-    isSubtype('T & int', 'T',
-        legacyMode: true, typeParameters: 'T extends num');
-    isSubtype('T & num', 'T',
-        legacyMode: true, typeParameters: 'T extends num');
+    isSubtype('T & int', 'T', typeParameters: 'T extends int');
+    isSubtype('T & int', 'T', typeParameters: 'T extends num');
+    isSubtype('T & num', 'T', typeParameters: 'T extends num');
 
     // T extends B <: T & A if B <: A
-    isSubtype('T', 'T & int',
-        legacyMode: true, typeParameters: 'T extends int');
-    isSubtype('T', 'T & num',
-        legacyMode: true, typeParameters: 'T extends int');
-    isSubtype('T', 'T & num',
-        legacyMode: true, typeParameters: 'T extends num');
-    isNotSubtype('T', 'T & int',
-        legacyMode: true, typeParameters: 'T extends num');
+    isSubtype('T', 'T & int', typeParameters: 'T extends int');
+    isSubtype('T', 'T & num', typeParameters: 'T extends int');
+    isSubtype('T', 'T & num', typeParameters: 'T extends num');
+    isNotSubtype('T', 'T & int', typeParameters: 'T extends num');
 
     // T extends A <: T extends A
-    isSubtype('T', 'T', legacyMode: true, typeParameters: 'T extends num');
+    isSubtype('T', 'T', typeParameters: 'T extends num');
 
     // S & B <: A if B <: A, A is not S (or a promotion thereof)
-    isSubtype('S & int', 'int', legacyMode: true, typeParameters: 'S');
-    isSubtype('S & int', 'num', legacyMode: true, typeParameters: 'S');
-    isSubtype('S & num', 'num', legacyMode: true, typeParameters: 'S');
-    isNotSubtype('S & num', 'int', legacyMode: true, typeParameters: 'S');
-    isNotSubtype('S & num', 'T', legacyMode: true, typeParameters: 'S, T');
-    isNotSubtype('S & num', 'T & num',
-        legacyMode: true, typeParameters: 'S, T');
+    isSubtype('S & int', 'int', typeParameters: 'S');
+    isSubtype('S & int', 'num', typeParameters: 'S');
+    isSubtype('S & num', 'num', typeParameters: 'S');
+    isNotSubtype('S & num', 'int', typeParameters: 'S');
+    isNotSubtype('S & num', 'T', typeParameters: 'S, T');
+    isNotSubtype('S & num', 'T & num', typeParameters: 'S, T');
 
     // S extends B <: A if B <: A, A is not S (or a promotion thereof)
-    isSubtype('S', 'int', legacyMode: true, typeParameters: 'S extends int');
-    isSubtype('S', 'num', legacyMode: true, typeParameters: 'S extends int');
-    isSubtype('S', 'num', legacyMode: true, typeParameters: 'S extends num');
-    isNotSubtype('S', 'int', legacyMode: true, typeParameters: 'S extends num');
-    isNotSubtype('S', 'T',
-        legacyMode: true, typeParameters: 'S extends num, T');
-    isNotSubtype('S', 'T & num',
-        legacyMode: true, typeParameters: 'S extends num, T');
+    isSubtype('S', 'int', typeParameters: 'S extends int');
+    isSubtype('S', 'num', typeParameters: 'S extends int');
+    isSubtype('S', 'num', typeParameters: 'S extends num');
+    isNotSubtype('S', 'int', typeParameters: 'S extends num');
+    isNotSubtype('S', 'T', typeParameters: 'S extends num, T');
+    isNotSubtype('S', 'T & num', typeParameters: 'S extends num, T');
+
+    isNotSubtype('dynamic', 'int');
+    isNotSubtype('void', 'int');
+    isNotSubtype('() -> int', 'int');
+    isNotSubtype('Typedef<Object>', 'int');
+    isSubtype('() -> int', 'Function');
+    isSubtype('() -> int', 'Object');
+
+    isNotSubtype('Null', 'bottom');
+    isSubtype('Null', 'Object');
+    isSubtype('Null', 'void');
+    isSubtype('Null', 'dynamic');
+    isSubtype('Null', 'double');
+    isSubtype('Null', 'Comparable<Object>');
+    isSubtype('Null', 'Typedef<Object>');
+    isSubtype('Null', 'T', typeParameters: 'T');
+
+    isSubtype('Null', 'Null');
+    isSubtype('bottom', 'bottom');
+    isSubtype('Object', 'Object');
+    isSubtype('Object', 'dynamic');
+    isSubtype('Object', 'void');
+    isSubtype('dynamic', 'Object');
+    isSubtype('dynamic', 'dynamic');
+    isSubtype('dynamic', 'void');
+    isSubtype('void', 'Object');
+    isSubtype('void', 'dynamic');
+    isSubtype('void', 'void');
+
+    // Check that the top types are equivalent.
+    isSubtype('<S extends Object, T extends void>(S, T) -> void',
+        '<U extends dynamic, V extends Object>(U, V) -> void');
+
+    {
+      String f = '<T extends dynamic>() -> T';
+      String g = '<T extends Object>() -> T';
+      isSubtype(f, g);
+      isSubtype(g, f);
+    }
+
+    {
+      String h = '<T extends List<dynamic>>() -> T';
+      String i = '<T extends List<Object>>() -> T';
+      String j = '<T extends List<void>>() -> T';
+      isSubtype(h, i);
+      isSubtype(h, j);
+      isSubtype(i, h);
+      isSubtype(i, j);
+      isSubtype(j, h);
+      isSubtype(j, i);
+    }
+
+    isNotSubtype('dynamic', '() -> dynamic');
+    isNotSubtype('FutureOr<() -> void>', '() -> void');
+    isSubtype('T & () -> void', '() -> void', typeParameters: 'T');
+    isSubtype('T & () -> void', '() -> dynamic', typeParameters: 'T');
+    isSubtype('T & () -> void', '() -> Object', typeParameters: 'T');
+
+    isSubtype('T & (void) -> void', '(void) -> void', typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(dynamic) -> dynamic',
+        typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(Object) -> Object', typeParameters: 'T');
+
+    isSubtype('T & (void) -> void', '(void) -> void', typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(Iterable<int>) -> dynamic',
+        typeParameters: 'T');
+    isSubtype('T & (void) -> void', '(int) -> Object', typeParameters: 'T');
+
+    isNotSubtype('T & (void) -> void', '(int) -> int', typeParameters: 'T');
+
+    isSubtype('T', '() -> void', typeParameters: 'T extends () -> void');
+    isNotSubtype('T', '() -> void', typeParameters: 'T');
+    isNotSubtype('Typedef<void>', '() -> void');
+    isSubtype('VoidFunction', '() -> void');
+    isNotSubtype(
+        'DefaultTypes<void, void, List<void>, List<void>, int, (int) -> void, () -> int>',
+        '() -> void');
+    isNotSubtype('void', '() -> void');
+
+    isNotSubtype('dynamic', 'T', typeParameters: 'T');
+    isNotSubtype('Iterable<T>', 'T', typeParameters: 'T');
+    isNotSubtype('() -> void', 'T', typeParameters: 'T');
+    isNotSubtype('FutureOr<T>', 'T', typeParameters: 'T');
+    isSubtype('Id<T>', 'T', typeParameters: 'T');
+    isNotSubtype('VoidFunction', 'T', typeParameters: 'T extends () -> void');
+    isNotSubtype('void', 'T', typeParameters: 'T extends void');
+
+    isSubtype('dynamic', 'Id<dynamic>');
+    isNotSubtype('dynamic', 'Id<int>');
+    isSubtype('() -> void', 'Id<() -> void>');
+    isNotSubtype('() -> void', 'Id<() -> int>');
+    isNotSubtype('FutureOr<() -> void>', 'Id<() -> void>');
+    isSubtype('FutureOr<() -> void>', 'Id<FutureOr<() -> void>>');
+    isSubtype('int', 'Id<int>');
+    isSubtype('T & () -> void', 'Id<() -> void>', typeParameters: 'T');
+    isSubtype('T & () -> void', 'Id<() -> dynamic>', typeParameters: 'T');
+    isSubtype('T & () -> void', 'Id<() -> Object>', typeParameters: 'T');
+
+    isSubtype('T & (void) -> void', 'Id<(void) -> void>', typeParameters: 'T');
+    isSubtype('T & (void) -> void', 'Id<(dynamic) -> dynamic>',
+        typeParameters: 'T');
+    isSubtype('T & (void) -> void', 'Id<(Object) -> Object>',
+        typeParameters: 'T');
+
+    isSubtype('T & (void) -> void', 'Id<(void) -> void>', typeParameters: 'T');
+    isSubtype('T & (void) -> void', 'Id<(Iterable<int>) -> dynamic>',
+        typeParameters: 'T');
+    isSubtype('T & (void) -> void', 'Id<(int) -> Object>', typeParameters: 'T');
+
+    isNotSubtype('T & (void) -> void', 'Id<(int) -> int>', typeParameters: 'T');
+
+    isSubtype('T', 'Id<T>', typeParameters: 'T');
+    isSubtype('T', 'Id<Object>', typeParameters: 'T');
+    isNotSubtype('T', 'Id<Comparable<int>>', typeParameters: 'T');
+    isSubtype('T', 'Id<Comparable<int>>',
+        typeParameters: 'T extends Comparable<int>');
+
+    isSubtype('Id<int>', 'Id<int>');
+    isSubtype('Id<int>', 'Id<Object>');
+    isNotSubtype('Id<Object>', 'Id<int>');
+    isSubtype('Id<() -> int>', 'Id<() -> int>');
+    isSubtype('Id<() -> int>', 'Id<() -> Object>');
+    isNotSubtype('Id<() -> Object>', 'Id<() -> int>');
+
+    isSubtype('void', 'Id<void>');
+    isNotSubtype('void', 'Id<Null>');
+
+    // The following function type tests are derived from
+    // ../../../../../tests/compiler/dart2js/model/subtype_test.dart.
+    isSubtype("() -> int", 'Function');
+    isNotSubtype('Function', "() -> int");
+
+    isSubtype("() -> dynamic", "() -> dynamic");
+    isSubtype("() -> dynamic", "() -> void");
+    isSubtype("() -> void", "() -> dynamic");
+
+    isSubtype("() -> int", "() -> void");
+    isNotSubtype("() -> void", "() -> int");
+    isSubtype("() -> void", "() -> void");
+    isSubtype("() -> int", "() -> int");
+    isSubtype("() -> int", "() -> Object");
+    isNotSubtype("() -> int", "() -> double");
+    isNotSubtype("() -> int", "(int) -> void");
+    isNotSubtype("() -> void", "(int) -> int");
+    isNotSubtype("() -> void", "(int) -> void");
+    isSubtype("(int) -> int", "(int) -> int");
+    isSubtype("(Object) -> int", "(int) -> Object");
+    isNotSubtype("(int) -> int", "(double) -> int");
+    isNotSubtype("() -> int", "(int) -> int");
+    isNotSubtype("(int) -> int", "(int, int) -> int");
+    isNotSubtype("(int, int) -> int", "(int) -> int");
+    isNotSubtype("(() -> void) -> void", "((int) -> void) -> void");
+    isNotSubtype("((int) -> void) -> void", "(() -> void) -> void");
+
+    // Optional positional parameters.
+    isSubtype("([int]) -> void", "() -> void");
+    isSubtype("([int]) -> void", "(int) -> void");
+    isNotSubtype("(int) -> void", "([int]) -> void");
+    isSubtype("([int]) -> void", "([int]) -> void");
+    isSubtype("([Object]) -> void", "([int]) -> void");
+    isNotSubtype("([int]) -> void", "([Object]) -> void");
+    isSubtype("(int, [int]) -> void", "(int) -> void");
+    isSubtype("(int, [int]) -> void", "(int, [int]) -> void");
+    isNotSubtype("(int) -> void", "([int]) -> void");
+    isSubtype("([int, int]) -> void", "(int) -> void");
+    isSubtype("([int, int]) -> void", "(int, [int]) -> void");
+    isNotSubtype("([int, int]) -> void", "(int, [int, int]) -> void");
+    isSubtype("([int, int, int]) -> void", "(int, [int, int]) -> void");
+    isNotSubtype("([int]) -> void", "(double) -> void");
+    isNotSubtype("([int]) -> void", "([int, int]) -> void");
+    isSubtype("([int, int]) -> void", "([int]) -> void");
+    isSubtype("([Object, int]) -> void", "([int]) -> void");
+
+    // Optional named parameters.
+    isSubtype("({int a}) -> void", "() -> void");
+    isNotSubtype("({int a}) -> void", "(int) -> void");
+    isNotSubtype("(int) -> void", "({int a}) -> void");
+    isSubtype("({int a}) -> void", "({int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({int b}) -> void");
+    isSubtype("({Object a}) -> void", "({int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({Object a}) -> void");
+    isSubtype("(int, {int a}) -> void", "(int, {int a}) -> void");
+    isNotSubtype("({int a}) -> void", "({double a}) -> void");
+    isNotSubtype("({int a}) -> void", "({int a, int b}) -> void");
+    isSubtype("({int a, int b}) -> void", "({int a}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int a, int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int a, int c}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int b, int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int b, int c}) -> void");
+    isSubtype("({int a, int b, int c}) -> void", "({int c}) -> void");
+    isSubtype("({int c, int b, int a}) -> void", "({int c}) -> void");
   }
 }
diff --git a/pkg/front_end/test/fasta/types/type_parser.dart b/pkg/front_end/test/fasta/types/type_parser.dart
index 906de12..1e72c17 100644
--- a/pkg/front_end/test/fasta/types/type_parser.dart
+++ b/pkg/front_end/test/fasta/types/type_parser.dart
@@ -267,6 +267,8 @@
       ParsedType type;
       if (optional("(") || optional("<")) {
         type = parseFunctionType();
+      } else if (optionalAdvance("void")) {
+        type = new ParsedInterfaceType("void", <ParsedType>[]);
       } else {
         String name = parseName();
         List<ParsedType> arguments = <ParsedType>[];
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 3f75732..682f362 100644
--- a/pkg/front_end/test/incremental_load_from_dill_test.dart
+++ b/pkg/front_end/test/incremental_load_from_dill_test.dart
@@ -25,11 +25,9 @@
 import 'package:front_end/src/fasta/incremental_compiler.dart'
     show IncrementalCompiler;
 
-import 'package:front_end/src/fasta/kernel/utils.dart' show serializeComponent;
-
 import 'package:front_end/src/fasta/severity.dart' show Severity;
 
-import 'package:kernel/kernel.dart' show Component;
+import 'package:kernel/kernel.dart' show Component, Library;
 
 import 'package:kernel/target/targets.dart' show TargetFlags;
 
@@ -44,6 +42,9 @@
 
 import "incremental_utils.dart" as util;
 
+import 'package:front_end/src/fasta/fasta_codes.dart'
+    show DiagnosticMessageFromJson, FormattedMessage;
+
 main([List<String> arguments = const []]) =>
     runMe(arguments, createContext, "../testing.json");
 
@@ -222,7 +223,8 @@
     if (brandNewWorld) {
       sourceFiles = new Map<String, String>.from(world["sources"]);
     } else {
-      sourceFiles.addAll(new Map<String, String>.from(world["sources"]));
+      sourceFiles.addAll(
+          new Map<String, String>.from(world["sources"] ?? <String, String>{}));
     }
     Uri packagesUri;
     for (String filename in sourceFiles.keys) {
@@ -244,17 +246,27 @@
       }
     }
     bool gotError = false;
-    final List<String> formattedErrors = <String>[];
+    final Set<String> formattedErrors = Set<String>();
     bool gotWarning = false;
-    final List<String> formattedWarnings = <String>[];
+    final Set<String> formattedWarnings = Set<String>();
 
     options.onDiagnostic = (DiagnosticMessage message) {
+      String stringId = message.ansiFormatted.join("\n");
+      if (message is FormattedMessage) {
+        stringId = message.toJsonString();
+      } else if (message is DiagnosticMessageFromJson) {
+        stringId = message.toJsonString();
+      }
       if (message.severity == Severity.error) {
         gotError = true;
-        formattedErrors.addAll(message.plainTextFormatted);
+        if (!formattedErrors.add(stringId)) {
+          Expect.fail("Got the same message twice: ${stringId}");
+        }
       } else if (message.severity == Severity.warning) {
         gotWarning = true;
-        formattedWarnings.addAll(message.plainTextFormatted);
+        if (!formattedWarnings.add(stringId)) {
+          Expect.fail("Got the same message twice: ${stringId}");
+        }
       }
     };
 
@@ -284,16 +296,28 @@
         world, gotError, formattedErrors, gotWarning, formattedWarnings);
     util.throwOnEmptyMixinBodies(component);
     print("Compile took ${stopwatch.elapsedMilliseconds} ms");
-    newestWholeComponentData = serializeComponent(component);
+    newestWholeComponentData = util.postProcess(component);
     newestWholeComponent = component;
     print("*****\n\ncomponent:\n${componentToString(component)}\n\n\n");
-    if (component.libraries.length != world["expectedLibraryCount"]) {
-      throw "Expected ${world["expectedLibraryCount"]} libraries, "
-          "got ${component.libraries.length}";
+
+    int nonSyntheticLibraries = countNonSyntheticLibraries(component);
+    int syntheticLibraries = countSyntheticLibraries(component);
+    if (nonSyntheticLibraries != world["expectedLibraryCount"]) {
+      throw "Expected ${world["expectedLibraryCount"]} non-synthetic "
+          "libraries, got ${nonSyntheticLibraries}";
     }
-    if (component.libraries[0].importUri != entry) {
-      throw "Expected the first library to have uri $entry but was "
-          "${component.libraries[0].importUri}";
+    if (world["expectedSyntheticLibraryCount"] != null) {
+      if (syntheticLibraries != world["expectedSyntheticLibraryCount"]) {
+        throw "Expected ${world["expectedSyntheticLibraryCount"]} synthetic "
+            "libraries, got ${syntheticLibraries}";
+      }
+    }
+    List<Library> entryLib = component.libraries
+        .where((Library lib) => lib.importUri == entry || lib.fileUri == entry)
+        .toList();
+    if (entryLib.length != 1) {
+      throw "Expected the entry to become a library. Got ${entryLib.length} "
+          "libraries for it.";
     }
     if (compiler.initializedFromDill != expectInitializeFromDill) {
       throw "Expected that initializedFromDill would be "
@@ -317,6 +341,8 @@
     }
 
     {
+      Set<String> prevFormattedErrors = formattedErrors.toSet();
+      Set<String> prevFormattedWarnings = formattedWarnings.toSet();
       gotError = false;
       formattedErrors.clear();
       gotWarning = false;
@@ -324,19 +350,58 @@
       Component component2 = await compiler.computeDelta(fullComponent: true);
       performErrorAndWarningCheck(
           world, gotError, formattedErrors, gotWarning, formattedWarnings);
-      List<int> thisWholeComponent = serializeComponent(component2);
+      List<int> thisWholeComponent = util.postProcess(component2);
       print("*****\n\ncomponent2:\n${componentToString(component2)}\n\n\n");
       checkIsEqual(newestWholeComponentData, thisWholeComponent);
+      if (prevFormattedErrors.length != formattedErrors.length) {
+        Expect.fail("Previously had ${prevFormattedErrors.length} errors, "
+            "now had ${formattedErrors.length}.\n\n"
+            "Before:\n"
+            "${prevFormattedErrors.join("\n")}"
+            "\n\n"
+            "Now:\n"
+            "${formattedErrors.join("\n")}");
+      }
+      if ((prevFormattedErrors.toSet()..removeAll(formattedErrors))
+          .isNotEmpty) {
+        Expect.fail("Previously got error messages $prevFormattedErrors, "
+            "now had ${formattedErrors}.");
+      }
+      if (prevFormattedWarnings.length != formattedWarnings.length) {
+        Expect.fail("Previously had ${prevFormattedWarnings.length} errors, "
+            "now had ${formattedWarnings.length}.");
+      }
+      if ((prevFormattedWarnings.toSet()..removeAll(formattedWarnings))
+          .isNotEmpty) {
+        Expect.fail("Previously got error messages $prevFormattedWarnings, "
+            "now had ${formattedWarnings}.");
+      }
     }
   }
 }
 
+int countNonSyntheticLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (!lib.isSynthetic) result++;
+  }
+  return result;
+}
+
+int countSyntheticLibraries(Component c) {
+  int result = 0;
+  for (Library lib in c.libraries) {
+    if (lib.isSynthetic) result++;
+  }
+  return result;
+}
+
 void performErrorAndWarningCheck(
     YamlMap world,
     bool gotError,
-    List<String> formattedErrors,
+    Set<String> formattedErrors,
     bool gotWarning,
-    List<String> formattedWarnings) {
+    Set<String> formattedWarnings) {
   if (world["errors"] == true && !gotError) {
     throw "Expected error, but didn't get any.";
   } else if (world["errors"] != true && gotError) {
@@ -466,21 +531,23 @@
 
   /// Filter out the automatically added entryPoint, unless it's explicitly
   /// specified as being invalidated.
+  /// Also filter out uris with "nonexisting.dart" in the name as synthetic
+  /// libraries are invalidated automatically too.
   /// This is not perfect, but works for what it's currently used for.
   Set<Uri> getFilteredInvalidatedImportUrisForTesting(
       List<Uri> invalidatedUris) {
     if (invalidatedImportUrisForTesting == null) return null;
+
     Set<String> invalidatedFilenames =
         invalidatedUris.map((uri) => uri.pathSegments.last).toSet();
-    if (invalidatedFilenames.contains(entryPoint.pathSegments.last)) {
-      return invalidatedImportUrisForTesting;
-    }
-
     Set<Uri> result = new Set<Uri>();
     for (Uri uri in invalidatedImportUrisForTesting) {
-      if (invalidatedFilenames.contains(uri.pathSegments.last)) result.add(uri);
+      if (uri.pathSegments.last == "nonexisting.dart") continue;
+      if (invalidatedFilenames.contains(entryPoint.pathSegments.last) ||
+          invalidatedFilenames.contains(uri.pathSegments.last)) result.add(uri);
     }
-    return result;
+
+    return result.isEmpty ? null : result;
   }
 
   TestIncrementalCompiler(CompilerOptions options, this.entryPoint,
diff --git a/pkg/front_end/test/messages_json_test.dart b/pkg/front_end/test/messages_json_test.dart
new file mode 100644
index 0000000..0756f80
--- /dev/null
+++ b/pkg/front_end/test/messages_json_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:front_end/src/api_prototype/diagnostic_message.dart'
+    show DiagnosticMessage, getMessageUri;
+
+import 'package:front_end/src/fasta/fasta_codes.dart'
+    show DiagnosticMessageFromJson, FormattedMessage, LocatedMessage;
+
+import 'package:front_end/src/fasta/severity.dart' show Severity;
+
+/// Test that turning a message into json and back again retains the wanted
+/// information.
+main() {
+  for (int i = 0; i < Severity.values.length; i++) {
+    Severity severity = Severity.values[i];
+    LocatedMessage locatedMessage1 =
+        new LocatedMessage(Uri.parse("what:ever/fun_1.dart"), 117, 2, null);
+    FormattedMessage formattedMessage2 = new FormattedMessage(
+        null, "Formatted string #2", 13, 2, Severity.error, []);
+    FormattedMessage formattedMessage3 = new FormattedMessage(
+        null, "Formatted string #3", 313, 32, Severity.error, []);
+
+    FormattedMessage formattedMessage1 = new FormattedMessage(
+        locatedMessage1,
+        "Formatted string",
+        42,
+        86,
+        severity,
+        [formattedMessage2, formattedMessage3]);
+
+    DiagnosticMessageFromJson diagnosticMessageFromJson =
+        new DiagnosticMessageFromJson.fromJson(
+            formattedMessage1.toJsonString());
+    compareMessages(formattedMessage1, diagnosticMessageFromJson);
+
+    DiagnosticMessageFromJson diagnosticMessageFromJson2 =
+        new DiagnosticMessageFromJson.fromJson(
+            diagnosticMessageFromJson.toJsonString());
+    compareMessages(diagnosticMessageFromJson, diagnosticMessageFromJson2);
+
+    expect(diagnosticMessageFromJson2.toJsonString(),
+        formattedMessage1.toJsonString());
+  }
+}
+
+void compareMessages(DiagnosticMessage a, DiagnosticMessage b) {
+  List<String> list1 = a.ansiFormatted.toList();
+  List<String> list2 = b.ansiFormatted.toList();
+  expect(list1.length, list2.length);
+  for (int i = 0; i < list1.length; i++) {
+    expect(list1[i], list2[i]);
+  }
+
+  list1 = a.plainTextFormatted.toList();
+  list2 = b.plainTextFormatted.toList();
+  expect(list1.length, list2.length);
+  for (int i = 0; i < list1.length; i++) {
+    expect(list1[i], list2[i]);
+  }
+
+  expect(a.severity, b.severity);
+  expect(getMessageUri(a), getMessageUri(b));
+}
+
+void expect(Object actual, Object expect) {
+  if (expect != actual) throw "Expected $expect got $actual";
+}
diff --git a/pkg/front_end/test/precedence_info_test.dart b/pkg/front_end/test/precedence_info_test.dart
index e8fc1eb..169f67c 100644
--- a/pkg/front_end/test/precedence_info_test.dart
+++ b/pkg/front_end/test/precedence_info_test.dart
@@ -28,7 +28,7 @@
     }
 
     for (TokenType type in TokenType.all) {
-      assertLexeme(type.value);
+      assertLexeme(type.lexeme);
     }
     assertLexeme('1.0'); // DOUBLE
     assertLexeme('0xA'); // HEXADECIMAL
diff --git a/pkg/front_end/test/severity_index_test.dart b/pkg/front_end/test/severity_index_test.dart
new file mode 100644
index 0000000..3070f73
--- /dev/null
+++ b/pkg/front_end/test/severity_index_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:front_end/src/fasta/severity.dart' show Severity;
+
+/// Test that Severity has the expected indexes. Note that this is important
+/// and shouldn't be changed lightly because we use it in serialization!
+main() {
+  expect(Severity.context.index, 0);
+  expect(Severity.error.index, 1);
+  expect(Severity.internalProblem.index, 4);
+  expect(Severity.warning.index, 5);
+
+  expect(Severity.values[0], Severity.context);
+  expect(Severity.values[1], Severity.error);
+  expect(Severity.values[4], Severity.internalProblem);
+  expect(Severity.values[5], Severity.warning);
+}
+
+void expect(Object actual, Object expect) {
+  if (expect != actual) throw "Expected $expect got $actual";
+}
diff --git a/pkg/front_end/testcases/expression/regress_34224.expression.yaml b/pkg/front_end/testcases/expression/regress_34224.expression.yaml
new file mode 100644
index 0000000..a399aaf
--- /dev/null
+++ b/pkg/front_end/testcases/expression/regress_34224.expression.yaml
@@ -0,0 +1,9 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+entry_point: "main.dart"
+definitions: []
+position: "dart:core#Object"
+expression: |
+  toString()
\ No newline at end of file
diff --git a/pkg/front_end/testcases/expression/regress_34224.expression.yaml.expect b/pkg/front_end/testcases/expression/regress_34224.expression.yaml.expect
new file mode 100644
index 0000000..d107580
--- /dev/null
+++ b/pkg/front_end/testcases/expression/regress_34224.expression.yaml.expect
@@ -0,0 +1,4 @@
+Errors: {
+}
+method /* from org-dartlang-debug:synthetic_debug_expression */ debugExpr() → dynamic
+  return this.{dart.core::Object::toString}();
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml
new file mode 100644
index 0000000..5bd270e
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main.yaml
@@ -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.md file.
+
+# When the entry is not given as a package-url, but is intepreted as one
+# (Interpreting this as package URI, 'package:untitled/main.dart'.) the library
+# should still be included in the output.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+        }
+      .packages: untitled:/
+    expectedLibraryCount: 1
+    errors: false
+    warnings: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml
new file mode 100644
index 0000000..2360641
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_main_with_errors.yaml
@@ -0,0 +1,21 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# When the entry is not given as a package-url, but is intepreted as one
+# (Interpreting this as package URI, 'package:untitled/main.dart'.) the library
+# should still be included in the output - even if there's errors in main.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        main() {
+          asdf;
+        }
+      .packages: untitled:/
+    expectedLibraryCount: 1
+    errors: true
+    warnings: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml
new file mode 100644
index 0000000..02a57de
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/entry_not_package_url_no_main.yaml
@@ -0,0 +1,19 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# When the entry is not given as a package-url, but is intepreted as one
+# (Interpreting this as package URI, 'package:untitled/main.dart'.) the library
+# should still be included in the output - even if there's no main.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        notMain() {}
+      .packages: untitled:/
+    expectedLibraryCount: 1
+    errors: false
+    warnings: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml
new file mode 100644
index 0000000..e571850
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/mixin_inferrer_error.yaml
@@ -0,0 +1,18 @@
+# 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.md file.
+
+# Test that errors issued by the hierarchy mixinInferrer are in fact reported,
+# and now swallowed somewhere when done in the incremental compiler.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        abstract class A<T> {}
+        mixin M<T> on A<T> {}
+        class C extends Object with M {}
+    expectedLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml
new file mode 100644
index 0000000..0be7810
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_1.yaml
@@ -0,0 +1,56 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.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:
+      main.dart: |
+        import "b.dart";
+      b.dart: |
+        asdf
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    expectedLibraryCount: 2
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+      b.dart: |
+        asdf
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - b.dart
+    sources:
+      b.dart: |
+        asdf;
+    expectedLibraryCount: 2
+  - entry: main.dart
+    errors: false
+    worldType: updated
+    invalidate:
+      - b.dart
+    sources:
+      b.dart: |
+        asdf() {}
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml
new file mode 100644
index 0000000..468566d
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_2.yaml
@@ -0,0 +1,66 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# 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:
+      main.dart: |
+        import "b.dart";
+
+        class A extends B {}
+      b.dart: |
+        import "nonexisting.dart";
+
+        class B extends A {}
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    expectedLibraryCount: 2
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+
+        class A extends B {}
+      b.dart: |
+        import "nonexisting.dart";
+
+        class B extends A {}
+    expectedLibraryCount: 2
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 2
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - b.dart
+    sources:
+      b.dart: |
+        import "main.dart";
+
+        class B extends A {}
+    expectedLibraryCount: 2
+  - entry: main.dart
+    errors: false
+    worldType: updated
+    invalidate:
+      - b.dart
+    sources:
+      b.dart: |
+        class B extends Object {}
+    expectedLibraryCount: 2
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml
new file mode 100644
index 0000000..5375fd6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_3.yaml
@@ -0,0 +1,65 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# 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";
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        class Foo<T> {}
+        class Bar<T> extends Foo<T> {}
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+
+        class Baz extends Bar<int> implements Foo<String> {}
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    expectedLibraryCount: 3
+  - entry: main.dart
+    sources:
+      .packages: mypackage:mypackage
+      main.dart: |
+        import "package:mypackage/a.dart";
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        class Foo<T> {}
+        class Bar<T> extends Foo<T> {}
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+
+        class Baz extends Bar<int> implements Foo<String> {}
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 3
+  - entry: main.dart
+    errors: false
+    worldType: updated
+    invalidate:
+      - mypackage/b.dart
+    sources:
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+
+        class Baz extends Bar<int> {}
+    expectedLibraryCount: 3
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml
new file mode 100644
index 0000000..994f2c6
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/reissue_errors_4.yaml
@@ -0,0 +1,74 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.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";
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        class Foo<T> {}
+        class Bar<T> extends Foo<T> {}
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+        part "package:mypackage/c.dart";
+      mypackage/c.dart: |
+        part of "package:mypackage/b.dart";
+
+        class Baz extends Bar<int> implements Foo<String> {}
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    expectInitializeFromDill: false
+    expectedLibraryCount: 3
+  - entry: main.dart
+    sources:
+      .packages: mypackage:mypackage
+      main.dart: |
+        import "package:mypackage/a.dart";
+      mypackage/a.dart: |
+        import "package:mypackage/b.dart";
+
+        class Foo<T> {}
+        class Bar<T> extends Foo<T> {}
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+        part "package:mypackage/c.dart";
+      mypackage/c.dart: |
+        part of "package:mypackage/b.dart";
+
+        class Baz extends Bar<int> implements Foo<String> {}
+    expectedLibraryCount: 3
+    errors: true
+  - entry: main.dart
+    errors: true
+    worldType: updated
+    invalidate:
+      - main.dart
+    expectedLibraryCount: 3
+  - entry: main.dart
+    errors: false
+    worldType: updated
+    invalidate:
+      - mypackage/c.dart
+    sources:
+      mypackage/b.dart: |
+        import "package:mypackage/a.dart";
+        part "package:mypackage/c.dart";
+      mypackage/c.dart: |
+        part of "package:mypackage/b.dart";
+
+        class Baz extends Bar<int> {}
+    expectedLibraryCount: 3
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml
new file mode 100644
index 0000000..14b0a58
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_1.yaml
@@ -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.md file.
+
+# Compile an application that includes a non-existing file.
+# Make sure the output includes a synthetic library.
+# Loading from such a dill is ok too.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+      b.dart: |
+        import "nonexisting.dart";
+    expectedLibraryCount: 2
+    expectedSyntheticLibraryCount: 1
+    errors: true
+  - entry: main.dart
+    invalidate:
+      - main.dart
+    sources:
+      main.dart: |
+        import "b.dart";
+      b.dart: |
+        import "nonexisting.dart";
+    expectedLibraryCount: 2
+    expectedSyntheticLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml
new file mode 100644
index 0000000..bbcc110
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_2.yaml
@@ -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.md file.
+
+# Compile an application that includes a non-existing file from dart:.
+# Make sure the output includes a synthetic library.
+# Loading from such a dill is ok too.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "dart:foo/nonexisting.dart";
+    expectedLibraryCount: 1
+    expectedSyntheticLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml
new file mode 100644
index 0000000..0402343
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_3.yaml
@@ -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.md file.
+
+# Compile an application that includes a non-existing file from dart: as a part.
+# Make sure the output includes a synthetic library.
+# Loading from such a dill is ok too.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        part "dart:foo/nonexisting.dart";
+    expectedLibraryCount: 1
+    expectedSyntheticLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml
new file mode 100644
index 0000000..df8a598
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_4.yaml
@@ -0,0 +1,19 @@
+# Copyright (c) 2019, the Dart project authors. Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE.md file.
+
+# Compile an application that includes a non-existing file
+# from package: as a part.
+# Make sure the output includes a synthetic library.
+# Loading from such a dill is ok too.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        part "package:foo/nonexisting.dart";
+    expectedLibraryCount: 1
+    expectedSyntheticLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml
new file mode 100644
index 0000000..bd55d81
--- /dev/null
+++ b/pkg/front_end/testcases/incremental_initialize_from_dill/working_with_synthetic_libraries_5.yaml
@@ -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.md file.
+
+# Compile an application that includes a non-existing file from package:.
+# Make sure the output includes a synthetic library.
+# Loading from such a dill is ok too.
+
+type: newworld
+strong: true
+worlds:
+  - entry: main.dart
+    sources:
+      main.dart: |
+        import "package:foo/nonexisting.dart";
+    expectedLibraryCount: 1
+    expectedSyntheticLibraryCount: 1
+    errors: true
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.hierarchy.expect
index 86c098f..06b9b49 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.hierarchy.expect
@@ -82,11 +82,11 @@
     Object.==
   interfaceSetters:
 
-M1 with M0:
+M1 with M0<int, String>:
   superclasses:
     Object
       -> M1
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, String>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -117,7 +117,7 @@
     Object
       -> M1
         -> _A&M1&M0
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, String>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect
index ad7e505..2fa7bf9 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::String> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect
index d6d20e8..2aeb31d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.legacy.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int, core::String> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
index 153cf0f..2af7824 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart.outline.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_1.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -27,7 +14,7 @@
   synthetic constructor •() → self::M1
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::String> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.hierarchy.expect
index 86c098f..3f48b79 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.hierarchy.expect
@@ -82,11 +82,11 @@
     Object.==
   interfaceSetters:
 
-M1 with M0:
+M1 with M0<int, int>:
   superclasses:
     Object
       -> M1
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -117,7 +117,7 @@
     Object
       -> M1
         -> _A&M1&M0
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, int>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect
index 2bf8871..db552ee 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::int> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect
index 95a03e7..6459244 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.legacy.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int, core::int> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
index aa64264..f91df74 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart.outline.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_2.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -27,7 +14,7 @@
   synthetic constructor •() → self::M1
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::int> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.hierarchy.expect
index 86c098f..7daaa837 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.hierarchy.expect
@@ -82,11 +82,11 @@
     Object.==
   interfaceSetters:
 
-M1 with M0:
+M1 with M0<int, Comparable<dynamic>>:
   superclasses:
     Object
       -> M1
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, Comparable<dynamic>>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -117,7 +117,7 @@
     Object
       -> M1
         -> _A&M1&M0
-  interfaces: I<int>, M0
+  interfaces: I<int>, M0<int, Comparable<dynamic>>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect
index 4b75804..7c6712b 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::Comparable<dynamic>> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect
index 9669075..47f9f64 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.legacy.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super core::Object::•()
     ;
 }
-abstract class _A&M1&M0 extends self::M1 implements self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 extends self::M1 implements self::M0<core::int, core::Comparable<dynamic>> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
index e967a16..5e19f97 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart.outline.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'M1 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart:13:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_instantiate_to_bounds_3.dart'.
-// class A extends M1 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -27,7 +14,7 @@
   synthetic constructor •() → self::M1
     ;
 }
-abstract class _A&M1&M0 = self::M1 with self::M0<dynamic, dynamic> {
+abstract class _A&M1&M0 = self::M1 with self::M0<core::int, core::Comparable<dynamic>> {
   synthetic constructor •() → self::_A&M1&M0
     : super self::M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.hierarchy.expect
index d6e962c..eebc3a2 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.hierarchy.expect
@@ -172,12 +172,12 @@
     Object.==
   interfaceSetters:
 
-M2 with M0:
+M2 with M0<int, double>:
   superclasses:
     Object
       -> M1
         -> M2
-  interfaces: I<int>, J<double>, M0, _M0&I&J<X, Y>
+  interfaces: I<int>, J<double>, M0<int, double>, _M0&I&J<int, double>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -209,7 +209,7 @@
       -> M1
         -> M2
           -> _A&M2&M0
-  interfaces: I<int>, J<double>, M0, _M0&I&J<X, Y>
+  interfaces: I<int>, J<double>, M0<int, double>, _M0&I&J<int, double>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect
index 3cc474f..9fe7a0a 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -55,7 +32,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 = self::M2 with self::M0<dynamic, dynamic> {
+abstract class _A&M2&M0 = self::M2 with self::M0<core::int, core::double> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect
index 435c5eb..435ce3b 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.legacy.transformed.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -55,7 +32,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 extends self::M2 implements self::M0<dynamic, dynamic> {
+abstract class _A&M2&M0 extends self::M2 implements self::M0<core::int, core::double> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
index d7d23fd..da0d2c6 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart.outline.expect
@@ -1,26 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'M2 with M0' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart:16:7: Error: 'A' can't implement both 'J<double>' and 'J<dynamic>'
-//  - 'J' is from 'pkg/front_end/testcases/inference/mixin_inference_multiple_constraints.dart'.
-// class A extends M2 with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -50,7 +27,7 @@
   synthetic constructor •() → self::M2
     ;
 }
-abstract class _A&M2&M0 = self::M2 with self::M0<dynamic, dynamic> {
+abstract class _A&M2&M0 = self::M2 with self::M0<core::int, core::double> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.hierarchy.expect
index 04cc994..5e81312 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.hierarchy.expect
@@ -74,7 +74,7 @@
 M2:
   superclasses:
     Object
-      -> I<List<T>>
+      -> I<List<Map<T, T>>>
         -> M1<Map<T, T>>
   interfaces:
   classMembers:
@@ -90,13 +90,13 @@
     Object.==
   classSetters:
 
-M2<int> with M0:
+M2<int> with M0<Map<int, int>>:
   superclasses:
     Object
-      -> I<List<T>>
-        -> M1<Map<T, T>>
+      -> I<List<Map<int, int>>>
+        -> M1<Map<int, int>>
           -> M2<int>
-  interfaces: M0
+  interfaces: M0<Map<int, int>>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -125,11 +125,11 @@
 A:
   superclasses:
     Object
-      -> I<List<T>>
-        -> M1<Map<T, T>>
+      -> I<List<Map<int, int>>>
+        -> M1<Map<int, int>>
           -> M2<int>
             -> _A&M2&M0
-  interfaces: M0
+  interfaces: M0<Map<int, int>>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect
index 9c7c097..1030f6b 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.expect
@@ -1,20 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'M2 with M0' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'A' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -39,7 +22,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 = self::M2<core::int> with self::M0<dynamic> {
+abstract class _A&M2&M0 = self::M2<core::int> with self::M0<core::Map<core::int, core::int>> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect
index 25112ed..3eabc8f 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.legacy.transformed.expect
@@ -1,20 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'M2 with M0' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'A' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -39,7 +22,7 @@
     : super self::M1::•()
     ;
 }
-abstract class _A&M2&M0 extends self::M2<core::int> implements self::M0<dynamic> {
+abstract class _A&M2&M0 extends self::M2<core::int> implements self::M0<core::Map<core::int, core::int>> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
index 07edfca..75b4f9d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart.outline.expect
@@ -1,20 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'M2 with M0' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart:14:7: Error: 'A' can't implement both 'I<List<Map<int, int>>>' and 'I<List<dynamic>>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_non_trivial_constraints.dart'.
-//  - 'List' is from 'dart:core'.
-//  - 'Map' is from 'dart:core'.
-// class A extends M2<int> with M0 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -35,7 +18,7 @@
   synthetic constructor •() → self::M2<self::M2::T>
     ;
 }
-abstract class _A&M2&M0 = self::M2<core::int> with self::M0<dynamic> {
+abstract class _A&M2&M0 = self::M2<core::int> with self::M0<core::Map<core::int, core::int>> {
   synthetic constructor •() → self::_A&M2&M0
     : super self::M2::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.hierarchy.expect
index 115669f..992d270 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.hierarchy.expect
@@ -71,12 +71,12 @@
     Object.==
   classSetters:
 
-M0<int> with M1:
+M0<int> with M1<int>:
   superclasses:
     Object
-      -> I<T>
+      -> I<int>
         -> M0<int>
-  interfaces: M1
+  interfaces: M1<int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -105,10 +105,10 @@
 A:
   superclasses:
     Object
-      -> I<T>
+      -> I<int>
         -> M0<int>
           -> _A&M0&M1
-  interfaces: M1
+  interfaces: M1<int>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect
index f6ebbf5..b336c68 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int> with self::M1<dynamic> {
+abstract class _A&M0&M1 = self::M0<core::int> with self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect
index 79b10e7..75ebf9d 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.legacy.transformed.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -30,7 +17,7 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 extends self::M0<core::int> implements self::M1<dynamic> {
+abstract class _A&M0&M1 extends self::M0<core::int> implements self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
index fcde3b5..641b87b 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart.outline.expect
@@ -1,16 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart:12:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_1.dart'.
-// class A extends M0<int> with M1 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -27,7 +14,7 @@
   synthetic constructor •() → self::M1<self::M1::T>
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int> with self::M1<dynamic> {
+abstract class _A&M0&M1 = self::M0<core::int> with self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.hierarchy.expect
index 9e34fc0..2113b02 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.hierarchy.expect
@@ -89,12 +89,12 @@
     Object.==
   classSetters:
 
-M0<int> with M1:
+M0<int> with M1<int>:
   superclasses:
     Object
-      -> I<T>
+      -> I<int>
         -> M0<int>
-  interfaces: M1
+  interfaces: M1<int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -120,13 +120,13 @@
     Object.==
   interfaceSetters:
 
-_A&M0&M1 with M2:
+_A&M0&M1 with M2<int>:
   superclasses:
     Object
-      -> I<T>
+      -> I<int>
         -> M0<int>
           -> _A&M0&M1
-  interfaces: M1, M2
+  interfaces: M1<int>, M2<int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -155,11 +155,11 @@
 A:
   superclasses:
     Object
-      -> I<T>
+      -> I<int>
         -> M0<int>
           -> _A&M0&M1
             -> _A&M0&M1&M2
-  interfaces: M1, M2
+  interfaces: M1<int>, M2<int>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect
index 3afefb6..d133391 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.expect
@@ -1,21 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1, M2' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -40,12 +22,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int> with self::M1<dynamic> {
+abstract class _A&M0&M1 = self::M0<core::int> with self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<dynamic> {
+abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int> {
   synthetic constructor •() → self::_A&M0&M1&M2
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect
index 19803cd..d4edaee 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.legacy.transformed.expect
@@ -1,21 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1, M2' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -40,12 +22,12 @@
     : super self::I::•()
     ;
 }
-abstract class _A&M0&M1 extends self::M0<core::int> implements self::M1<dynamic> {
+abstract class _A&M0&M1 extends self::M0<core::int> implements self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 extends self::_A&M0&M1 implements self::M2<dynamic> {
+abstract class _A&M0&M1&M2 extends self::_A&M0&M1 implements self::M2<core::int> {
   synthetic constructor •() → self::_A&M0&M1&M2
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
index 2f5c367..7456cbf 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart.outline.expect
@@ -1,21 +1,3 @@
-//
-// Problems in component:
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'M0 with M1, M2' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
-// pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart:15:7: Error: 'A' can't implement both 'I<int>' and 'I<dynamic>'
-//  - 'I' is from 'pkg/front_end/testcases/inference/mixin_inference_outwards_2.dart'.
-// class A extends M0<int> with M1, M2 {}
-//       ^
-//
 library;
 import self as self;
 import "dart:core" as core;
@@ -36,12 +18,12 @@
   synthetic constructor •() → self::M2<self::M2::T>
     ;
 }
-abstract class _A&M0&M1 = self::M0<core::int> with self::M1<dynamic> {
+abstract class _A&M0&M1 = self::M0<core::int> with self::M1<core::int> {
   synthetic constructor •() → self::_A&M0&M1
     : super self::M0::•()
     ;
 }
-abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<dynamic> {
+abstract class _A&M0&M1&M2 = self::_A&M0&M1 with self::M2<core::int> {
   synthetic constructor •() → self::_A&M0&M1&M2
     : super self::_A&M0&M1::•()
     ;
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.hierarchy.expect
index 7f0efb6..45aa225 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_3.dart.hierarchy.expect
@@ -82,10 +82,10 @@
     Object.==
   classSetters:
 
-Object with M0:
+Object with M0<dynamic>:
   superclasses:
     Object
-  interfaces: M0, I<T>
+  interfaces: M0<dynamic>, I<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -115,7 +115,7 @@
   superclasses:
     Object
       -> _A&Object&M0
-  interfaces: M0, I<T>, M1<int>
+  interfaces: M0<dynamic>, I<dynamic>, M1<int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -146,7 +146,7 @@
     Object
       -> _A&Object&M0
         -> _A&Object&M0&M1
-  interfaces: M0, I<T>, M1<int>
+  interfaces: M0<dynamic>, I<dynamic>, M1<int>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.hierarchy.expect
index 64729ae..1d1e2f0 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_outwards_4.dart.hierarchy.expect
@@ -82,10 +82,10 @@
     Object.==
   classSetters:
 
-Object with M0:
+Object with M0<dynamic>:
   superclasses:
     Object
-  interfaces: M0, I<T>
+  interfaces: M0<dynamic>, I<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -111,11 +111,11 @@
     Object.==
   interfaceSetters:
 
-_A&Object&M0 with M1:
+_A&Object&M0 with M1<dynamic>:
   superclasses:
     Object
       -> _A&Object&M0
-  interfaces: M0, I<T>, M1
+  interfaces: M0<dynamic>, I<dynamic>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -146,7 +146,7 @@
     Object
       -> _A&Object&M0
         -> _A&Object&M0&M1
-  interfaces: M0, I<T>, M1
+  interfaces: M0<dynamic>, I<dynamic>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.hierarchy.expect
index 3e0a432..9e4e1b8 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_1.dart.hierarchy.expect
@@ -93,10 +93,10 @@
     Object.==
   interfaceSetters:
 
-Object with M0:
+Object with M0<dynamic>:
   superclasses:
     Object
-  interfaces: M0, I<T, int>
+  interfaces: M0<dynamic>, I<dynamic, int>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -122,11 +122,11 @@
     Object.==
   interfaceSetters:
 
-_A&Object&M0 with M1:
+_A&Object&M0 with M1<dynamic>:
   superclasses:
     Object
       -> _A&Object&M0
-  interfaces: M0, I<T, int>, M1
+  interfaces: M0<dynamic>, I<dynamic, int>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -157,7 +157,7 @@
     Object
       -> _A&Object&M0
         -> _A&Object&M0&M1
-  interfaces: M0, I<T, int>, M1
+  interfaces: M0<dynamic>, I<dynamic, int>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.hierarchy.expect b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.hierarchy.expect
index f5f0895..e8cc39f 100644
--- a/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/inference/mixin_inference_unification_2.dart.hierarchy.expect
@@ -93,10 +93,10 @@
     Object.==
   interfaceSetters:
 
-Object with M0:
+Object with M0<dynamic>:
   superclasses:
     Object
-  interfaces: M0, I<T, List<T>>
+  interfaces: M0<dynamic>, I<dynamic, List<dynamic>>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -122,11 +122,11 @@
     Object.==
   interfaceSetters:
 
-_A&Object&M0 with M1:
+_A&Object&M0 with M1<dynamic>:
   superclasses:
     Object
       -> _A&Object&M0
-  interfaces: M0, I<T, List<T>>, M1
+  interfaces: M0<dynamic>, I<dynamic, List<dynamic>>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
@@ -157,7 +157,7 @@
     Object
       -> _A&Object&M0
         -> _A&Object&M0&M1
-  interfaces: M0, I<T, List<T>>, M1
+  interfaces: M0<dynamic>, I<dynamic, List<dynamic>>, M1<dynamic>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/issue34515.dart b/pkg/front_end/testcases/issue34515.dart
new file mode 100644
index 0000000..829ce3b
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.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.
+
+import "issue34515_lib1.dart";
+import "issue34515_lib2.dart";
+
+void test() {
+  ImportedClass(1);
+  ImportedClass("a");
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/issue34515.dart.hierarchy.expect b/pkg/front_end/testcases/issue34515.dart.hierarchy.expect
new file mode 100644
index 0000000..32f2c5e
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.hierarchy.expect
@@ -0,0 +1,53 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+ImportedClass:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+ImportedClass:
+  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/issue34515.dart.legacy.expect b/pkg/front_end/testcases/issue34515.dart.legacy.expect
new file mode 100644
index 0000000..528e442
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.legacy.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue34515.dart:9:3: Warning: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass(1);
+//   ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/issue34515.dart:10:3: Warning: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass("a");
+//   ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue34515_lib1.dart";
+import "org-dartlang-testcase:///issue34515_lib2.dart";
+
+static method test() → void {
+  let final core::Object #t1 = 1 in invalid-expression "pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(1);
+  ^^^^^^^^^^^^^";
+  let final core::Object #t2 = "a" in invalid-expression "pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(\"a\");
+  ^^^^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::int a) → self2::ImportedClass
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as self3;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::String a) → self3::ImportedClass
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/issue34515.dart.legacy.transformed.expect b/pkg/front_end/testcases/issue34515.dart.legacy.transformed.expect
new file mode 100644
index 0000000..528e442
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.legacy.transformed.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue34515.dart:9:3: Warning: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass(1);
+//   ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/issue34515.dart:10:3: Warning: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass("a");
+//   ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue34515_lib1.dart";
+import "org-dartlang-testcase:///issue34515_lib2.dart";
+
+static method test() → void {
+  let final core::Object #t1 = 1 in invalid-expression "pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(1);
+  ^^^^^^^^^^^^^";
+  let final core::Object #t2 = "a" in invalid-expression "pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(\"a\");
+  ^^^^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::int a) → self2::ImportedClass
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as self3;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::String a) → self3::ImportedClass
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/issue34515.dart.outline.expect b/pkg/front_end/testcases/issue34515.dart.outline.expect
new file mode 100644
index 0000000..1c038cb
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.outline.expect
@@ -0,0 +1,28 @@
+library;
+import self as self;
+
+import "org-dartlang-testcase:///issue34515_lib1.dart";
+import "org-dartlang-testcase:///issue34515_lib2.dart";
+
+static method test() → void
+  ;
+static method main() → dynamic
+  ;
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::int a) → self2::ImportedClass
+    ;
+}
+
+library;
+import self as self3;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::String a) → self3::ImportedClass
+    ;
+}
diff --git a/pkg/front_end/testcases/issue34515.dart.strong.expect b/pkg/front_end/testcases/issue34515.dart.strong.expect
new file mode 100644
index 0000000..d8a23b4
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.strong.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass(1);
+//   ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass("a");
+//   ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue34515_lib1.dart";
+import "org-dartlang-testcase:///issue34515_lib2.dart";
+
+static method test() → void {
+  let final core::Object #t1 = 1 in invalid-expression "pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(1);
+  ^^^^^^^^^^^^^";
+  let final core::Object #t2 = "a" in invalid-expression "pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(\"a\");
+  ^^^^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::int a) → self2::ImportedClass
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as self3;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::String a) → self3::ImportedClass
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/issue34515.dart.strong.transformed.expect b/pkg/front_end/testcases/issue34515.dart.strong.transformed.expect
new file mode 100644
index 0000000..d8a23b4
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515.dart.strong.transformed.expect
@@ -0,0 +1,47 @@
+library;
+//
+// Problems in library:
+//
+// pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass(1);
+//   ^^^^^^^^^^^^^
+//
+// pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+//   ImportedClass("a");
+//   ^^^^^^^^^^^^^
+//
+import self as self;
+import "dart:core" as core;
+
+import "org-dartlang-testcase:///issue34515_lib1.dart";
+import "org-dartlang-testcase:///issue34515_lib2.dart";
+
+static method test() → void {
+  let final core::Object #t1 = 1 in invalid-expression "pkg/front_end/testcases/issue34515.dart:9:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(1);
+  ^^^^^^^^^^^^^";
+  let final core::Object #t2 = "a" in invalid-expression "pkg/front_end/testcases/issue34515.dart:10:3: Error: 'ImportedClass' is imported from both 'pkg/front_end/testcases/issue34515_lib1.dart' and 'pkg/front_end/testcases/issue34515_lib2.dart'.
+  ImportedClass(\"a\");
+  ^^^^^^^^^^^^^";
+}
+static method main() → dynamic {}
+
+library;
+import self as self2;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::int a) → self2::ImportedClass
+    : super core::Object::•()
+    ;
+}
+
+library;
+import self as self3;
+import "dart:core" as core;
+
+class ImportedClass extends core::Object {
+  constructor •(core::String a) → self3::ImportedClass
+    : super core::Object::•()
+    ;
+}
diff --git a/pkg/front_end/testcases/issue34515_lib1.dart b/pkg/front_end/testcases/issue34515_lib1.dart
new file mode 100644
index 0000000..00f9340
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515_lib1.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.
+
+class ImportedClass {
+  ImportedClass(int a);
+}
diff --git a/pkg/front_end/testcases/issue34515_lib2.dart b/pkg/front_end/testcases/issue34515_lib2.dart
new file mode 100644
index 0000000..2ec64bb
--- /dev/null
+++ b/pkg/front_end/testcases/issue34515_lib2.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.
+
+class ImportedClass {
+  ImportedClass(String a);
+}
diff --git a/pkg/front_end/testcases/issue35875.dart b/pkg/front_end/testcases/issue35875.dart
new file mode 100644
index 0000000..53cd8a0
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart
@@ -0,0 +1,12 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class A {
+  int a;
+  A(int a) {
+    (this).a = a;
+  }
+}
+
+main() {}
diff --git a/pkg/front_end/testcases/issue35875.dart.hierarchy.expect b/pkg/front_end/testcases/issue35875.dart.hierarchy.expect
new file mode 100644
index 0000000..eef7d41
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.hierarchy.expect
@@ -0,0 +1,38 @@
+Object:
+  superclasses:
+  interfaces:
+  classMembers:
+    Object._haveSameRuntimeType
+    Object.toString
+    Object.runtimeType
+    Object._toString
+    Object._simpleInstanceOf
+    Object._hashCodeRnd
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._objectHashCode
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+
+A:
+  superclasses:
+    Object
+  interfaces:
+  classMembers:
+    A.a
+    Object.toString
+    Object.runtimeType
+    Object._simpleInstanceOf
+    Object._instanceOf
+    Object.noSuchMethod
+    Object._identityHashCode
+    Object.hashCode
+    Object._simpleInstanceOfFalse
+    Object._simpleInstanceOfTrue
+    Object.==
+  classSetters:
+    A.a
diff --git a/pkg/front_end/testcases/issue35875.dart.legacy.expect b/pkg/front_end/testcases/issue35875.dart.legacy.expect
new file mode 100644
index 0000000..ee54528
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.legacy.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = a;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue35875.dart.legacy.transformed.expect b/pkg/front_end/testcases/issue35875.dart.legacy.transformed.expect
new file mode 100644
index 0000000..ee54528
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.legacy.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = a;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue35875.dart.outline.expect b/pkg/front_end/testcases/issue35875.dart.outline.expect
new file mode 100644
index 0000000..305f440
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.outline.expect
@@ -0,0 +1,11 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a;
+  constructor •(core::int a) → self::A
+    ;
+}
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/issue35875.dart.strong.expect b/pkg/front_end/testcases/issue35875.dart.strong.expect
new file mode 100644
index 0000000..ee54528
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.strong.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = a;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/issue35875.dart.strong.transformed.expect b/pkg/front_end/testcases/issue35875.dart.strong.transformed.expect
new file mode 100644
index 0000000..ee54528
--- /dev/null
+++ b/pkg/front_end/testcases/issue35875.dart.strong.transformed.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+class A extends core::Object {
+  field core::int a = null;
+  constructor •(core::int a) → self::A
+    : super core::Object::•() {
+    this.{self::A::a} = a;
+  }
+}
+static method main() → dynamic {}
diff --git a/pkg/front_end/testcases/rasta/generic_factory.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/generic_factory.dart.hierarchy.expect
index a76ff0d..c01709a 100644
--- a/pkg/front_end/testcases/rasta/generic_factory.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/generic_factory.dart.hierarchy.expect
@@ -111,7 +111,7 @@
 C:
   superclasses:
     Object
-      -> A<S>
+      -> A<U>
         -> B<U>
   interfaces:
   classMembers:
diff --git a/pkg/front_end/testcases/rasta/super_mixin.dart.hierarchy.expect b/pkg/front_end/testcases/rasta/super_mixin.dart.hierarchy.expect
index ca47cf9..ff7667f 100644
--- a/pkg/front_end/testcases/rasta/super_mixin.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/rasta/super_mixin.dart.hierarchy.expect
@@ -189,11 +189,11 @@
     Mixin.x
     Mixin.z
 
-Super with Mixin:
+Super with Mixin<dynamic>:
   superclasses:
     Object
       -> Super
-  interfaces: Mixin
+  interfaces: Mixin<dynamic>
   classMembers:
     Mixin.y
     Super.f
@@ -254,7 +254,7 @@
     Object
       -> Super
         -> _D&Super&Mixin
-  interfaces: Mixin
+  interfaces: Mixin<dynamic>
   classMembers:
     Mixin.y
     Super.f
@@ -374,7 +374,7 @@
   superclasses:
     Object
       -> Super
-  interfaces: Mixin
+  interfaces: Mixin<dynamic>
   classMembers:
     Mixin.y
     Super.f
diff --git a/pkg/front_end/testcases/redirecting_factory.dart.hierarchy.expect b/pkg/front_end/testcases/redirecting_factory.dart.hierarchy.expect
index 094dc64..a3bb376 100644
--- a/pkg/front_end/testcases/redirecting_factory.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/redirecting_factory.dart.hierarchy.expect
@@ -178,7 +178,7 @@
 SimpleCaseImpl2:
   superclasses:
     Object
-  interfaces: SimpleCaseImpl<Ai2, Bi2>, SimpleCase<Ai, Bi>
+  interfaces: SimpleCaseImpl<Ai2, Bi2>, SimpleCase<Ai2, Bi2>
   classMembers:
     Object.toString
     Object.runtimeType
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments.dart.hierarchy.expect b/pkg/front_end/testcases/redirection_chain_type_arguments.dart.hierarchy.expect
index 4add870..6e0f389 100644
--- a/pkg/front_end/testcases/redirection_chain_type_arguments.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/redirection_chain_type_arguments.dart.hierarchy.expect
@@ -60,7 +60,7 @@
 C:
   superclasses:
     Object
-      -> A<U>
+      -> A<V>
         -> B<V, S>
   interfaces:
   classMembers:
diff --git a/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.hierarchy.expect b/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.hierarchy.expect
index 4add870..6e0f389 100644
--- a/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/redirection_chain_type_arguments_subst.dart.hierarchy.expect
@@ -60,7 +60,7 @@
 C:
   superclasses:
     Object
-      -> A<U>
+      -> A<V>
         -> B<V, S>
   interfaces:
   classMembers:
diff --git a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
index 892f232..86cc21b 100644
--- a/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
+++ b/pkg/front_end/testcases/runtime_checks_new/stub_from_interface_covariantInterface_from_class.dart.hierarchy.expect
@@ -102,7 +102,7 @@
   superclasses:
     Object
       -> B<F<T>>
-  interfaces: A<F<T>>, I<F<T>>
+  interfaces: A<F<F<T>>>, I<F<T>>
   classMembers:
     B.f
     Object.toString
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect
index 0db9ad9e..2e3dd40 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:13:28: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'LinkedHashSet' is from 'dart:collection'.
+// Change the type of the set literal or the context in which it is used.
+//   LinkedHashSet<int> lhs = {};
+//                            ^
+//
 // pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
 //  - 'Map' is from 'dart:core'.
 //  - 'LinkedHashMap' is from 'dart:collection'.
@@ -9,6 +16,13 @@
 //   LinkedHashMap<int, bool> lhm = {};
 //                                  ^
 //
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:32:46: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'LinkedHashSet' is from 'dart:collection'.
+// Change the type of the set literal or the context in which it is used.
+// Future<LinkedHashSet<int>> lhsfun() async => {};
+//                                              ^
+//
 // pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
 //  - 'Map' is from 'dart:core'.
 //  - 'LinkedHashMap' is from 'dart:collection'.
@@ -44,8 +58,13 @@
   core::Map<core::int, core::bool> m = <core::int, core::bool>{};
   core::Set<core::int> s = let final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>() in #t1;
   core::Iterable<core::int> i = let final core::Set<core::int> #t2 = col::LinkedHashSet::•<core::int>() in #t2;
-  col::LinkedHashSet<core::int> lhs = (let final core::Set<dynamic> #t3 = col::LinkedHashSet::•<dynamic>() in #t3) as{TypeError} col::LinkedHashSet<core::int>;
-  col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+  col::LinkedHashSet<core::int> lhs = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:13:28: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+ - 'Set' is from 'dart:core'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Change the type of the set literal or the context in which it is used.
+  LinkedHashSet<int> lhs = {};
+                           ^" in let final core::Set<dynamic> #t4 = col::LinkedHashSet::•<dynamic>() in #t4;
+  col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
  - 'Map' is from 'dart:core'.
  - 'LinkedHashMap' is from 'dart:collection'.
 Change the type of the map literal or the context in which it is used.
@@ -65,13 +84,18 @@
 static method mapfun() → asy::Future<core::Map<core::int, core::bool>> async 
   return <core::int, core::bool>{};
 static method setfun() → asy::Future<core::Set<core::int>> async 
-  return let final core::Set<core::int> #t5 = col::LinkedHashSet::•<core::int>() in #t5;
-static method iterablefun() → asy::Future<core::Iterable<core::int>> async 
   return let final core::Set<core::int> #t6 = col::LinkedHashSet::•<core::int>() in #t6;
+static method iterablefun() → asy::Future<core::Iterable<core::int>> async 
+  return let final core::Set<core::int> #t7 = col::LinkedHashSet::•<core::int>() in #t7;
 static method lhsfun() → asy::Future<col::LinkedHashSet<core::int>> async 
-  return (let final core::Set<dynamic> #t7 = col::LinkedHashSet::•<dynamic>() in #t7) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:32:46: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+ - 'Set' is from 'dart:core'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Change the type of the set literal or the context in which it is used.
+Future<LinkedHashSet<int>> lhsfun() async => {};
+                                             ^" in let final core::Set<dynamic> #t9 = col::LinkedHashSet::•<dynamic>() in #t9;
 static method lhmfun() → asy::Future<col::LinkedHashMap<core::int, core::bool>> async 
-  return let final<BottomType> #t8 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+  return let final<BottomType> #t10 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
  - 'Map' is from 'dart:core'.
  - 'LinkedHashMap' is from 'dart:collection'.
 Change the type of the map literal or the context in which it is used.
@@ -80,19 +104,19 @@
 static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
   return <core::int, core::bool>{};
 static method setfun2() → asy::FutureOr<core::Set<core::int>>
-  return let final core::Set<core::int> #t9 = col::LinkedHashSet::•<core::int>() in #t9;
+  return let final core::Set<core::int> #t11 = col::LinkedHashSet::•<core::int>() in #t11;
 static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
-  return let final core::Set<core::int> #t10 = col::LinkedHashSet::•<core::int>() in #t10;
+  return let final core::Set<core::int> #t12 = col::LinkedHashSet::•<core::int>() in #t12;
 static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
-  return let final<BottomType> #t11 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
+  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
  - 'Set' is from 'dart:core'.
  - 'FutureOr' is from 'dart:async'.
  - 'LinkedHashSet' is from 'dart:collection'.
 Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashSet<int>>'.
 FutureOr<LinkedHashSet<int>> lhsfun2() => {};
-                                          ^" in (let final core::Set<dynamic> #t12 = col::LinkedHashSet::•<dynamic>() in #t12) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+                                          ^" in (let final core::Set<dynamic> #t14 = col::LinkedHashSet::•<dynamic>() in #t14) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
 static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
-  return let final<BottomType> #t13 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
+  return let final<BottomType> #t15 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
  - 'Map' is from 'dart:core'.
  - 'FutureOr' is from 'dart:async'.
  - 'LinkedHashMap' is from 'dart:collection'.
diff --git a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
index 1a139dc..072636a 100644
--- a/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
+++ b/pkg/front_end/testcases/set_literals/disambiguation_rule.dart.strong.transformed.expect
@@ -2,6 +2,13 @@
 //
 // Problems in library:
 //
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:13:28: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'LinkedHashSet' is from 'dart:collection'.
+// Change the type of the set literal or the context in which it is used.
+//   LinkedHashSet<int> lhs = {};
+//                            ^
+//
 // pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
 //  - 'Map' is from 'dart:core'.
 //  - 'LinkedHashMap' is from 'dart:collection'.
@@ -9,6 +16,13 @@
 //   LinkedHashMap<int, bool> lhm = {};
 //                                  ^
 //
+// pkg/front_end/testcases/set_literals/disambiguation_rule.dart:32:46: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+//  - 'Set' is from 'dart:core'.
+//  - 'LinkedHashSet' is from 'dart:collection'.
+// Change the type of the set literal or the context in which it is used.
+// Future<LinkedHashSet<int>> lhsfun() async => {};
+//                                              ^
+//
 // pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
 //  - 'Map' is from 'dart:core'.
 //  - 'LinkedHashMap' is from 'dart:collection'.
@@ -56,32 +70,37 @@
         core::Map<core::int, core::bool> m = <core::int, core::bool>{};
         core::Set<core::int> s = let final core::Set<core::int> #t1 = col::LinkedHashSet::•<core::int>() in #t1;
         core::Iterable<core::int> i = let final core::Set<core::int> #t2 = col::LinkedHashSet::•<core::int>() in #t2;
-        col::LinkedHashSet<core::int> lhs = (let final core::Set<dynamic> #t3 = col::LinkedHashSet::•<dynamic>() in #t3) as{TypeError} col::LinkedHashSet<core::int>;
-        col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t4 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+        col::LinkedHashSet<core::int> lhs = let final<BottomType> #t3 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:13:28: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+ - 'Set' is from 'dart:core'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Change the type of the set literal or the context in which it is used.
+  LinkedHashSet<int> lhs = {};
+                           ^" in let final core::Set<dynamic> #t4 = col::LinkedHashSet::•<dynamic>() in #t4;
+        col::LinkedHashMap<core::int, core::bool> lhm = let final<BottomType> #t5 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:14:34: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
  - 'Map' is from 'dart:core'.
  - 'LinkedHashMap' is from 'dart:collection'.
 Change the type of the map literal or the context in which it is used.
   LinkedHashMap<int, bool> lhm = {};
                                  ^" in <dynamic, dynamic>{};
-        [yield] let dynamic #t5 = asy::_awaitHelper(self::mapfun(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t6 = asy::_awaitHelper(self::mapfun(), :async_op_then, :async_op_error, :async_op) in null;
         core::Map<core::int, core::bool> fm = :result;
-        [yield] let dynamic #t6 = asy::_awaitHelper(self::setfun(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t7 = asy::_awaitHelper(self::setfun(), :async_op_then, :async_op_error, :async_op) in null;
         core::Set<core::int> fs = :result;
-        [yield] let dynamic #t7 = asy::_awaitHelper(self::iterablefun(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t8 = asy::_awaitHelper(self::iterablefun(), :async_op_then, :async_op_error, :async_op) in null;
         core::Iterable<core::int> fi = :result;
-        [yield] let dynamic #t8 = asy::_awaitHelper(self::lhsfun(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t9 = asy::_awaitHelper(self::lhsfun(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashSet<core::int> flhs = :result;
-        [yield] let dynamic #t9 = asy::_awaitHelper(self::lhmfun(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t10 = asy::_awaitHelper(self::lhmfun(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashMap<core::int, core::bool> flhm = :result;
-        [yield] let dynamic #t10 = asy::_awaitHelper(self::mapfun2(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t11 = asy::_awaitHelper(self::mapfun2(), :async_op_then, :async_op_error, :async_op) in null;
         core::Map<core::int, core::bool> fm2 = :result;
-        [yield] let dynamic #t11 = asy::_awaitHelper(self::setfun2(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t12 = asy::_awaitHelper(self::setfun2(), :async_op_then, :async_op_error, :async_op) in null;
         core::Set<core::int> fs2 = :result;
-        [yield] let dynamic #t12 = asy::_awaitHelper(self::iterablefun2(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t13 = asy::_awaitHelper(self::iterablefun2(), :async_op_then, :async_op_error, :async_op) in null;
         core::Iterable<core::int> fi2 = :result;
-        [yield] let dynamic #t13 = asy::_awaitHelper(self::lhsfun2(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t14 = asy::_awaitHelper(self::lhsfun2(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashSet<core::int> flhs2 = :result;
-        [yield] let dynamic #t14 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
+        [yield] let dynamic #t15 = asy::_awaitHelper(self::lhmfun2(), :async_op_then, :async_op_error, :async_op) in null;
         col::LinkedHashMap<core::int, core::bool> flhm2 = :result;
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -135,7 +154,7 @@
     try {
       #L3:
       {
-        :return_value = let final core::Set<core::int> #t15 = col::LinkedHashSet::•<core::int>() in #t15;
+        :return_value = let final core::Set<core::int> #t16 = col::LinkedHashSet::•<core::int>() in #t16;
         break #L3;
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -162,7 +181,7 @@
     try {
       #L4:
       {
-        :return_value = let final core::Set<core::int> #t16 = col::LinkedHashSet::•<core::int>() in #t16;
+        :return_value = let final core::Set<core::int> #t17 = col::LinkedHashSet::•<core::int>() in #t17;
         break #L4;
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -189,7 +208,12 @@
     try {
       #L5:
       {
-        :return_value = (let final core::Set<dynamic> #t17 = col::LinkedHashSet::•<dynamic>() in #t17) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+        :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:32:46: Error: The set literal type 'Set<dynamic>' isn't of expected type 'LinkedHashSet<int>'.
+ - 'Set' is from 'dart:core'.
+ - 'LinkedHashSet' is from 'dart:collection'.
+Change the type of the set literal or the context in which it is used.
+Future<LinkedHashSet<int>> lhsfun() async => {};
+                                             ^" in let final core::Set<dynamic> #t19 = col::LinkedHashSet::•<dynamic>() in #t19;
         break #L5;
       }
       asy::_completeOnAsyncReturn(:async_completer, :return_value);
@@ -216,7 +240,7 @@
     try {
       #L6:
       {
-        :return_value = let final<BottomType> #t18 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
+        :return_value = let final<BottomType> #t20 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:33:52: Error: The map literal type 'Map<dynamic, dynamic>' isn't of expected type 'LinkedHashMap<int, bool>'.
  - 'Map' is from 'dart:core'.
  - 'LinkedHashMap' is from 'dart:collection'.
 Change the type of the map literal or the context in which it is used.
@@ -239,19 +263,19 @@
 static method mapfun2() → asy::FutureOr<core::Map<core::int, core::bool>>
   return <core::int, core::bool>{};
 static method setfun2() → asy::FutureOr<core::Set<core::int>>
-  return let final core::Set<core::int> #t19 = col::LinkedHashSet::•<core::int>() in #t19;
+  return let final core::Set<core::int> #t21 = col::LinkedHashSet::•<core::int>() in #t21;
 static method iterablefun2() → asy::FutureOr<core::Iterable<core::int>>
-  return let final core::Set<core::int> #t20 = col::LinkedHashSet::•<core::int>() in #t20;
+  return let final core::Set<core::int> #t22 = col::LinkedHashSet::•<core::int>() in #t22;
 static method lhsfun2() → asy::FutureOr<col::LinkedHashSet<core::int>>
-  return let final<BottomType> #t21 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
+  return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:38:43: Error: A value of type 'Set<dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashSet<int>>'.
  - 'Set' is from 'dart:core'.
  - 'FutureOr' is from 'dart:async'.
  - 'LinkedHashSet' is from 'dart:collection'.
 Try changing the type of the left hand side, or casting the right hand side to 'FutureOr<LinkedHashSet<int>>'.
 FutureOr<LinkedHashSet<int>> lhsfun2() => {};
-                                          ^" in (let final core::Set<dynamic> #t22 = col::LinkedHashSet::•<dynamic>() in #t22) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
+                                          ^" in (let final core::Set<dynamic> #t24 = col::LinkedHashSet::•<dynamic>() in #t24) as{TypeError} asy::FutureOr<col::LinkedHashSet<core::int>>;
 static method lhmfun2() → asy::FutureOr<col::LinkedHashMap<core::int, core::bool>>
-  return let final<BottomType> #t23 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
+  return let final<BottomType> #t25 = invalid-expression "pkg/front_end/testcases/set_literals/disambiguation_rule.dart:39:49: Error: A value of type 'Map<dynamic, dynamic>' can't be assigned to a variable of type 'FutureOr<LinkedHashMap<int, bool>>'.
  - 'Map' is from 'dart:core'.
  - 'FutureOr' is from 'dart:async'.
  - 'LinkedHashMap' is from 'dart:collection'.
diff --git a/pkg/front_end/testcases/text_serialization.status b/pkg/front_end/testcases/text_serialization.status
index a8ef9c4..0027189 100644
--- a/pkg/front_end/testcases/text_serialization.status
+++ b/pkg/front_end/testcases/text_serialization.status
@@ -96,7 +96,6 @@
 function_in_field: TextSerializationFailure # Was: Pass
 functions: TextSerializationFailure # Was: Pass
 function_type_assignments: TextSerializationFailure # Was: Pass
-function_type_default_value: TextSerializationFailure # Was: Pass
 function_type_is_check: TextSerializationFailure # Was: Pass
 function_type_recovery: TextSerializationFailure # Was: Pass
 future_or_test: TextSerializationFailure # Was: Pass
@@ -665,7 +664,9 @@
 invalid_cast: TextSerializationFailure # Was: Pass
 invalid_type: TypeCheckError
 invocations: TextSerializationFailure # Was: RuntimeError
+issue34515: TextSerializationFailure
 issue34899: TypeCheckError
+issue35875: TextSerializationFailure
 literals: TextSerializationFailure # Was: Pass
 local_generic_function: TextSerializationFailure # Was: Pass
 magic_const: TextSerializationFailure # Was: Pass
@@ -785,7 +786,6 @@
 rasta/issue_000043: TextSerializationFailure # Was: RuntimeError
 rasta/issue_000044: TextSerializationFailure # Was: RuntimeError
 rasta/issue_000046: TextSerializationFailure # Was: RuntimeError
-rasta/issue_000047: TextSerializationFailure # Was: Pass
 rasta/issue_000048: TextSerializationFailure # Was: Pass
 rasta/issue_000052: TextSerializationFailure # Was: Pass
 rasta/issue_000053: TextSerializationFailure # Was: Pass
@@ -837,7 +837,6 @@
 regress/issue_29941: TextSerializationFailure # Was: Pass
 regress/issue_29942: TextSerializationFailure # Was: Pass
 regress/issue_29944: TextSerializationFailure # Was: Pass
-regress/issue_29975: TextSerializationFailure # Was: Pass
 regress/issue_29976: RuntimeError # Tests runtime behavior of error recovery.
 regress/issue_29978: TextSerializationFailure # Was: Pass
 regress/issue_29979: TextSerializationFailure # Was: Pass
@@ -971,6 +970,7 @@
 top_level_accessors: TextSerializationFailure # Was: Pass
 top_level_library_method: TextSerializationFailure # Was: Pass
 typedef: TextSerializationFailure # Was: Pass
+type_of_null: 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_of_null.dart b/pkg/front_end/testcases/type_of_null.dart
new file mode 100644
index 0000000..859c3db
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.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.
+
+/*@testedFeatures=inference*/
+T map<T>(T Function() f1, T Function() f2) {}
+
+id<T>(T t) => t;
+
+Null foo() => null;
+
+main() {
+  /*@typeArgs=Null*/map(/*@returnType=Null*/() {}, /*@returnType=<BottomType>*/() => throw "hello");
+  /*@typeArgs=Null*/map(/*@returnType=<BottomType>*/() => throw "hello", /*@returnType=Null*/() {});
+  Null Function() f = /*@returnType=Null*/() {};
+  /*@typeArgs=Null*/map(foo, /*@returnType=<BottomType>*/() => throw "hello");
+  /*@typeArgs=Null*/map(/*@returnType=<BottomType>*/() => throw "hello", foo);
+  /*@typeArgs=Null*/map(/*@returnType=Null*/() {
+    return null;
+  }, /*@returnType=<BottomType>*/() => throw "hello");
+
+  /*@typeArgs=Null*/map(/*@returnType=<BottomType>*/() => throw "hello", /*@returnType=Null*/() {
+    return null;
+  });
+  /*@typeArgs=() -> Null*/id(/*@returnType=Null*/() {});
+}
diff --git a/pkg/front_end/testcases/type_of_null.dart.legacy.expect b/pkg/front_end/testcases/type_of_null.dart.legacy.expect
new file mode 100644
index 0000000..83e584c
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.dart.legacy.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method map<T extends core::Object = dynamic>(() → self::map::T f1, () → self::map::T f2) → self::map::T {}
+static method id<T extends core::Object = dynamic>(self::id::T t) → dynamic
+  return t;
+static method foo() → core::Null
+  return null;
+static method main() → dynamic {
+  self::map<dynamic>(() → dynamic {}, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", () → dynamic {});
+  () → core::Null f = () → dynamic {};
+  self::map<dynamic>(self::foo, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", self::foo);
+  self::map<dynamic>(() → dynamic {
+    return null;
+  }, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", () → dynamic {
+    return null;
+  });
+  self::id<dynamic>(() → dynamic {});
+}
diff --git a/pkg/front_end/testcases/type_of_null.dart.legacy.transformed.expect b/pkg/front_end/testcases/type_of_null.dart.legacy.transformed.expect
new file mode 100644
index 0000000..83e584c
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.dart.legacy.transformed.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method map<T extends core::Object = dynamic>(() → self::map::T f1, () → self::map::T f2) → self::map::T {}
+static method id<T extends core::Object = dynamic>(self::id::T t) → dynamic
+  return t;
+static method foo() → core::Null
+  return null;
+static method main() → dynamic {
+  self::map<dynamic>(() → dynamic {}, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", () → dynamic {});
+  () → core::Null f = () → dynamic {};
+  self::map<dynamic>(self::foo, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", self::foo);
+  self::map<dynamic>(() → dynamic {
+    return null;
+  }, () → dynamic => throw "hello");
+  self::map<dynamic>(() → dynamic => throw "hello", () → dynamic {
+    return null;
+  });
+  self::id<dynamic>(() → dynamic {});
+}
diff --git a/pkg/front_end/testcases/type_of_null.dart.outline.expect b/pkg/front_end/testcases/type_of_null.dart.outline.expect
new file mode 100644
index 0000000..c42aee1
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.dart.outline.expect
@@ -0,0 +1,12 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method map<T extends core::Object = dynamic>(() → self::map::T f1, () → self::map::T f2) → self::map::T
+  ;
+static method id<T extends core::Object = dynamic>(self::id::T t) → dynamic
+  ;
+static method foo() → core::Null
+  ;
+static method main() → dynamic
+  ;
diff --git a/pkg/front_end/testcases/type_of_null.dart.strong.expect b/pkg/front_end/testcases/type_of_null.dart.strong.expect
new file mode 100644
index 0000000..5bee3f8
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.dart.strong.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method map<T extends core::Object = dynamic>(() → self::map::T f1, () → self::map::T f2) → self::map::T {}
+static method id<T extends core::Object = dynamic>(self::id::T t) → dynamic
+  return t;
+static method foo() → core::Null
+  return null;
+static method main() → dynamic {
+  self::map<core::Null>(() → core::Null {}, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", () → core::Null {});
+  () → core::Null f = () → core::Null {};
+  self::map<core::Null>(self::foo, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", self::foo);
+  self::map<core::Null>(() → core::Null {
+    return null;
+  }, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", () → core::Null {
+    return null;
+  });
+  self::id<() → core::Null>(() → core::Null {});
+}
diff --git a/pkg/front_end/testcases/type_of_null.dart.strong.transformed.expect b/pkg/front_end/testcases/type_of_null.dart.strong.transformed.expect
new file mode 100644
index 0000000..5bee3f8
--- /dev/null
+++ b/pkg/front_end/testcases/type_of_null.dart.strong.transformed.expect
@@ -0,0 +1,23 @@
+library;
+import self as self;
+import "dart:core" as core;
+
+static method map<T extends core::Object = dynamic>(() → self::map::T f1, () → self::map::T f2) → self::map::T {}
+static method id<T extends core::Object = dynamic>(self::id::T t) → dynamic
+  return t;
+static method foo() → core::Null
+  return null;
+static method main() → dynamic {
+  self::map<core::Null>(() → core::Null {}, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", () → core::Null {});
+  () → core::Null f = () → core::Null {};
+  self::map<core::Null>(self::foo, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", self::foo);
+  self::map<core::Null>(() → core::Null {
+    return null;
+  }, () → <BottomType>=> throw "hello");
+  self::map<core::Null>(() → <BottomType>=> throw "hello", () → core::Null {
+    return null;
+  });
+  self::id<() → core::Null>(() → core::Null {});
+}
diff --git a/pkg/front_end/testing.json b/pkg/front_end/testing.json
index 6ad3fa1..6dd8999 100644
--- a/pkg/front_end/testing.json
+++ b/pkg/front_end/testing.json
@@ -192,9 +192,12 @@
         "/language_2/export_ambiguous_main_test\\.dart$",
         "/language_2/export_double_same_main_test\\.dart$",
         "/language_2/export_main_test\\.dart$",
+        "/language_2/import_nonexisting_dart_uri_test\\.dart$",
+        "/language_2/internal_library_test\\.dart$",
         "/language_2/issue1578_negative_test\\.dart$",
         "/language_2/missing_part_of_tag_test\\.dart$",
         "/language_2/no_main_test\\.dart$",
+        "/language_2/part_refers_to_core_library_test\\.dart$",
         "/language_2/regress_27957_test\\.dart$",
         "/language_2/script1_negative_test\\.dart$",
         "/language_2/script2_negative_test\\.dart$",
diff --git a/pkg/front_end/tool/_fasta/command_line.dart b/pkg/front_end/tool/_fasta/command_line.dart
index f7c85f9..77987c1 100644
--- a/pkg/front_end/tool/_fasta/command_line.dart
+++ b/pkg/front_end/tool/_fasta/command_line.dart
@@ -379,7 +379,8 @@
           ..verbose = verbose
           ..verify = verify
           ..bytecode = bytecode
-          ..experimentalFlags = experimentalFlags,
+          ..experimentalFlags = experimentalFlags
+          ..environmentDefines = parsedArguments.defines,
         inputs: <Uri>[Uri.parse(arguments[0])],
         output: resolveInputUri(arguments[3]));
   } else if (arguments.isEmpty) {
@@ -413,7 +414,8 @@
     ..omitPlatform = omitPlatform
     ..verbose = verbose
     ..verify = verify
-    ..experimentalFlags = experimentalFlags;
+    ..experimentalFlags = experimentalFlags
+    ..environmentDefines = parsedArguments.defines;
 
   // TODO(ahe): What about chase dependencies?
 
diff --git a/pkg/js/proposal.md b/pkg/js/proposal.md
new file mode 100644
index 0000000..abc888d
--- /dev/null
+++ b/pkg/js/proposal.md
@@ -0,0 +1,1636 @@
+# Better JavaScript and Dart interoperability
+
+Table of contents:
+
+<!-- toc -->
+
+- [Motivation](#motivation)
+- [Typed APIs](#typed-apis)
+  * [Automatic Typed API Generation](#automatic-typed-api-generation)
+  * [Static Dispatch](#static-dispatch)
+    + [Extension Fields](#extension-fields)
+  * [JS Interop Checked Mode](#js-interop-checked-mode)
+  * [Data Type Interoperability](#data-type-interoperability)
+  * [Implicit and Explicit Conversions](#implicit-and-explicit-conversions)
+- [Functions](#functions)
+  * [Optional Arguments](#optional-arguments)
+  * [Named Arguments](#named-arguments)
+  * [Overloads](#overloads)
+  * [This Argument](#this-argument)
+  * [Method Tearoffs](#method-tearoffs)
+  * [Generic Type Parameters](#generic-type-parameters)
+- [Data Types Conversions](#data-types-conversions)
+  * [Generic Types, List and JS Array](#generic-types-list-and-js-array)
+  * [Null and Undefined](#null-and-undefined)
+  * [Future and JS Promise](#future-and-js-promise)
+  * [Iterable and JS Iterable](#iterable-and-js-iterable)
+  * [Stream and JS Async Iterable](#stream-and-js-async-iterable)
+  * [Stream and Callbacks](#stream-and-callbacks)
+  * [DateTime and JS Date](#datetime-and-js-date)
+  * [Map/Set and JS Map/Set](#mapset-and-js-mapset)
+  * [Maps and JS Objects](#maps-and-js-objects)
+    + [Wrapper-based JSObjectMap](#wrapper-based-jsobjectmap)
+    + [Autoboxing JSObjectMap](#autoboxing-jsobjectmap)
+- [Less Static Interop](#less-static-interop)
+  * [Virtual Dispatch](#virtual-dispatch)
+  * [Interface and Dynamic dispatch](#interface-and-dynamic-dispatch)
+  * [JS Proxy](#js-proxy)
+  * [JS Reflection](#js-reflection)
+- [Exporting Dart to JS](#exporting-dart-to-js)
+  * [Exporting classes and libraries](#exporting-classes-and-libraries)
+  * [Inheritance between Dart and JS](#inheritance-between-dart-and-js)
+  * [Interop with JS Modules](#interop-with-js-modules)
+  * [Exposing JS Methods as Getters](#exposing-js-methods-as-getters)
+- [JS Types in the Dart Type System](#js-types-in-the-dart-type-system)
+- [Implementation Roadmap](#implementation-roadmap)
+- [Compatibility and Evolution](#compatibility-and-evolution)
+- [FAQ](#faq)
+  * [Q: How does JSON work?](#q-how-does-json-work)
+  * [Q: Would new Dart language features help?](#q-would-new-dart-language-features-help)
+  * [Q: Can dart2js and dartdevc share implementation for JS interop?](#q-can-dart2js-and-dartdevc-share-implementation-for-js-interop)
+  * [Q: If a JS API returns "Object" does this break dart2js tree shaking?](#q-if-a-js-api-returns-object-does-this-break-dart2js-tree-shaking)
+  * [Q: Could we use dynamic interop instead?](#q-could-we-use-dynamic-interop-instead)
+
+<!-- tocstop -->
+
+## Motivation
+
+Better interoperability with JavaScript is one of the most highly requested 
+features for Dart. Previous work has made JS interop possible, but gaps remain.
+This proposal outlines a series of usability improvements that, taken together,
+make it much easier to use JS from Dart and vice versa.
+
+Here's an example of JS interop is like today, from the [Firebase package](https://pub.dartlang.org/packages/firebase):
+```dart
+import 'interop/app_interop.dart';
+
+/// A Firebase App holds the initialization information for a collection
+/// of services.
+///
+/// See: <https://firebase.google.com/docs/reference/js/firebase.app>.
+class App extends JsObjectWrapper<AppJsImpl> {
+  // [ed: doc comments removed to condense code]
+  static final _expando = Expando<App>();
+
+  String get name => jsObject.name;
+  FirebaseOptions get options => jsObject.options;
+
+  static App getInstance(AppJsImpl jsObject) {
+    if (jsObject == null) {
+      return null;
+    }
+    return _expando[jsObject] ??= App._fromJsObject(jsObject);
+  }
+
+  App._fromJsObject(AppJsImpl jsObject) : super.fromJsObject(jsObject);
+
+  Auth auth() => Auth.getInstance(jsObject.auth());
+  Database database() => Database.getInstance(jsObject.database());
+  Future delete() => handleThenable(jsObject.delete());
+  Firestore firestore() => Firestore.getInstance(jsObject.firestore());
+
+  Storage storage([String url]) {
+    var jsObjectStorage =
+        (url != null) ? jsObject.storage(url) : jsObject.storage();
+    return Storage.getInstance(jsObjectStorage);
+  }
+}
+
+// [ed: in interop/app_interop.dart]
+
+@JS('App')
+abstract class AppJsImpl {
+  external String get name;
+  external FirebaseOptions get options;
+  external AuthJsImpl auth();
+  external DatabaseJsImpl database();
+  external PromiseJsImpl delete();
+  external StorageJsImpl storage([String url]);
+  external FirestoreJsImpl firestore();
+}
+```
+
+Nearly all of the Firebase classes are wrapped like that. It's a lot of work and
+boilerplate to implement wrappers like this, and it adds overhead to every
+operation.
+
+What we'd like to write is more like this:
+```dart
+@JS()
+class App {
+  external String get name;
+  external FirebaseOptions get options;
+
+  // Wrappers no longer necessary for these classes.
+  external Auth auth();
+  external Database database();
+  external Firestore firestore();
+
+  // Promise -> Future is handled automatically
+  external Future delete();
+
+  // Optional arguments are handled correctly by the compiler.
+  // (In advanced cases, there are ways to declare overloads.)
+  external Storage storage([String url]);
+}
+```
+
+The [Google Maps API](https://github.com/a14n/dart-google-maps) package is
+similar, but generated using the [js_wrapping](https://github.com/a14n/dart-js-wrapping)
+code generator:
+
+```dart
+@GeneratedFrom(_LatLngBounds)
+@JsName('google.maps.LatLngBounds')
+class LatLngBounds extends JsInterface {
+  LatLngBounds([LatLng sw, LatLng ne])
+      : this.created(JsObject(context['google']['maps']['LatLngBounds'],
+            [__codec0.encode(sw), __codec0.encode(ne)]));
+  LatLngBounds.created(JsObject o) : super.created(o);
+
+  bool contains(LatLng latLng) =>
+      asJsObject(this).callMethod('contains', [__codec0.encode(latLng)]);
+  bool equals(LatLngBounds other) =>
+      asJsObject(this).callMethod('equals', [__codec1.encode(other)]);
+  LatLngBounds extend(LatLng point) => __codec1
+      .decode(asJsObject(this).callMethod('extend', [__codec0.encode(point)]));
+  LatLng get center => _getCenter();
+  LatLng _getCenter() =>
+      __codec0.decode(asJsObject(this).callMethod('getCenter'));
+  LatLng get northEast => _getNorthEast();
+  LatLng _getNorthEast() =>
+      __codec0.decode(asJsObject(this).callMethod('getNorthEast'));
+  LatLng get southWest => _getSouthWest();
+  LatLng _getSouthWest() =>
+      __codec0.decode(asJsObject(this).callMethod('getSouthWest'));
+  bool intersects(LatLngBounds other) =>
+      asJsObject(this).callMethod('intersects', [__codec1.encode(other)]);
+  bool get isEmpty => _isEmpty();
+  bool _isEmpty() => asJsObject(this).callMethod('isEmpty');
+  LatLng toSpan() => __codec0.decode(asJsObject(this).callMethod('toSpan'));
+  String toString() => asJsObject(this).callMethod('toString');
+  String toUrlValue([num precision]) =>
+      asJsObject(this).callMethod('toUrlValue', [precision]);
+  LatLngBounds union(LatLngBounds other) => __codec1
+      .decode(asJsObject(this).callMethod('union', [__codec1.encode(other)]));
+}
+```
+
+What we'd like to write instead:
+```dart
+@JS('google.maps.LatLngBounds')
+class LatLngBounds {
+  external LatLngBounds([LatLng sw, LatLng ne]);
+
+  external bool contains(LatLng latLng);
+  external bool equals(LatLngBounds other);
+  external LatLngBounds extend(LatLng point);
+  external bool intersects(LatLngBounds other);
+  external LatLng toSpan();
+  external String toString();
+  external String toUrlValue([num precision]);
+  external LatLngBounds union(LatLngBounds other);
+
+  @sealed
+  LatLng get center => _getCenter();
+  @sealed
+  LatLng get northEast => _getNorthEast();
+  @sealed
+  LatLng get southWest => _getSouthWest();
+  @sealed
+  bool get isEmpty => _isEmpty();
+
+  @JS('getCenter')
+  external LatLng _getCenter();
+  @JS('getNorthEast')
+  external LatLng _getNorthEast();
+  @JS('getSouthWest')
+  external LatLng _getSouthWest();
+  @JS('isEmpty')
+  external bool _isEmpty();
+}
+```
+
+The rest of the proposal outlines how we get there, as well as many other
+usability and correctness improvements.
+
+
+## Typed APIs
+
+The key principle behind Dart and JS interop is declaring API signatures,
+as illustrated above. The two main pieces of this are `@JS()` annotations and
+the `external` keyword:
+
+```dart
+@JS('firebase.app')
+library firebase.app;
+
+import 'package:js/js.dart' show JS;
+
+@JS('App')
+class App {
+  external String get name;
+  // [...]
+}
+```
+
+The `external` keyword marks a class member or library member as representing a 
+JavaScript API. It allows the body of the API to be omitted, and is only valid
+on a declaration that is in a `@JS()` context (either it is marked with `@JS()`
+itself, or is within a library/class that is marked).
+
+The `@JS()` annotation marks a declaration (library, class, library member or
+class member) as representing a JavaScript API. An optional string can be
+provided, to specify the name of the declaration in JS. This allows APIs to be
+renamed. For example:
+
+```dart
+@JS()
+@anonymous
+class UserInfo {
+  // [...]
+
+  /// Returns a JSON-serializable representation of this object.
+  @JS('toJSON')
+  @JSConvert(dartify)
+  external Map<String, dynamic> toJson();
+}
+```
+
+In the example above `toJSON()` was named `toJson()` to match Dart naming
+conventions. (This also implicitly marks it as `@sealed`.)
+
+Typed APIs provide many benefits:
+- They assist discovery and use of the API, via autocompletion in the editor.
+- They provide static type checking to help use the API correctly.
+- They're the foundation of automatic data type conversions, and adding Dart
+  members to JS interop classes, to provide a more Dart-like API when desired.
+
+
+### Automatic Typed API Generation
+
+Many JavaScript APIs have types now, either from TypeScript or Closure Compiler
+comments. We'd like to have a tool to automatically generate
+Dart interop APIs from those. The resulting file can then be hand edited, if
+desired, to further customize the interop, or used immediately.
+
+
+### Static Dispatch
+
+The example above renames *instance members*, allowing the API to be made
+more Dart-friendly. This feature is crucial for interoperability, as the
+JavaScript API may have a name that is not legal in Dart, or its name may have
+different visibility, such as names starting with underscore.
+
+Renames are made possible by taking advantage of the static type of the
+reciever. This is similar to static calls and extension methods.
+
+```dart
+UserInfo user = someExpression;
+print(user.toJson());
+```
+
+The compiler only needs to generate something like:
+
+```js
+let user = someExpression;
+core.print(js.dartify(user.toJSON()));
+```
+
+Here a conversion was also inserted, based on the `@JSConvert(dartify)`
+annotation. Because it's static, the compilers are able to inline JS code if
+they choose to.
+
+Static dispatch lets us reshape APIs in very powerful ways, without the
+overhead and complexity of wrappers. It also provides a good user experience
+in the IDE.
+
+Notably, this interop is extremely similar to the language team's
+[Static Extension Types](https://github.com/dart-lang/language/issues/42) and
+[Static Extension Methods](https://github.com/dart-lang/language/issues/41)
+proposals. All members in a JS interop class that have Dart implementation code
+(i.e. function bodies, rather than `external`) are required to be nonextensible.
+If we get those language features, they'll provide an alternate syntax, and
+offer additional capabilities.
+
+
+#### Extension Fields
+
+In existing web compilers, there is some ambiguity about how fields on JS types
+are interpreted:
+
+```dart
+@JS()
+class MyJSClass {
+  external int get foo;
+  external set foo(int value);
+
+  int bar;
+
+  @JS()
+  int baz;
+}
+```
+
+Both compilers support "foo". DDC interprets "bar" as a getter/setter pair
+similar to "foo" but dart2js does not. Neither compiler recognizes the `@JS` on
+"baz".
+
+Existing JS interop code suggests we need to provide two features:
+- make it easy to declare external getter/setter pairs.
+- add Dart state to JS classes.
+
+We can accomplish this by using `@JS` to indicate a JS field. With the new
+interpretation:
+
+```dart
+@JS()
+class MyJSClass {
+  external int get foo; // external getter/setter
+  external set foo(int value);
+
+  @sealed
+  int bar; // Dart extension field
+
+  @JS() // sugar for external getter/setter, can't have an initializer
+  int baz;
+}
+```
+
+The "extension field" is essentially an expando:
+
+```dart
+@JS()
+class MyJSClass {
+  // [...]
+  @sealed
+  int get bar => _bar[this];
+  @sealed
+  void set bar(value) { _bar[this] = value; }
+}
+
+final _bar = Expando<int>();
+```
+
+(Web compilers may implement it differently, such as a JS Symbol property stored
+on the instance.)
+
+
+### JS Interop Checked Mode
+
+We may want a "JS interop checked mode" to instrument APIs and check that
+parameters and return types match their declarations. This would provide a lot
+of added safety. It could be turned on for tests, for example.
+If implemented, this would be an opt-in capability
+
+
+### Data Type Interoperability
+
+To use typed APIs, we need to be able to pass data back and forth, and write
+type annotations for the parameters and return value. One of the key questions
+then is: can JS and Dart objects be passed directly, or is some type of
+conversion or wrappers required?
+
+As the Firebase example illustrates, using wrappers everywhere has significant
+cost in code size, performance, and usability.
+
+However, it is impossible to make every single Dart and JS object "just work" in
+the other environment. Consider this example:
+
+```dart
+  external factory RecaptchaVerifier(container,
+      [@JSConvert(jsify) Map<String, Object> parameters, App app]);
+```
+
+While JavaScript has a [Map class](https://tc39.github.io/ecma262/#sec-map-objects) 
+now, many APIs still use raw JS Objects, such as `{ "size": "invisible" }`. In
+Dart `Map<String, Object>` is an interface that at runtime, could contain any
+class that implements Map (including user-defined Maps). Dart's equality
+semantics (`operator ==` and `hashCode`) are different from JS too.
+
+(Even if we're only interested in Dart's default LinkedHashMap with String
+keys, it would be difficult to make this work. The Map class would need to
+store its data as properties on itself. Some keys would not work correctly such
+as "__proto__", and some operations would have different performance 
+characteristics. The map can be modified from JS, so it's difficult to see how
+things like `length` and `keys` could be implemented efficiently.)
+
+For these reasons, we can't take an all-or-nothing approach: ideally most types
+are wrapperless, but we'll need good support for conversions too.
+
+
+### Implicit and Explicit Conversions
+
+Wrapperless types are very convenient: you pass them back and forth, and they
+just work. Explicit conversions involve a lot of boilerplate that must be
+repeated everywhere. For example, we could've written the earlier `toJson()`
+example like this:
+
+```dart
+@JS()
+@anonymous
+class UserInfo {
+  // [...]
+
+  /// Returns a JSON-serializable representation of this object.
+  @sealed
+  Map<String, dynamic> toJson() => dartify(_toJson());
+
+  @JS('toJSON')
+  external Map<String, dynamic> _toJson();
+}
+```
+
+Or worse, the original version of the Recaptcha example shown earlier:
+```dart
+factory RecaptchaVerifier(container,
+          [Map<String, dynamic> parameters, App app]) =>
+      (parameters != null)
+          ? ((app != null)
+              ? RecaptchaVerifier.fromJsObject(RecaptchaVerifierJsImpl(
+                  container, jsify(parameters), app.jsObject))
+              : RecaptchaVerifier.fromJsObject(
+                  RecaptchaVerifierJsImpl(container, jsify(parameters))))
+          : RecaptchaVerifier.fromJsObject(RecaptchaVerifierJsImpl(container));
+
+// [ed: in interop/auth_interop.dart]
+
+  external factory RecaptchaVerifierJsImpl(container,
+      [Object parameters, AppJsImpl app]);
+```
+
+Implicit conversions reduce the boilerplate and make the types feel more
+like directly passed (wrapperless) types. They require less developer input to
+get the correct conversion. The downside is that the conversion is less visible,
+and the implications of conversions may surprise the developer. Overall these
+conversion are similar to "autoboxing" in C# and Java, and are probably a net
+usability benefit.
+
+There's a language issue for [implicit conversions](https://github.com/dart-lang/language/issues/107),
+so that may provide us better support. The native FFI also has a similar
+mechanism for marshalling.
+
+
+## Functions
+
+Similar to Array, functions from JS do not have reified type information and are
+allowed to be cast to any Dart function. This is already implemented in Dart web
+compilers.
+
+Ideally Dart functions could also be directly passed to JS. However this is not
+the case in dart2js. It is not simple to change that, however.
+
+In the meantime, automatic converisons will be provided:
+- passing a Dart function type to any JS parameter performs an `allowInterop`
+  conversion.
+- passing any Dart value to a JS function type performs an `allowInterop`
+  conversion if the runtime value is a Dart function.
+- Function typed parameters/variables can be annotated with `@JS()` to indicate
+  that they should be treated as being passed to JS, implying an `allowInterop`
+  conversion.
+- Typedefs can be annoated with `@JS()` to indicated they should be treated as
+  being passed to JS, implying an `allowInterop` conversion.
+
+One particular challenge is that dartdevc (DDC) represents Dart functions as JS
+functions, so it is difficult to catch problems that may arise later in dart2js.
+It should not occur much in practice, thanks to implicit conversions, and the
+previously mentioned "checked mode" provides a means to catch it.
+
+
+### Optional Arguments
+
+To pass functions between JS and Dart, we need to define how calling conventions
+work. The general principle is "when calling JS, work like JS". Consider the
+first example again:
+
+```dart
+  Storage storage([String url]) {
+    var jsObjectStorage =
+        (url != null) ? jsObject.storage(url) : jsObject.storage();
+    return Storage.getInstance(jsObjectStorage);
+  }
+
+  // What we'd like to write:
+  external Storage storage([String url]);
+```
+
+Or for a more complex case, consider the Recaptcha example:
+```dart
+factory RecaptchaVerifier(container,
+          [Map<String, dynamic> parameters, App app]) =>
+      (parameters != null)
+          ? ((app != null)
+              ? RecaptchaVerifier.fromJsObject(RecaptchaVerifierJsImpl(
+                  container, jsify(parameters), app.jsObject))
+              : RecaptchaVerifier.fromJsObject(
+                  RecaptchaVerifierJsImpl(container, jsify(parameters))))
+          : RecaptchaVerifier.fromJsObject(RecaptchaVerifierJsImpl(container));
+
+// [ed: in interop/auth_interop.dart]
+  external factory RecaptchaVerifierJsImpl(container,
+      [Object parameters, AppJsImpl app]);
+```
+
+These methods are dispatching the call manually, to handle the difference in
+JS and Dart calling conventions: optional arguments are not passed as `null`
+in JS, but are visible via `arguments.length` and their value defaults to
+`undefined` rather than `null`.
+
+What we'd like to write for Recaptcha is: 
+```dart
+  external factory RecaptchaVerifier(container,
+      [@JSMapToObject() Map<String, Object> parameters, App app]);
+```
+
+Because it's now a JS function, the compilers must call it with the correct
+number of arguments. For example, this Dart code:
+```dart
+RecaptchaVerifier(container);
+RecaptchaVerifier(container, {'foo': 'bar'});
+RecaptchaVerifier(container, {'foo': 'bar'}, app);
+```
+
+Should compile to JS code similar to:
+```js
+new auth.RecaptchaVerifier(container);
+new auth.RecaptchaVerifier(container, {'foo': 'bar'});
+new auth.RecaptchaVerifier(container, {'foo': 'bar'}, app);
+```
+
+If someone wants to forward multiple parameters, we could provide an annotation
+to help:
+
+```dart
+@JS()
+class Example {
+  @sealed
+  Object wrapsMethodWithOptionalArgs([Object foo, Object bar]) {
+    // [...]
+    return _underlyingJSMethod(foo, bar);
+  }
+
+  @JS('underlyingJSMethod')
+  external Object _underlyingJSMethod(
+      [@JSNullToOptional() Object foo, @JSNullToOptional() Object bar]);
+}
+```
+
+With `@JSNullToOptional()` the compiler would automatically check for `null` in
+those arguments and dispatch the call to the correct JS signature.
+
+
+### Named Arguments
+
+JS functions don't have a notion of named arguments; rather by convention, JS
+Object literals are passed, and optionally destructured into parameters by the
+callee.
+
+Named arguments will be allowed as syntactic sugar for passing a JS object
+literal. For example:
+
+```dart
+class Example {
+  external takesJSObject({String a, int b})
+}
+f(Example e) {
+  e.takesJSObject(a: 'hi', b: 123);
+}
+```
+
+Is equivalent to this JS:
+
+```js
+function f(e) {
+  e.takesJSObject({a: 'hi', b: 123});
+}
+```
+
+Similarly if a Dart function that takes named arguments is passed to JS, it
+must desugar them. To make this work, we'll need to restrict JS function types
+to having only optional or named arguments, not both.
+
+
+### Overloads
+
+Method overloads do not exist in JavaScript. They can be helpful for
+expressing type signatures, and calling native APIs that are
+overloaded, such as Canvas's [createImageData](https://html.spec.whatwg.org/multipage/canvas.html#pixel-manipulation).
+ 
+Overloads can be expressed by declaring multiple Dart methods and giving them
+the same JavaScript name:
+
+```dart
+// in CanvasRenderingContext2D
+  @JS('createImageData')
+  external ImageData createImageDataFromImage(ImageData imagedata);
+  @JS()
+  external ImageData createImageData(int sw, int sh);
+```
+
+If the author wanted to expose those as the same method, they could instead do:
+
+```dart
+  @JS()
+  external ImageData createImageData(imagedata_OR_sw, [int sh]);
+```
+
+Dispatching based on types should not generally be required, but if it is, it
+can be written like this:
+
+```dart
+  @sealed
+  ImageData createImageData(imagedata_OR_sw, [int sh]) {
+    if (imagedata_OR_sw is int && sh != null) {
+      return _createImageData(imagedata_OR_sw, sh);
+    } else {
+      return _createImageDataFromImage(imagedata_OR_sw);
+    }
+  }
+  JS('createImageData')
+  external ImageData _createImageDataFromImage(ImageData imagedata);
+  @JS()
+  external ImageData _createImageData(int sw, int sh);
+```
+
+The language team is also considering the problem of declaring Dart APIs like
+this, see [issue 145](https://github.com/dart-lang/language/issues/145).
+
+
+### This Argument
+
+JS functions have a hidden `this` parameter, and it is sometimes important for
+Dart to be able to pass that to JS, or receive it from JS.
+
+That's accomplished with the `@JSThis()` annotation:
+
+```dart
+@JS('Object')
+abstract class JSObject {
+  external static _JSObjectPrototype prototype;
+}
+
+@JS()
+@anonymous
+abstract class _JSObjectPrototype {
+  external static bool hasOwnProperty(@JSThis() target, propertyKey);
+}
+
+@JS()
+@anonymous
+class PropertyDescriptor {
+  @JS() Object value;
+  @JS() bool writable;
+  @JS() bool configurable;
+  @JS() bool enumerable;
+  external Object Function(@JSThis() Object) get;
+  external void Function(@JSThis() Object, Object) set;
+}
+```
+
+This lets you declare which parameter should receive `this`/be passed as `this`.
+
+
+### Method Tearoffs
+
+Tearoffs of JS types should bind `this`, as noted in
+[issue 32370](https://github.com/dart-lang/sdk/issues/32370). We also need to
+decide what runtime type information to attach. Tearoffs could get the
+statically visible type at the call site, or they could be treated like other
+JS functions, and be assignable to any function type. Untyped is advantageous
+for performance/simplicity, so it's probably preferrable, unless we find
+compelling examples.
+
+
+### Generic Type Parameters
+
+JavaScript does not have reified generic types. Generic types can
+be used in interop signatures, but they have no effect at runtime, and no type
+argument is passed. 
+
+For JS code calling into exported Dart functions (e.g. `@JSExport`), generic
+type arguments will come through as a special, runtime-only type `JSAny` that
+represents the absence of a reified generic type. This is discussed further in
+the next section, about Generic Types, List and JS Array.
+
+
+## Data Types Conversions
+
+This section discusses specific data types, and has recommendations for how
+these should be handled in the Dart web compilers
+
+### Generic Types, List and JS Array
+
+Both Dart web compilers already use JS Array to implement Dart `List<T>` in
+a wrapperless style. The main challenge for JS interop is how to handle generic
+types.
+
+Generic types in Dart are reified, in other words, generic type arguments are
+represented and stored at run time. These are used by `is` and `as` checks, for
+example, `<int>[1, 2, 3] is List<int>` will return true, and the cast
+`<int>[1, 2, 3] as List<int>` will succeed. But `<int>[1, 2, 3] is List<String>`
+will return false.
+
+JavaScript cannot create Arrays that have an associated Dart generic type.
+Currently these are interpreted as `List<dynamic>`, which frequently results in
+a cast failure, or requires a workaround. For example:
+```dart
+List<App> get apps => firebase.apps
+    // explicitly typing the param as dynamic to work-around
+    // https://github.com/dart-lang/sdk/issues/33537
+    .map((dynamic e) => App.getInstance(e))
+    .toList();
+
+// [in another file]
+
+@JS()
+external List<AppJsImpl> get apps;
+```
+
+The problem is that `List<AppJsImpl> get apps` actually returns `List<dynamic>`,
+so calls like `.map` will fail Dart's reified generic checks (because the list
+could contain anything, the parameter `e` must be typed to accept anything).
+This leads to other strange results, such as:
+
+```dart
+@JS()
+external List<String> get stringsFromJS;
+
+main() {
+  // Either prints `true` or `false`!
+  // True if the compiler optimizes it, false if it's evaluated at runtime.
+  print(stringsFromJS is List<String>);
+
+  List list = stringsFromJS;
+  List<String> list2 = list; // type error: not a List<String>.
+}
+```
+
+The new version of this API is simply:
+```dart
+external List<App> get apps;
+```
+
+And it works mostly how you'd expect with `is` and `as` checks:
+
+```dart
+main() {
+  List apps = firebase.apps;
+  print(apps is List<App>); // true
+  apps as List<App>; // works
+
+  // prints list of names names, `(a)` is inferred as `(App a)`
+  print(apps.map((a) => a.name).toList());
+
+  apps is List<int>         // true: `int` could be from JS
+  apps is List<MyDartClass> // false: can't be a list of Dart classes
+                            // (unless the class is exported to JS)
+}
+```
+
+The last check is an example of one consequence of the looser checking. 
+Conceptually we have a `JSAny` type. This type only exists in runtime, and does
+not require a representation, since it results from the absense of type
+information. This is discussed later when we look at the type system.
+
+Besides JS Arrays, Dart generic functions and methods can also be called from
+JS. In that case, the reified generic type will usually be omitted. This is
+discussed later when we look at exporting Dart classes to JS.
+
+
+### Null and Undefined
+
+Dart web compilers generally treat these as interchangeable; while they don't
+create `undefined` themselves, it's treated as `== null`. This makes interop
+easier, so it's probably worth keeping. We should also add an `undefined`
+constant to "package:js", for cases where it's necessary to pass it explicitly
+to JS.
+
+
+### Future and JS Promise
+
+JS Promises are very common in web APIs, as many operations are asynchronous.
+These function very similarly to Dart's `Future<T>` interface.
+
+There are several possible answers:
+1. provide an implicit conversion
+2. both types implement the other's interface
+3. have _Future be a JS Promise
+
+Option 3 is not feasible. Option 2 is ideal, but may cause issues in dart2js,
+because they currently assume no JS types implement `Future` (this avoids
+"getInterceptor" overhead). So we probably need to go with Option 1. The
+dart:html library already has a conversion in one direction, and `dartdevc` may
+soon have both directions (to use JS async/await).
+
+If we did want to do the adapter design, here is a rough sketch:
+
+```dart
+@JS('Promise')
+@JSInterfaceDispatch()
+@JSDynamicDispatch() // Note: because existing SDK native types support this.
+class JSPromise<T> implements Future<T> {
+  @JS('then')
+  external JSPromise<R> _then<R>(
+    /*R | Thenable<R>*/Object Function(T) onFulfilled,
+    [/*R | Thenable<R>*/Object Function(Object) onRejected]);
+
+  external factory JSPromise.resolve(/*R | Thenable<R>*/Object value);
+
+  Future<R> then<R>(FutureOr<R> onValue(T value), {Function onError}) {
+    return _then(
+        Zone.current.bindUnaryCallback(onValue),
+        onError != null
+            // Note: real impl must also support an `onError` callback that 
+            // takes a StackTrace as the second argument.
+            ? Zone.current.bindUnaryCallback(onError as dynamic)
+            : null);
+  }
+  // [...]
+}
+
+class _Future<T> implements Future<T> {
+  // [...]
+
+  // Note: in reality this could be injected by the compiler on any class
+  // implementing Future<T> if we want them to be Promise-like.
+  @JSExport('then')
+  JSPromise<R> _jsThen<R>(
+    /*R | Thenable<R>*/Object Function(T) onFulfilled,
+    [/*R | Thenable<R>*/Object Function(Object) onRejected]) {
+
+    Future<R> f = then((value) => JSPromise.resolve(onFulfilled(value)),
+        onError: onRejected != null
+            ? (error) => JSPromise.resolve(onRejected(error))
+            : null);
+    // This conversion is not necessary if we only want to implement Thenable.
+    return JSPromise.resolve(f);
+  }
+}
+```
+
+
+### Iterable<T> and JS Iterable
+
+All Dart `Iterable<T>` classes should implement `[Symbol.iterator]`, which
+allows them to be used in JS `for-of` loops.
+
+Converting from a JS iterable to a Dart Iterable requires a conversion
+(either implicit or explicit).
+
+Avoiding a conversion is probably not ideal. We'd need `Iterable<T>` methods
+on any JS object that contains `[Symbol.iterator]`. This requires compilers to
+place `Iterable<T>` members on Object.prototype, or handle this at the
+interceptor level. The current theory is that not many JS APIs return
+iterables (Arrays are much more common). A wrapper-based conversion, either
+implicit or explcit, should be enought to handle this.
+
+
+### Stream<T> and JS Async Iterable
+
+The EcmaScript draft contains a new feature [for-await-of loops](https://tc39.github.io/ecma262/#sec-for-in-and-for-of-statements)
+and `Symbol.asyncIterator` (see also [MDN for-await-of](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Statements/for-await...of)).
+Once JS has that, `Stream<T>` could work similarly to `Future<T>`.
+
+
+### Stream<T> and Callbacks
+
+These will require a conversion in either direction. However we can provide
+helpers to make this easy. Consider this example from Firebase:
+
+```dart
+class Auth extends JsObjectWrapper<AuthJsImpl> {
+  // [...]
+  Func0 _onAuthUnsubscribe;
+  StreamController<User> _changeController;
+
+  Stream<User> get onAuthStateChanged {
+    if (_changeController == null) {
+      var nextWrapper = allowInterop((firebase_interop.UserJsImpl user) {
+        _changeController.add(User.getInstance(user));
+      });
+
+      var errorWrapper = allowInterop((e) => _changeController.addError(e));
+
+      void startListen() {
+        assert(_onAuthUnsubscribe == null);
+        _onAuthUnsubscribe =
+            jsObject.onAuthStateChanged(nextWrapper, errorWrapper);
+      }
+
+      void stopListen() {
+        _onAuthUnsubscribe();
+        _onAuthUnsubscribe = null;
+      }
+
+      _changeController = StreamController<User>.broadcast(
+          onListen: startListen, onCancel: stopListen, sync: true);
+    }
+    return _changeController.stream;
+  }
+}
+
+// [in interop/auth_iterop.dart]
+@JS('Auth')
+class AuthJsImpl {
+  // [...]
+  external Func0 onAuthStateChanged(nextOrObserver,
+      [Func1 opt_error, Func0 opt_completed]);
+}
+```
+
+With the right helpers and elimination of wrappers, this becomes:
+
+```dart
+@JS()
+class Auth {
+  @sealed
+  Stream<User> _changeStream;
+
+  @JS('onAuthStateChanged')
+  external Func0 _onAuthStateChanged(Func1<User, void> nextOrObserver,
+      [Func1 opt_error, Func0 opt_completed]);
+
+  @sealed
+  Stream<User> get onAuthStateChanged =>
+      _changeStream ??= CreateStream(_onAuthStateChanged);
+}
+
+// Note: package:js will defined some helpers like this.
+// More research is needed to find all of the the common patterns.
+static Stream<T> CreateStream<T>(
+    @JS() Func0 Function(Func1<T, void> nextOrObserver, [Func1 opt_error])
+        subscribeToEvent) {
+  Func0 unsubscribe;
+  StreamController<T> controller;
+  controller = StreamController.broadcast(
+      onListen: () {
+        // Because `subscribeToEvent` is annotated with `@JS()`, `allowInterop`
+        // will be automatically handled on these callbacks.
+        unsubscribe = subscribeToEvent(controller.add, controller.addError);
+      },
+      onCancel: unsubscribe,
+      sync: true);
+  return controller.stream;
+}
+```
+
+
+### DateTime and JS Date
+
+Similar to Future/Promise, we can investigate and determine which of these is
+best:
+- implement DateTime on top of JS Date
+- have them implement each other's interfaces
+- provide an implicit conversion
+
+
+### Map/Set and JS Map/Set
+
+At the very least, we'll provide `JSMap<K, V>` and `JSSet<T>` types in
+"package:js" that will implement the corresponding Dart interfaces and also be
+wrapperless JS Maps/Sets.
+
+Both web compilers already use (or have prototyped use of) ES6 Map/Set under
+some circumstances, such as identity Maps/Sets. So it may be possible to have
+the objects returned by `HashMap.identity()` and `HashSet.identity()` simply be
+JS Map/Set respectively. That would be a nice feature, but is not necessary
+to provide good interop with these types.
+
+Declaring a JS API as returning a Dart Map will be a hint, because it will
+probably not work the way the developer expects (if they are expecting a JS
+object to be interpreted as a Map). Instead they can:
+- use `JSMap<K, V>` if they intended the JS Map class.
+- use `JSObjectMap<K, V>` if the return value is a JS object. It's a normal Dart
+  class that implements Map and is backed by the JS Object. This indicates a
+  wrapping conversion.
+- use `@JSConvert()` to provide a custom conversion to Map
+- use some other JS class type, which declares the properties that the map
+  contains. Useful when a JS Object is returned, and the data is structured.
+
+Open question: are the generic type arguments to JSMap/JSSet reified if
+allocated in Dart? I think they should be, for consistency with `List<T>`.
+Similar to `List<T>` however, a `Map` allocated in JS could be cast to
+`JSMap<K, V>` for any types `K` and `V` that subtype `JSAny`.
+
+
+### Maps and JS Objects
+
+Converting arbitrary Dart maps to JS Objects is probably not feasible, for
+reasons discussed in "Data Type Interoperability". However we can provide
+a conversion: 
+
+```dart
+  external factory RecaptchaVerifier(container,
+      [@JSConvert(jsify) Map<String, Object> parameters, App app]);
+```
+
+The `jsify` function is declared by Firebase, and does a deep conversion based
+on the specific types Firebase APIs use. However most of that will no longer be
+necessary, so we might be able to get away with:
+
+```dart
+  external factory RecaptchaVerifier(container,
+      [@MapToJSObject() Map<String, Object> parameters, App app]);
+```
+
+This uses a built-in shallow conversion from a Dart Map to a JS object.
+
+
+#### Wrapper-based JSObjectMap
+
+To make it easier to work with JS objects via indexing, we could provide several
+classes in "package:js" to help:
+
+```dart
+@JS()
+@anonymous
+class JSIndexable<K extends Object, V extends Object> {
+  external V operator [](K key);
+  external void operator []=(K key, Object value);
+
+  Map<K2, V2> toMap<K2, V2>() => JSObjectMap(this);
+}
+
+/// Wraps a JS Object in a Dart Map.
+class JSObjectMap<K, V> with MapMixin<K, V> implements Map<K, V> {
+  final JSIndexable object;
+
+  JSObjectMap([Object object])
+      : object = object as JSIndexable ?? JSIndexable();
+
+  factory JSObjectMap.from(Map other) => JSObjectMap<K, V>()..addAll(other);
+  factory JSObjectMap.of(Map<K, V> other) = JSObjectMap.from;
+  factory JSObjectMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
+      JSObjectMap<K, V>()..addEntries(entries);
+
+  bool containsKey(Object key) => Reflect.has(object, key);
+  V operator [](Object key) => object[key];
+  void operator []=(Object key, value) {
+    object[key] = value;
+  }
+  List<K> get keys => Reflect.ownKeys(object) as List<K>;
+  V remove(Object key) {
+    if (Reflect.has(object, key)) {
+      var result = object[key];
+      Reflect.deleteProperty(object, key);
+      return result;
+    }
+    return null;
+  }
+  void clear() {
+    for (var key in Reflect.ownKeys(object)) {
+      Reflect.deleteProperty(object, key);
+    }
+  }
+}
+```
+
+Here `JSObjectMap` works like a normal Dart class, but it's easy to get the
+raw JS object from it. Meanwhile any JS object can be cast to `JSIndexable` to
+provide access to the index operators and the `toMap()` function.
+
+
+#### Autoboxing JSObjectMap
+
+
+*NOTE*: we probably won't want/need this, but I wanted to mention it as a
+possible optoon. It provides a means of implementing Dart interfaces from JS
+classes, that is reasonably friendly to optimizations.
+
+An alternative design for `JSObjectMap` is to work similarly to `JSIndexable`.
+This provides a Map-like view of an arbitrary JS object. Then the question
+becomes: how do we cast our type to a `Map<K, V>`? Autoboxing would allow us to
+do that.
+
+Here's a rough sketch:
+
+```dart
+@JS()
+@JSAutobox()
+class JSObjectMap<K, V> extends MapBase<K, V> {
+  factory JSObjectMap() => _create(null);
+  factory JSObjectMap.from(Map other) => _create<K, V>(null)..addAll(other);
+  factory JSObjectMap.of(Map<K, V> other) = JSObjectMap.from;
+  factory JSObjectMap.fromEntries(Iterable<MapEntry<K, V>> entries) =>
+      _create<K, V>(null)..addEntries(entries);
+
+  @JS('create')
+  external static JSObjectMap<K2, V2> _create<K2, V2>(Object proto);
+
+  external V operator [](Object key);
+  external void operator []=(Object key, Object value);
+  
+  bool containsKey(Object key) => Reflect.has(this, key);
+  List<K> get keys => Reflect.ownKeys(this) as List<K>;
+
+  V remove(Object key) {
+    if (Reflect.has(this, key)) {
+      var result = this[key];
+      Reflect.deleteProperty(this, key);
+      return result;
+    }
+    return null;
+  }
+
+  void clear() {
+    for (var key in Reflect.ownKeys(this)) {
+      Reflect.deleteProperty(this, key);
+    }
+  }
+}
+```
+
+Because this type uses `@JSAutobox()`, the JS object will be automatically
+boxed when cast to any Dart interface that it implements (except for dart:core
+Object). This reduces the boilerplate that might otherwise be required.
+
+The benefit of this approach is that any JS object can be freely cast to
+`JSObjectMap`, providing efficient access using Map-like APIs. For example,
+let's revist our `UserInfo.toJson()` example:
+
+```dart
+@JS()
+@anonymous
+class UserInfo {
+  // [...]
+  /// Returns a JSON-serializable representation of this object.
+  @JS('toJSON')
+  external JSObjectMap<String, dynamic> toJson();
+}
+
+// [code snippet from auth_test.dart]
+
+  test('toJson()', () async {
+    // [...]
+    var userMap = userCredential.user.toJson();
+    expect(userMap, isNotNull);
+    expect(userMap as Map, isNotEmpty); // [note: `as Map` was added]
+    expect(userMap["displayName"], "Other User");
+    expect(userMap["photoURL"], "http://google.com");
+    // [...]
+  });
+```
+
+Consider the line `expect(userMap as Map, isNotEmpty)` in this example.
+The `as Map` is necessary to trigger boxing, so the `isNotEmpty` matcher will
+work.
+
+Autoboxing would be a neat way to provide support for implementing Dart
+interfaces from JS. Autoboxing has proven useful in other languages for native
+interop. It may be useful for advanced JS interop scenarios, such as providing
+a dart:html-like API without JS dynamic/interface dispatch.
+
+
+## Less Static Interop
+
+### Virtual Dispatch
+
+In many cases JS interop can take advantage of virtual dispatch, even with
+`@sealed`, because the JS method it calls will dispatch with normal JS rules
+(i.e. lookup the property on the prototype chain). `@sealed` procludes overrides
+of itself with another Dart member, however.
+
+We support virtual Dart methods on JS types, with a bit more work. This doesn't
+compromise the model very much, but it does add additional dispatch cost.
+Implementing interfaces and dynamic dispatch would still be restricted.
+
+
+### Interface and Dynamic dispatch
+
+In the future, we may want to provide something like `@JSInterfaceDispatch()` or
+`@JSDynamicDispatch()`, that preserves RTTI and enables interface/dynamic
+dispatch. Our compilers already support this, as they use it themselves for core
+types in the SDK, and for the HTML libraries.
+
+There are several issues with exposing this:
+- extensions would now have to be globally unique for a given JS prototype.
+- this requires compile time checking (dart2js) or runtime checking (dartdevc).
+- it's possible to subvert compile time checking accidentally (if the same JS 
+  prototype is exposed with two different names).
+- we'd need to standardize the annotations between the compilers and ensure
+  they have the same semantics.
+
+Scoped extension method approaches for dynamic languages may help for the naming
+conflicts (e.g.
+[as discussed in this paper](https://arxiv.org/pdf/1708.01679.pdf)),
+but those have performance/complexity/usability tradeoffs.
+
+Many users have requested flags to disable dynamic dispatch, so this may not be
+the direction we need go. Implementing interfaces can be useful however.
+(The "autoboxing" approach discussed previously may be a possible compromise.)
+
+
+### JS Proxy
+
+One question that comes up occassionally is how to use JS Proxy from Dart.
+We can expose JSProxy from "package:js":
+
+```dart
+@JS('Proxy')
+class JSProxy {
+  external factory JSProxy(Object target, JSProxyHadler handler);
+}
+
+@JS()
+@anonymous
+abstract class JSProxyHandler {
+  // Note: these are defined as field to allow only a subset of them to be
+  // implemented
+  @JS()
+  Object Function(Object target) getPrototypeOf;
+
+  @JS()
+  Object Function(Object target, Object proto) setPrototypeOf;
+
+  // [...]
+
+  @JS()
+  bool Function(Object target, Object key) has;
+
+  @JS()
+  Object Function(Object target, Object key) get;
+
+  @JS()
+  Object Function(Object target, Object key, Object value) set;
+
+  @JS()
+  bool Function(Object target, Object key) deleteProperty;
+
+  external factory JSProxyHandler({
+      this.getPrototypeOf,
+      this.setPrototypeOf,
+      this.get,
+      this.set,
+      this.has,
+      this.deleteProperty /* [...] */});
+}
+```
+
+It's possible to implement a proxy handler that forwards to Dart's
+noSuchMethod, or the reverse, if someone wanted to do that.
+
+(It's also possible to have a noSuchMethod that uses JS Reflect and Object APIs
+to access the JS object. It's not necessary though, because `@JS()` classes are
+essentially a more optimized form of that.)
+
+
+### JS Reflection
+
+JS Reflection APIs are useful for low level support, and these can be provided
+by "package:js":
+
+```dart
+@JS('Reflect')
+class JSReflect {
+  external static Object apply(target, thisArgument, argumentsList);
+  external static Object construct(target, argumentsList, [newTarget]);
+  external static bool defineProperty(
+      target, propertyKey, PropertyDescriptor attributes);
+  external static bool deleteProperty(target, propertyKey, [receiver]);
+  external static Object get(target, propertyKey);
+  external static PropertyDescriptor getOwnPropertyDescriptor(
+      target, propertyKey);
+  external static Object getPrototypeOf(target);
+  external static bool has(target, propertyKey);
+  external static bool isExtensible(target);
+  external static List<Object> ownKeys(target);
+  external static void preventExtensions();
+  external static set(target, propertyKey, value, [receiver]);
+  external static setPrototypeOf(target, prototype);
+
+  static bool hasOwnProperty(target, propertyKey) {
+    // Note: could also be implemented using `getOwnPropertyDescriptor`
+    return _JSObject.prototype.hasOwnProperty(target, propertyKey);
+  }
+
+  static Object getOwnProperty(target, propertyKey) {
+    var desc = getOwnPropertyDescriptor(target, propertyKey);
+    if (desc == null) return null;
+    if (desc.get != null) return desc.get(target);
+    return desc.value;
+  }
+}
+
+@JS('Object')
+abstract class _JSObject {
+  external static _JSObjectPrototype prototype;
+}
+
+@JS()
+@anonymous
+abstract class _JSObjectPrototype {
+  external static bool hasOwnProperty(@JSThis() target, propertyKey);
+}
+
+@JS()
+@anonymous
+class PropertyDescriptor {
+  Object value;
+  bool writable;
+  bool configurable;
+  bool enumerable;
+  Object Function(@JSThis() Object) get;
+  void Function(@JSThis() Object, Object) set;
+}
+```
+
+
+## Exporting Dart to JS
+
+Dart functions and accessors can be exported to JS with `@JSExport`. A compiler
+must provide a version of the function that is callable via the JS interop
+calling conventions described earlier, and ensure that version of the function
+is used when it is passed to JavaScript. (It may have other versions of the
+function that use optimized, dart-specific calling conventions.)
+
+
+### Exporting classes and libraries
+
+This will use `@JSExport` similar to top-level functions/accessors.
+
+TODO: more details here
+
+### Inheritance between Dart and JS
+
+Conceptually extending a JS class from Dart is similar to adding methods,
+because `super` calls are statically dispatched. The tricky part is what to do
+with constructors. JS constructors are normally written as `external factory`
+which precludes extending them. Also there are some notable differences in
+field initialization+super constructor call order between Dart and JS.
+
+(JS requires super before initializing fields, Dart requires super after
+initializing final fields. Dart's approach is nice because it prevents
+virtual methods from observing uninitialized state. But for interop, the problem
+is that the two orders are incompatible.)
+
+We may be able to provide a method that creates your class:
+
+```dart
+class MyDartClass extends TheirJSClass {
+  final int x = 1;
+  int y, z;
+  factory MyDartClass(int y, int z) {
+    // super constructpr parameters passed here?
+    var self = createJS<MyDartClass>(); 
+    self.y = y;
+    self.z = z;
+    return self;
+  }
+  // ...
+}
+```
+
+It's not the most satisfying solution, but it seems like a relatively easy way
+to support this.
+
+TODO: extending a Dart class from JS
+
+
+### Interop with JS Modules
+
+We'll need a way to declare a JS interop library corresponds to a JS module.
+This could be done on the library tag:
+
+```dart
+@JSImport('goog.editor', moduleFormat: 'closure')
+library goog.editor;
+```
+
+The compiler can then generate the appropriate import, instead of a global
+reference. This will need to be coordinated with the overall build and server
+system, however, to ensure the JS module is available to the module loader
+(requirejs, ES6 imports, etc).
+
+Typically the module format will be assumed to be passed in globally to the
+compiler, as there is generally one standardized module format, so that argument
+won't be present. (Closure library is illustrated here as it can be used in
+addition to other formats, it may be useful to tell the compiler "this module
+is definitely a closure namespace, import it as such".)
+
+
+### Exposing JS Methods as Getters
+
+One common pattern that comes up is converting "getX" methods into "get X"
+getters. We could add `@JSMethod` syntactic sugar to simplify that.
+Consider this prior example of a Google Maps API:
+
+```dart
+  LatLng get center => _getCenter();
+  LatLng get northEast => _getNorthEast();
+  LatLng get southWest => _getSouthWest();
+  bool get isEmpty => _isEmpty();
+
+  @JS('getCenter')
+  external LatLng _getCenter();
+  @JS('getNorthEast')
+  external LatLng _getNorthEast();
+  @JS('getSouthWest')
+  external LatLng _getSouthWest();
+  @JS('isEmpty')
+  external bool _isEmpty();
+```
+
+It could be written as:
+
+```dart
+  @JSMethod('getCenter')
+  external LatLng get center;
+
+  @JSMethod('getNorthEast')
+  external LatLng get northEast;
+
+  @JSMethod('getSouthWest')
+  external LatLng get southWest;
+
+  @JSMethod('isEmpty')
+  external bool get isEmpty;
+```
+
+## JS Types in the Dart Type System
+
+As discussed earlier, at runtime the absence of reified type information will be
+tracked with a `JSAny` type. `JSAny` can contain types that may originate from
+JS, and it only exists at run time. Here are some examples:
+
+```dart
+import 'package:firebase/firebase.dart' show App, Database;
+import 'package:firebase/firebase.dart' as firebase;
+main() {
+  List apps = firebase.apps;
+  apps is List<Object>      // true: Object can hold JS types
+  apps is List<int>         // true: `int` could be from JS
+  apps is List<List>        // true: `List` could be from JS
+  apps is List<Database>    // true: could be a list of any JS interop types
+  apps is List<MyDartClass> // false: can't be a Dart class
+  apps is List<Stopwatch>   // false: can't be a Dart class like Stopwatch
+}
+```
+
+We'll probably want to provide access to JS `typeof` and `instanceof` as library
+functions in "package:js".
+
+The proposed typing rules for JSAny allow it assigned to/from these types:
+- primitives: Null | bool | int | num | double | String
+- JS interop classes (`@JS()`)
+- Dart classes exported to JS (`@JSExport()`)
+- `List<JSAny>`
+- other "native" SDK types
+- functions (restrict to JSAny param/return types?)
+
+This type will not exist in the static type system. The hope is that these
+restrictions keep the unsoundness restricted to objects allocated from JS, and
+to types that are likely to be used by existing JS APIs. By excluding Dart
+classes, we're able to catch things like `List<JSAny>` assigned to
+`List<MyDartClass>`, which is unlikely to work.
+
+Open question: should preserve reified JSAny if that type parameter is used to
+construct other types? For example:
+
+```dart
+@JS()
+external List foo();
+bar() {
+  var list = foo();
+  var set = list.toSet() as Set<int>; // does this work?
+  // ...
+}
+```
+
+
+## Implementation Roadmap
+
+Here's a rough breakdown of the features into different categories.
+Details subject to change. The items are not in any particular order.
+
+Required features (P0):
+- static dispatch (with rename support)
+- static type checking rules (warnings/errors for incorrect usage)
+- runtime type checking rules
+- conversions for builtin types:
+  - Functions
+  - Dart Map to/from JS Object
+  - Future/Promise
+- calling conventions for optional arguments, "this"
+- exporting top-level functions, accessors to JS
+
+Important features (P1):
+- user defined conversions
+- conversions for types (e.g. DateTime, Iterables)
+- named arguments
+- exporting classes/members to JS
+- package:js helper library
+  - common conversion functions, e.g. jsify/dartify
+  - predefined interop for core JS types like Set/Map
+- extension fields
+
+Nice to have features (P2):
+- helpers for common callback-to-stream patterns
+- other helpers like `@JSMethod`
+- autoboxing to implement Dart interfaces(?)
+
+Features for building "package:html" (P2?):
+- virtual dispatch for JS classes
+- subtyping Dart classes from JS
+- subtyping JS classes from Dart
+- interface dispatch for JS classes (useful for migrating to package:html)
+- dynamic dispatch for JS classes (useful for migrating to package:html)
+
+
+## Compatibility and Evolution
+
+Most of the features described here are backwards compatible, relative to the
+set of JS interop supported by both web compilers.
+
+One question that came up is interfaces: currently JS interop classes can be
+implemented by Dart classes (although this may lead to inconsistent behavior
+between the compilers). If `@sealed` Dart members are added to a JS interop
+class, then it won't be legal to implement that as an interface. But this is a
+new feature, so it's only "breaking" in the sense that adding `@sealed` members
+is a breaking change for the package API. (Technically: adding *any* public
+member to a Dart class is a breaking change, for this reason. In practice many
+types are not intended to be used as interfaces, so they don't treat new members
+as breaking).
+
+If we discover something that is too backwards incompatible, we can add new
+annotations and leave the current behavior for the existing ones. Or we can
+bump the major version on "package:js". There's a lot of possibilities.
+
+
+## FAQ
+
+### Q: How does JSON work?
+
+A: If the JSON is relatively typed, then it can be 
+
+
+### Q: Would new Dart language features help?
+
+A: Yes! All of these features would be helpful:
+- extension methods/members
+- extension types
+- implicit conversions
+- autoboxing
+- non-null
+- generalized typedefs
+- `external` on fields (sugar for external getter/setter)
+
+In the meantime, this proposal provides a way to improve interop, and is
+intended to be compatible with those features.
+
+
+### Q: Can dart2js and dartdevc share implementation for JS interop?
+
+A: Probably, especially for the static features.
+
+If both compilers are exclusively using Kernel, much of this can
+be implemented as a Kernel transform. The static checking can also be done in
+a shared way.
+
+Dynamic dispatch, calling conventions, and runtime type checks, and native SDK
+types are different between the two compilers, so those details would require
+separete work.
+
+
+### Q: If a JS API returns "Object" does this break dart2js tree shaking?
+
+A: It does not. Dart classes can be tree-shaken, unless they're explicitly
+exported to JS. Static dispatch members can be tree shaken. Static JS Interop
+types, by design, do not require any runtime type information (RTTI).
+Opt-in features like interface or dynamic dispatch will cause more RTTI to be
+retained.
+
+This question may be referring to "dart:html". It supports dynamic dispatch, and
+this causes RTTI to be retained, unless great care is taken on the part
+of dart:html authors (to carefully annotate return types, and avoid untyped
+results) and by developers (to carefully avoid dynamic calls that use names in
+"dart:html", and to avoid JS interop features that could return HTML elements).
+
+We may be able to find a better solution, such a providing new "package:html"
+bindings that are mostly static (and using interface/dynamic dispatch sparingly,
+in places where it's really needed).
+
+
+### Q: Could we use dynamic interop instead?
+
+A: It's certainly possible to imagine interop that works "like JS"
+(example from Closure Library's
+[goog.editor Example](https://github.com/google/closure-library/blob/master/closure/goog/demos/editor/editor.html#L84)):
+
+```dart
+// Hypothetical dynamic interop
+dynamic goog = window.goog;
+dynamic myField = goog.editor.Field.new('editMe');
+
+// Create and register all of the editing plugins you want to use.
+myField.registerPlugin(goog.editor.plugins.BasicTextFormatter.new());
+```
+
+The problem is it'll run into the same issues around data type conversions, but
+it won't be able to address them without wrapper classes. As illustrated by the
+".new" it will never be as simple as copying and pasting JS code, and there
+won't be any tooling to help.
+
+What we may want to do is provide a way to write small chunk of JS code (in a
+Dart file), similar to GWT. But that shouldn't be used much, with the
+improvements in this proposal to calling conventions and easy ways to access
+properties on JS objects.
diff --git a/pkg/kernel/bin/transform.dart b/pkg/kernel/bin/transform.dart
index 12a3e91..3fe69da 100755
--- a/pkg/kernel/bin/transform.dart
+++ b/pkg/kernel/bin/transform.dart
@@ -37,6 +37,7 @@
       negatable: false,
       help: 'Be verbose (e.g. prints transformed main library).',
       defaultsTo: false)
+  ..addMultiOption('define', abbr: 'D', splitCommas: false)
   ..addMultiOption('embedder-entry-points-manifest',
       help: 'A path to a file describing entrypoints '
           '(lines of the form `<library>,<class>,<member>`).')
@@ -69,6 +70,21 @@
   var format = options['format'];
   var verbose = options['verbose'];
 
+  Map<String, String> defines = <String, String>{};
+  for (String define in options['define']) {
+    int index = define.indexOf('=');
+    String name;
+    String expression;
+    if (index != -1) {
+      name = define.substring(0, index);
+      expression = define.substring(index + 1);
+    } else {
+      name = define;
+      expression = define;
+    }
+    defines[name] = expression;
+  }
+
   if (output == null) {
     output = '${input.substring(0, input.lastIndexOf('.'))}.transformed.dill';
   }
@@ -94,13 +110,9 @@
       component = coq.transformComponent(coreTypes, component);
       break;
     case 'constants':
-      // We use the -D defines supplied to this VM instead of explicitly using a
-      // constructed map of constants.
-      final Map<String, String> defines = null;
-      final VmConstantsBackend backend =
-          new VmConstantsBackend(defines, coreTypes);
+      final VmConstantsBackend backend = new VmConstantsBackend(coreTypes);
       component = constants.transformComponent(
-          component, backend, const constants.SimpleErrorReporter());
+          component, backend, defines, const constants.SimpleErrorReporter());
       break;
     case 'treeshake':
       component = treeshaker.transformComponent(coreTypes, hierarchy, component,
diff --git a/pkg/kernel/binary.md b/pkg/kernel/binary.md
index 9456ebe..8ea99dc 100644
--- a/pkg/kernel/binary.md
+++ b/pkg/kernel/binary.md
@@ -221,7 +221,7 @@
 }
 
 type Library {
-  Byte flags (isExternal);
+  Byte flags (isExternal, isSynthetic);
   CanonicalNameReference canonicalName;
   StringReference name;
   // An absolute path URI to the .dart file from which the library was created.
diff --git a/pkg/kernel/lib/ast.dart b/pkg/kernel/lib/ast.dart
index 5f6abdf..d738ec5 100644
--- a/pkg/kernel/lib/ast.dart
+++ b/pkg/kernel/lib/ast.dart
@@ -155,6 +155,8 @@
 
   Component get enclosingComponent => parent?.enclosingComponent;
 
+  Library get enclosingLibrary => parent?.enclosingLibrary;
+
   /// Returns the best known source location of the given AST node, or `null` if
   /// the node is orphaned.
   ///
@@ -278,6 +280,11 @@
   /// The URI of the source file this library was loaded from.
   Uri fileUri;
 
+  static const int ExternalFlag = 1 << 0;
+  static const int SyntheticFlag = 1 << 1;
+
+  int flags = 0;
+
   /// If true, the library is part of another build unit and its contents
   /// are only partially loaded.
   ///
@@ -287,7 +294,17 @@
   ///
   /// If the library is non-external, then its classes are at [ClassLevel.Body]
   /// and all members are loaded.
-  bool isExternal;
+  bool get isExternal => (flags & ExternalFlag) != 0;
+  void set isExternal(bool value) {
+    flags = value ? (flags | ExternalFlag) : (flags & ~ExternalFlag);
+  }
+
+  /// If true, the library is synthetic, for instance library that doesn't
+  /// represents an actual file and is created as the result of error recovery.
+  bool get isSynthetic => flags & SyntheticFlag != 0;
+  void set isSynthetic(bool value) {
+    flags = value ? (flags | SyntheticFlag) : (flags & ~SyntheticFlag);
+  }
 
   String name;
 
@@ -318,7 +335,7 @@
 
   Library(this.importUri,
       {this.name,
-      this.isExternal: false,
+      bool isExternal: false,
       List<Expression> annotations,
       List<LibraryDependency> dependencies,
       List<LibraryPart> parts,
@@ -336,6 +353,7 @@
         this.procedures = procedures ?? <Procedure>[],
         this.fields = fields ?? <Field>[],
         super(reference) {
+    this.isExternal = isExternal;
     setParents(this.dependencies, this);
     setParents(this.parts, this);
     setParents(this.typedefs, this);
@@ -450,6 +468,8 @@
   Location _getLocationInEnclosingFile(int offset) {
     return _getLocationInComponent(enclosingComponent, fileUri, offset);
   }
+
+  Library get enclosingLibraray => this;
 }
 
 /// An import or export declaration in a library.
diff --git a/pkg/kernel/lib/binary/ast_from_binary.dart b/pkg/kernel/lib/binary/ast_from_binary.dart
index 89e2183..cc11d87 100644
--- a/pkg/kernel/lib/binary/ast_from_binary.dart
+++ b/pkg/kernel/lib/binary/ast_from_binary.dart
@@ -785,7 +785,7 @@
     _byteOffset = savedByteOffset;
 
     int flags = readByte();
-    bool isExternal = (flags & 0x1) != 0;
+    bool isExternal = (flags & Library.ExternalFlag) != 0;
     _isReadingLibraryImplementation = !isExternal;
     var canonicalName = readCanonicalNameReference();
     Reference reference = canonicalName.getReference();
@@ -805,7 +805,7 @@
     List<String> problemsAsJson = readListOfStrings();
 
     if (shouldWriteData) {
-      library.isExternal = isExternal;
+      library.flags = flags;
       library.name = name;
       library.fileUri = fileUri;
       library.problemsAsJson = problemsAsJson;
diff --git a/pkg/kernel/lib/binary/ast_to_binary.dart b/pkg/kernel/lib/binary/ast_to_binary.dart
index 61eae52..1b945ba 100644
--- a/pkg/kernel/lib/binary/ast_to_binary.dart
+++ b/pkg/kernel/lib/binary/ast_to_binary.dart
@@ -883,7 +883,7 @@
   void visitLibrary(Library node) {
     insideExternalLibrary = node.isExternal;
     libraryOffsets.add(getBufferOffset());
-    writeByte(insideExternalLibrary ? 1 : 0);
+    writeByte(node.flags);
     writeNonNullCanonicalNameReference(getCanonicalNameOfLibrary(node));
     writeStringReference(node.name ?? '');
     writeUriReference(node.fileUri);
diff --git a/pkg/kernel/lib/class_hierarchy.dart b/pkg/kernel/lib/class_hierarchy.dart
index 9fa31ec..51f0730 100644
--- a/pkg/kernel/lib/class_hierarchy.dart
+++ b/pkg/kernel/lib/class_hierarchy.dart
@@ -34,6 +34,8 @@
   void set onAmbiguousSupertypes(
       HandleAmbiguousSupertypes onAmbiguousSupertypes);
 
+  void set mixinInferrer(MixinInferrer mixinInferrer);
+
   /// Given the [unordered] classes, return them in such order that classes
   /// occur after their superclasses.  If some superclasses are not in
   /// [unordered], they are not included.
diff --git a/pkg/kernel/lib/core_types.dart b/pkg/kernel/lib/core_types.dart
index 504eea5..ddc4aac 100644
--- a/pkg/kernel/lib/core_types.dart
+++ b/pkg/kernel/lib/core_types.dart
@@ -33,6 +33,11 @@
     'dart:async': [
       'Future',
       'Stream',
+    ],
+    'dart:ffi': [
+      'DynamicLibrary',
+      'Pointer',
+      'Struct',
     ]
   };
 
@@ -93,10 +98,97 @@
   Class _pragmaClass;
   Field _pragmaName;
   Field _pragmaOptions;
+  Constructor _pragmaConstructor;
+
+  Library _ffiLibrary;
+  Class _ffiPointerClass;
+  Procedure _ffiPointerLoadProcedure;
+  Procedure _ffiPointerStoreProcedure;
+  Procedure _ffiPointerCastProcedure;
+  Procedure _ffiPointerOffsetByProcedure;
+  Procedure _ffiPointerAsFunctionProcedure;
+  Field _ffiStructField;
+  Class _ffiDynamicLibraryClass;
+  Procedure _ffiDynamicLibraryLookupFunctionProcedure;
+  Procedure _ffiAllocateProcedure;
+  Procedure _ffiSizeOfProcedure;
+  Procedure _ffiFromFunctionProcedure;
+  Class _ffiNativeFunctionClass;
 
   CoreTypes(Component component)
       : index = new LibraryIndex.coreLibraries(component);
 
+  Library get ffiLibrary {
+    return _ffiLibrary ??= index.getLibrary('dart:ffi');
+  }
+
+  Class get ffiPointerClass {
+    return _ffiPointerClass ??= index.getClass('dart:ffi', 'Pointer');
+  }
+
+  Procedure get ffiPointerLoadProcedure {
+    return _ffiPointerLoadProcedure ??=
+        index.getMember('dart:ffi', 'Pointer', 'load');
+  }
+
+  Procedure get ffiPointerStoreProcedure {
+    return _ffiPointerStoreProcedure ??=
+        index.getMember('dart:ffi', 'Pointer', 'store');
+  }
+
+  Procedure get ffiPointerCastProcedure {
+    return _ffiPointerCastProcedure ??=
+        index.getMember('dart:ffi', 'Pointer', 'cast');
+  }
+
+  Procedure get ffiPointerOffsetByProcedure {
+    return _ffiPointerOffsetByProcedure ??=
+        index.getMember('dart:ffi', 'Pointer', 'offsetBy');
+  }
+
+  Procedure get ffiPointerAsFunctionProcedure {
+    return _ffiPointerAsFunctionProcedure ??=
+        index.getMember('dart:ffi', 'Pointer', 'asFunction');
+  }
+
+  Field get ffiStructField {
+    return _ffiStructField ??= index.getTopLevelMember('dart:ffi', 'struct');
+  }
+
+  Class get ffiDynamicLibraryClass {
+    return _ffiDynamicLibraryClass ??=
+        index.getClass('dart:ffi', 'DynamicLibrary');
+  }
+
+  Procedure get ffiDynamicLibraryLookupFunctionProcedure {
+    return _ffiDynamicLibraryLookupFunctionProcedure ??=
+        index.getMember('dart:ffi', 'DynamicLibrary', 'lookupFunction');
+  }
+
+  Procedure get ffiAllocateProcedure {
+    return _ffiAllocateProcedure ??=
+        index.getTopLevelMember('dart:ffi', 'allocate');
+  }
+
+  Procedure get ffiSizeOfProcedure {
+    return _ffiSizeOfProcedure ??=
+        index.getTopLevelMember('dart:ffi', 'sizeOf');
+  }
+
+  Procedure get ffiFromFunctionProcedure {
+    return _ffiFromFunctionProcedure ??=
+        index.getTopLevelMember('dart:ffi', 'fromFunction');
+  }
+
+  Class get ffiNativeFunctionClass {
+    return _ffiNativeFunctionClass ??=
+        index.getClass('dart:ffi', 'NativeFunction');
+  }
+
+  Class ffiNativeTypeClass(String name) {
+    return index.getClass('dart:ffi', name);
+  }
+
   Procedure get asyncErrorWrapperHelperProcedure {
     return _asyncErrorWrapperHelperProcedure ??=
         index.getTopLevelMember('dart:async', '_asyncErrorWrapperHelper');
@@ -312,6 +404,10 @@
     return _pragmaOptions ??= index.getMember('dart:core', 'pragma', 'options');
   }
 
+  Constructor get pragmaConstructor {
+    return _pragmaConstructor ??= index.getMember('dart:core', 'pragma', '_');
+  }
+
   Class get stackTraceClass {
     return _stackTraceClass ??= index.getClass('dart:core', 'StackTrace');
   }
diff --git a/pkg/kernel/lib/src/bounds_checks.dart b/pkg/kernel/lib/src/bounds_checks.dart
index 907865a..a165582 100644
--- a/pkg/kernel/lib/src/bounds_checks.dart
+++ b/pkg/kernel/lib/src/bounds_checks.dart
@@ -454,3 +454,59 @@
   return type is InterfaceType &&
       type.classNode == typeEnvironment.nullType.classNode;
 }
+
+// Value set for variance of a type parameter X in a type term T.
+class Variance {
+  // Used when X does not occur free in T.
+  static const int unrelated = 0;
+
+  // Used when X occurs free in T, and U <: V implies [U/X]T <: [V/X]T.
+  static const int covariant = 1;
+
+  // Used when X occurs free in T, and U <: V implies [V/X]T <: [U/X]T.
+  static const int contravariant = 2;
+
+  // Used when there exists a pair U and V such that U <: V, but [U/X]T and
+  // [V/X]T are incomparable.
+  static const int invariant = 3;
+
+  // Variance values form a lattice where [unrelated] is the top, [invariant]
+  // is the bottom, and [covariant] and [contravariant] are incomparable.
+  // [meet] calculates the meet of two elements of such lattice.  It can be
+  // used, for example, to calculate the variance of a typedef type parameter
+  // if it's encountered on the r.h.s. of the typedef multiple times.
+  static int meet(int a, int b) => a | b;
+
+  // Combines variances of X in T and Y in S into variance of X in [Y/T]S.
+  //
+  // Consider the following examples:
+  //
+  // * variance of X in Function(X) is [contravariant], variance of Y in List<Y>
+  // is [covariant], so variance of X in List<Function(X)> is [contravariant];
+  //
+  // * variance of X in List<X> is [covariant], variance of Y in Function(Y) is
+  // [contravariant], so variance of X in Function(List<X>) is [contravariant];
+  //
+  // * variance of X in Function(X) is [contravariant], variance of Y in
+  // Function(Y) is [contravariant], so variance of X in Function(Function(X))
+  // is [covariant];
+  //
+  // * let the following be declared:
+  //
+  //     typedef F<Z> = Function();
+  //
+  // then variance of X in F<X> is [unrelated], variance of Y in List<Y> is
+  // [covariant], so variance of X in List<F<X>> is [unrelated];
+  //
+  // * let the following be declared:
+  //
+  //     typedef G<Z> = Z Function(Z);
+  //
+  // then variance of X in List<X> is [covariant], variance of Y in G<Y> is
+  // [invariant], so variance of `X` in `G<List<X>>` is [invariant].
+  static int combine(int a, int b) {
+    if (a == unrelated || b == unrelated) return unrelated;
+    if (a == invariant || b == invariant) return invariant;
+    return a == b ? covariant : contravariant;
+  }
+}
diff --git a/pkg/kernel/lib/target/targets.dart b/pkg/kernel/lib/target/targets.dart
index f64802f..a0e9a5b 100644
--- a/pkg/kernel/lib/target/targets.dart
+++ b/pkg/kernel/lib/target/targets.dart
@@ -6,6 +6,7 @@
 import '../ast.dart';
 import '../class_hierarchy.dart';
 import '../core_types.dart';
+import '../transformations/constants.dart' show ConstantsBackend;
 import '../transformations/treeshaker.dart' show ProgramRoot;
 
 final List<String> targetNames = targets.keys.toList();
@@ -195,6 +196,8 @@
 
   Class concreteIntLiteralClass(CoreTypes coreTypes, int value) => null;
   Class concreteStringLiteralClass(CoreTypes coreTypes, String value) => null;
+
+  ConstantsBackend constantsBackend(CoreTypes coreTypes);
 }
 
 class NoneTarget extends Target {
@@ -234,4 +237,8 @@
       bool isTopLevel: false}) {
     return new InvalidExpression(null);
   }
+
+  @override
+  ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
+      new ConstantsBackend();
 }
diff --git a/pkg/kernel/lib/text/ast_to_text.dart b/pkg/kernel/lib/text/ast_to_text.dart
index fe34841..dc0a65e 100644
--- a/pkg/kernel/lib/text/ast_to_text.dart
+++ b/pkg/kernel/lib/text/ast_to_text.dart
@@ -467,6 +467,7 @@
     if (showMetadata) {
       inner.writeMetadata(component);
     }
+    writeComponentProblems(component);
     for (var library in component.libraries) {
       if (library.isExternal) {
         if (!showExternal) {
diff --git a/pkg/kernel/lib/text/text_serializer.dart b/pkg/kernel/lib/text/text_serializer.dart
index 226f774..b3a3595 100644
--- a/pkg/kernel/lib/text/text_serializer.dart
+++ b/pkg/kernel/lib/text/text_serializer.dart
@@ -838,6 +838,7 @@
   String visitDynamicType(DynamicType _) => "dynamic";
   String visitVoidType(VoidType _) => "void";
   String visitBottomType(BottomType _) => "bottom";
+  String visitFunctionType(FunctionType _) => "->";
 }
 
 TextSerializer<InvalidType> invalidTypeSerializer =
@@ -868,6 +869,23 @@
 
 BottomType wrapBottomType(void ignored) => const BottomType();
 
+// TODO(dmitryas):  Also handle typeParameters, nameParameters, and typedefType.
+TextSerializer<FunctionType> functionTypeSerializer = new Wrapped(
+    unwrapFunctionType,
+    wrapFunctionType,
+    Tuple3Serializer(new ListSerializer(dartTypeSerializer), const DartInt(),
+        dartTypeSerializer));
+
+Tuple3<List<DartType>, int, DartType> unwrapFunctionType(FunctionType type) {
+  return new Tuple3(
+      type.positionalParameters, type.requiredParameterCount, type.returnType);
+}
+
+FunctionType wrapFunctionType(Tuple3<List<DartType>, int, DartType> tuple) {
+  return new FunctionType(tuple.first, tuple.third,
+      requiredParameterCount: tuple.second);
+}
+
 Case<DartType> dartTypeSerializer =
     new Case.uninitialized(const DartTypeTagger());
 
@@ -967,11 +985,13 @@
     "dynamic",
     "void",
     "bottom",
+    "->",
   ]);
   dartTypeSerializer.serializers.addAll([
     invalidTypeSerializer,
     dynamicTypeSerializer,
     voidTypeSerializer,
     bottomTypeSerializer,
+    functionTypeSerializer,
   ]);
 }
diff --git a/pkg/kernel/lib/transformations/constants.dart b/pkg/kernel/lib/transformations/constants.dart
index d0799cd..eceaa13 100644
--- a/pkg/kernel/lib/transformations/constants.dart
+++ b/pkg/kernel/lib/transformations/constants.dart
@@ -23,13 +23,12 @@
 import '../ast.dart';
 import '../class_hierarchy.dart';
 import '../core_types.dart';
-import '../external_name.dart' show getExternalName;
 import '../kernel.dart';
 import '../type_algebra.dart';
 import '../type_environment.dart';
 
-Component transformComponent(
-    Component component, ConstantsBackend backend, ErrorReporter errorReporter,
+Component transformComponent(Component component, ConstantsBackend backend,
+    Map<String, String> environmentDefines, ErrorReporter errorReporter,
     {bool keepFields: false,
     bool legacyMode: false,
     bool enableAsserts: false,
@@ -42,8 +41,8 @@
   final typeEnvironment =
       new TypeEnvironment(coreTypes, hierarchy, legacyMode: legacyMode);
 
-  transformLibraries(
-      component.libraries, backend, coreTypes, typeEnvironment, errorReporter,
+  transformLibraries(component.libraries, backend, environmentDefines,
+      typeEnvironment, errorReporter,
       keepFields: keepFields,
       enableAsserts: enableAsserts,
       evaluateAnnotations: evaluateAnnotations);
@@ -53,7 +52,7 @@
 void transformLibraries(
     List<Library> libraries,
     ConstantsBackend backend,
-    CoreTypes coreTypes,
+    Map<String, String> environmentDefines,
     TypeEnvironment typeEnvironment,
     ErrorReporter errorReporter,
     {bool keepFields: false,
@@ -62,10 +61,10 @@
     bool enableAsserts: false}) {
   final ConstantsTransformer constantsTransformer = new ConstantsTransformer(
       backend,
+      environmentDefines,
       keepFields,
       keepVariables,
       evaluateAnnotations,
-      coreTypes,
       typeEnvironment,
       enableAsserts,
       errorReporter);
@@ -76,7 +75,6 @@
 
 class ConstantsTransformer extends Transformer {
   final ConstantEvaluator constantEvaluator;
-  final CoreTypes coreTypes;
   final TypeEnvironment typeEnvironment;
 
   /// Whether to preserve constant [Field]s.  All use-sites will be rewritten.
@@ -86,15 +84,15 @@
 
   ConstantsTransformer(
       ConstantsBackend backend,
+      Map<String, String> environmentDefines,
       this.keepFields,
       this.keepVariables,
       this.evaluateAnnotations,
-      this.coreTypes,
       this.typeEnvironment,
       bool enableAsserts,
       ErrorReporter errorReporter)
-      : constantEvaluator = new ConstantEvaluator(
-            backend, typeEnvironment, coreTypes, enableAsserts, errorReporter);
+      : constantEvaluator = new ConstantEvaluator(backend, environmentDefines,
+            typeEnvironment, enableAsserts, errorReporter);
 
   // Transform the library/class members:
 
@@ -377,6 +375,7 @@
 
 class ConstantEvaluator extends RecursiveVisitor {
   final ConstantsBackend backend;
+  Map<String, String> environmentDefines;
   final CoreTypes coreTypes;
   final TypeEnvironment typeEnvironment;
   final bool enableAsserts;
@@ -396,10 +395,12 @@
   InstanceBuilder instanceBuilder;
   EvaluationEnvironment env;
 
-  ConstantEvaluator(this.backend, this.typeEnvironment, this.coreTypes,
+  ConstantEvaluator(this.backend, this.environmentDefines, this.typeEnvironment,
       this.enableAsserts, this.errorReporter)
-      : canonicalizationCache = <Constant, Constant>{},
-        nodeCache = <Node, Constant>{};
+      : coreTypes = typeEnvironment.coreTypes,
+        canonicalizationCache = <Constant, Constant>{},
+        nodeCache = <Node, Constant>{},
+        env = new EvaluationEnvironment();
 
   /// Evaluates [node] and possibly cache the evaluation result.
   Constant evaluate(Expression node) {
@@ -506,8 +507,7 @@
       entries[i] = node.expressions[i].accept(this);
     }
     final DartType typeArgument = evaluateDartType(node, node.typeArgument);
-    final ListConstant listConstant = new ListConstant(typeArgument, entries);
-    return canonicalize(backend.lowerListConstant(listConstant));
+    return canonicalize(new ListConstant(typeArgument, entries));
   }
 
   visitMapLiteral(MapLiteral node) {
@@ -532,9 +532,7 @@
     }
     final DartType keyType = evaluateDartType(node, node.keyType);
     final DartType valueType = evaluateDartType(node, node.valueType);
-    final MapConstant mapConstant =
-        new MapConstant(keyType, valueType, entries);
-    return canonicalize(backend.lowerMapConstant(mapConstant));
+    return canonicalize(new MapConstant(keyType, valueType, entries));
   }
 
   visitFunctionExpression(FunctionExpression node) {
@@ -553,6 +551,14 @@
         constructor.function.body is! EmptyStatement) {
       throw 'Constructor "$node" has non-trivial body "${constructor.function.body.runtimeType}".';
     }
+    if (constructor.isInExternalLibrary &&
+        constructor.initializers.isEmpty &&
+        constructor.enclosingClass.supertype != null) {
+      // The constructor is unavailable due to separate compilation.
+      return new UnevaluatedConstant(new ConstructorInvocation(
+          constructor, unevaluatedArguments(node.arguments),
+          isConst: true));
+    }
     if (klass.isAbstract) {
       throw 'Constructor "$node" belongs to abstract class "${klass}".';
     }
@@ -1108,6 +1114,10 @@
       final Member target = node.target;
       if (target is Field) {
         if (target.isConst) {
+          if (target.isInExternalLibrary && target.initializer == null) {
+            // The variable is unavailable due to separate compilation.
+            return new UnevaluatedConstant(node);
+          }
           return runInsideContext(target, () {
             return _evaluateSubexpression(target.initializer);
           });
@@ -1151,26 +1161,63 @@
 
   visitStaticInvocation(StaticInvocation node) {
     final Procedure target = node.target;
+    final Arguments arguments = node.arguments;
     if (target.kind == ProcedureKind.Factory) {
-      final String nativeName = getExternalName(target);
-      if (nativeName != null) {
-        final Constant constant = backend.buildConstantForNative(
-            nativeName,
-            evaluateTypeArguments(node, node.arguments),
-            evaluatePositionalArguments(node.arguments),
-            evaluateNamedArguments(node.arguments),
-            contextChain,
-            node,
-            errorReporter,
-            (String message) => throw new _AbortCurrentEvaluation(message));
-        assert(constant != null);
-        return canonicalize(constant);
+      if (target.isConst &&
+          target.name.name == "fromEnvironment" &&
+          target.enclosingLibrary == coreTypes.coreLibrary &&
+          arguments.positional.length == 1) {
+        if (environmentDefines != null) {
+          // Evaluate environment constant.
+          Constant name = arguments.positional[0].accept(this);
+          if (name is StringConstant) {
+            String value = environmentDefines[name.value];
+            Constant defaultValue = null;
+            for (int i = 0; i < arguments.named.length; i++) {
+              NamedExpression named = arguments.named[i];
+              if (named.name == "defaultValue") {
+                defaultValue = named.value.accept(this);
+                break;
+              }
+            }
+
+            if (target.enclosingClass == coreTypes.boolClass) {
+              Constant boolConstant = value == "true"
+                  ? trueConstant
+                  : value == "false"
+                      ? falseConstant
+                      : defaultValue is BoolConstant
+                          ? defaultValue.value ? trueConstant : falseConstant
+                          : defaultValue is NullConstant
+                              ? nullConstant
+                              : falseConstant;
+              return boolConstant;
+            } else if (target.enclosingClass == coreTypes.intClass) {
+              int intValue = value != null ? int.tryParse(value) : null;
+              intValue ??=
+                  defaultValue is IntConstant ? defaultValue.value : null;
+              if (intValue == null) return nullConstant;
+              return canonicalize(new IntConstant(intValue));
+            } else if (target.enclosingClass == coreTypes.stringClass) {
+              value ??=
+                  defaultValue is StringConstant ? defaultValue.value : null;
+              if (value == null) return nullConstant;
+              return canonicalize(new StringConstant(value));
+            }
+          }
+          // TODO(askesc): Give more meaningful error message if name is null.
+        } else {
+          // Leave environment constant unevaluated.
+          return new UnevaluatedConstant(new StaticInvocation(
+              target, unevaluatedArguments(arguments),
+              isConst: true));
+        }
       }
     } else if (target.name.name == 'identical') {
       // Ensure the "identical()" function comes from dart:core.
       final parent = target.parent;
       if (parent is Library && parent == coreTypes.coreLibrary) {
-        final positionalArguments = evaluatePositionalArguments(node.arguments);
+        final positionalArguments = evaluatePositionalArguments(arguments);
         final Constant left = positionalArguments[0];
         final Constant right = positionalArguments[1];
         // Since we canonicalize constants during the evaluation, we can use
@@ -1279,7 +1326,23 @@
     return named;
   }
 
-  canonicalize(Constant constant) {
+  Arguments unevaluatedArguments(Arguments arguments) {
+    final positional = new List<Expression>(arguments.positional.length);
+    final named = new List<NamedExpression>(arguments.named.length);
+    for (int i = 0; i < arguments.positional.length; ++i) {
+      Constant constant = arguments.positional[i].accept(this);
+      positional[i] = constant.asExpression();
+    }
+    for (int i = 0; i < arguments.named.length; ++i) {
+      NamedExpression arg = arguments.named[i];
+      Constant constant = arg.value.accept(this);
+      named[i] = new NamedExpression(arg.name, constant.asExpression());
+    }
+    return new Arguments(positional, named: named, types: arguments.types);
+  }
+
+  Constant canonicalize(Constant constant) {
+    constant = backend.lowerConstant(constant);
     return canonicalizationCache.putIfAbsent(constant, () => constant);
   }
 
@@ -1303,7 +1366,10 @@
     }
   }
 
-  evaluateBinaryNumericOperation(String op, num a, num b, TreeNode node) {
+  Constant evaluateBinaryNumericOperation(
+      String op, num a, num b, TreeNode node) {
+    a = backend.prepareNumericOperand(a);
+    b = backend.prepareNumericOperand(b);
     num result;
     switch (op) {
       case '+':
@@ -1425,18 +1491,16 @@
   }
 }
 
-abstract class ConstantsBackend {
-  Constant buildConstantForNative(
-      String nativeName,
-      List<DartType> typeArguments,
-      List<Constant> positionalArguments,
-      Map<String, Constant> namedArguments,
-      List<TreeNode> context,
-      StaticInvocation node,
-      ErrorReporter errorReporter,
-      Constant abortEvaluation(String message));
-  Constant lowerListConstant(ListConstant constant);
-  Constant lowerMapConstant(MapConstant constant);
+// Backend specific constant evaluation behavior
+class ConstantsBackend {
+  /// Transformation of constants prior to canonicalization, e.g. to change the
+  /// representation of certain kinds of constants, or to implement specific
+  /// number semantics.
+  Constant lowerConstant(Constant constant) => constant;
+
+  /// Transformation of numeric operands prior to a binary operation,
+  /// e.g. to implement specific number semantics.
+  num prepareNumericOperand(num operand) => operand;
 }
 
 // Used as control-flow to abort the current evaluation.
diff --git a/pkg/kernel/lib/type_environment.dart b/pkg/kernel/lib/type_environment.dart
index 3e3b4c5..20cceb6 100644
--- a/pkg/kernel/lib/type_environment.dart
+++ b/pkg/kernel/lib/type_environment.dart
@@ -177,6 +177,7 @@
     if (identical(subtype, supertype)) return true;
     if (subtype is BottomType) return true;
     if (subtype == nullType) {
+      // See rule 4 of the subtype rules from the Dart Language Specification.
       return supertype is! BottomType;
     }
     if (isTop(supertype)) return true;
diff --git a/pkg/kernel/lib/vm/constants_native_effects.dart b/pkg/kernel/lib/vm/constants_native_effects.dart
index 0d8fad8..58c8eca 100644
--- a/pkg/kernel/lib/vm/constants_native_effects.dart
+++ b/pkg/kernel/lib/vm/constants_native_effects.dart
@@ -8,152 +8,48 @@
 import '../transformations/constants.dart';
 import '../core_types.dart';
 
-class VmConstantsBackend implements ConstantsBackend {
-  final Map<String, String> defines;
-
+class VmConstantsBackend extends ConstantsBackend {
   final Class immutableMapClass;
-  final Class internalSymbolClass;
-  final Class stringClass;
-  final Field symbolNameField;
 
-  VmConstantsBackend._(this.defines, this.immutableMapClass,
-      this.internalSymbolClass, this.stringClass, this.symbolNameField);
+  VmConstantsBackend._(this.immutableMapClass);
 
   /// If [defines] is not `null` it will be used for handling
   /// `const {bool,...}.fromEnvironment()` otherwise the current VM's values
   /// will be used.
-  factory VmConstantsBackend(Map<String, String> defines, CoreTypes coreTypes) {
+  factory VmConstantsBackend(CoreTypes coreTypes) {
     final Library coreLibrary = coreTypes.coreLibrary;
     final Class immutableMapClass = coreLibrary.classes
         .firstWhere((Class klass) => klass.name == '_ImmutableMap');
     assert(immutableMapClass != null);
 
-    final Class internalSymbolClass = coreTypes.internalSymbolClass;
-    assert(internalSymbolClass != null);
-
-    final Class stringClass = coreTypes.stringClass;
-    assert(stringClass != null);
-
-    final Field symbolNameField =
-        internalSymbolClass.fields.where((Field field) {
-      return field.isInstanceMember && field.name.name == '_name';
-    }).single;
-
-    return new VmConstantsBackend._(defines, immutableMapClass,
-        internalSymbolClass, stringClass, symbolNameField);
+    return new VmConstantsBackend._(immutableMapClass);
   }
 
-  Constant buildConstantForNative(
-      String nativeName,
-      List<DartType> typeArguments,
-      List<Constant> positionalArguments,
-      Map<String, Constant> namedArguments,
-      List<TreeNode> context,
-      StaticInvocation node,
-      ErrorReporter errorReporter,
-      Constant abortEvaluation(String message)) {
-    if ([
-      'Bool_fromEnvironment',
-      'Integer_fromEnvironment',
-      'String_fromEnvironment'
-    ].contains(nativeName)) {
-      final argument = positionalArguments[0];
-      if (argument is StringConstant) {
-        final name = argument.value;
-
-        Constant handleFromEnvironment<ValueT, ConstantT>(
-            {ValueT defaultValue,
-            ValueT parse(String v, {ValueT defaultValue}),
-            ValueT fromEnvironment(String name, {ValueT defaultValue}),
-            ConstantT makeConstant(ValueT val)}) {
-          final Constant constant = namedArguments['defaultValue'];
-          if (constant is ConstantT) {
-            defaultValue = (constant as dynamic).value;
-          } else if (constant is NullConstant) {
-            defaultValue = null;
-          }
-          ValueT value;
-          if (defines != null) {
-            value = parse(defines[name], defaultValue: defaultValue);
-          } else {
-            value = fromEnvironment(name, defaultValue: defaultValue);
-          }
-          return value != null ? makeConstant(value) : new NullConstant();
-        }
-
-        switch (nativeName) {
-          case 'Bool_fromEnvironment':
-            return handleFromEnvironment<bool, BoolConstant>(
-                defaultValue: false,
-                parse: (String v, {bool defaultValue}) {
-                  final String defineValue = defines[name];
-                  return defineValue == 'true'
-                      ? true
-                      : (defineValue == 'false' ? false : defaultValue);
-                },
-                fromEnvironment: (v, {defaultValue}) =>
-                    bool.fromEnvironment(v, defaultValue: defaultValue),
-                makeConstant: (v) => BoolConstant(v));
-          case 'Integer_fromEnvironment':
-            return handleFromEnvironment<int, IntConstant>(
-                defaultValue: null,
-                parse: (String v, {int defaultValue}) {
-                  final String defineValue = defines[name];
-                  return defineValue != null
-                      ? (int.tryParse(defineValue) ?? defaultValue)
-                      : defaultValue;
-                },
-                fromEnvironment: (v, {defaultValue}) =>
-                    int.fromEnvironment(v, defaultValue: defaultValue),
-                makeConstant: (v) => new IntConstant(v));
-          case 'String_fromEnvironment':
-            return handleFromEnvironment<String, StringConstant>(
-                defaultValue: null,
-                parse: (String v, {String defaultValue}) {
-                  final String defineValue = defines[name];
-                  return defineValue ?? defaultValue;
-                },
-                fromEnvironment: (v, {defaultValue}) =>
-                    String.fromEnvironment(v, defaultValue: defaultValue),
-                makeConstant: (v) => new StringConstant(v));
-        }
-      } else {
-        return abortEvaluation(errorReporter.invalidDartType(
-            context,
-            node.arguments.positional.first,
-            argument,
-            new InterfaceType(stringClass)));
+  @override
+  Constant lowerConstant(Constant constant) {
+    if (constant is MapConstant) {
+      // The _ImmutableMap class is implemented via one field pointing to a list
+      // of key/value pairs -- see runtime/lib/immutable_map.dart!
+      final List<Constant> kvListPairs =
+          new List<Constant>(2 * constant.entries.length);
+      for (int i = 0; i < constant.entries.length; i++) {
+        final ConstantMapEntry entry = constant.entries[i];
+        kvListPairs[2 * i] = entry.key;
+        kvListPairs[2 * i + 1] = entry.value;
       }
+      // This is a bit fishy, since we merge the key and the value type by
+      // putting both into the same list.
+      final kvListConstant = new ListConstant(const DynamicType(), kvListPairs);
+      assert(immutableMapClass.fields.length == 1);
+      final Field kvPairListField = immutableMapClass.fields[0];
+      return new InstanceConstant(immutableMapClass.reference, <DartType>[
+        constant.keyType,
+        constant.valueType,
+      ], <Reference, Constant>{
+        kvPairListField.reference: kvListConstant,
+      });
     }
 
-    throw 'No native effect registered for constant evaluation: $nativeName';
-  }
-
-  Constant lowerMapConstant(MapConstant constant) {
-    // The _ImmutableMap class is implemented via one field pointing to a list
-    // of key/value pairs -- see runtime/lib/immutable_map.dart!
-    final List<Constant> kvListPairs =
-        new List<Constant>(2 * constant.entries.length);
-    for (int i = 0; i < constant.entries.length; i++) {
-      final ConstantMapEntry entry = constant.entries[i];
-      kvListPairs[2 * i] = entry.key;
-      kvListPairs[2 * i + 1] = entry.value;
-    }
-    // This is a bit fishy, since we merge the key and the value type by
-    // putting both into the same list.
-    final kvListConstant = new ListConstant(const DynamicType(), kvListPairs);
-    assert(immutableMapClass.fields.length == 1);
-    final Field kvPairListField = immutableMapClass.fields[0];
-    return new InstanceConstant(immutableMapClass.reference, <DartType>[
-      constant.keyType,
-      constant.valueType,
-    ], <Reference, Constant>{
-      kvPairListField.reference: kvListConstant,
-    });
-  }
-
-  Constant lowerListConstant(ListConstant constant) {
-    // Currently we let vipunen deal with the [ListConstant]s.
     return constant;
   }
 }
diff --git a/pkg/kernel/problems.md b/pkg/kernel/problems.md
index d9f2ee6..3c1fb5e 100644
--- a/pkg/kernel/problems.md
+++ b/pkg/kernel/problems.md
@@ -10,9 +10,15 @@
 
 `ansiFormatted`: A list of strings the contain ansi formatted (for instance with
 colors) problem-texts as reported by the compiler.
+
 `plainTextFormatted`: A list of strings that contain formatted plaintext
 problem-texts as reported by the compiler.
 
+`severity`: An integer representing severity. This should match the index in
+`package:front_end/src/fasta/severity.dart`.
+
+`uri: A uri that this problems relates to.
+
 These values are subject to change, but this file will be updated along with any
 such changes. On the code-side these are defined in
 `package:front_end/src/fasta/fasta_codes.dart`.
diff --git a/pkg/kernel/pubspec.yaml b/pkg/kernel/pubspec.yaml
index eceffca..21e199c 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.9
+version: 0.3.11
 author: Dart Team <misc@dartlang.org>
 description: Dart IR (Intermediate Representation)
 homepage: https://github.com/dart-lang/sdk/tree/master/pkg/kernel
@@ -13,9 +13,9 @@
 dev_dependencies:
   expect:
     path: ../expect
-  front_end: 0.1.9
-  test: ^1.3.4
-  stack_trace: ^1.6.6
-  test_reflective_loader: ^0.1.0
+  front_end:
+    path: ../front_end
+  test:
+    path: ../third_party/pkg/test
   testing:
     path: ../testing
diff --git a/pkg/kernel/test/binary/library_flags_test.dart b/pkg/kernel/test/binary/library_flags_test.dart
new file mode 100644
index 0000000..9389b21
--- /dev/null
+++ b/pkg/kernel/test/binary/library_flags_test.dart
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'utils.dart';
+
+/// Test that library flags (external, synthetic)
+/// are serialized and read correctly.
+main() {
+  Library lib = new Library(Uri.parse("foo://bar.dart"));
+  lib.isExternal = false;
+  lib.isSynthetic = false;
+  Library lib2 = libRoundTrip(lib);
+  if (lib2.isExternal != false)
+    throw "Serialized and re-read library had change in external flag.";
+  if (lib2.isSynthetic != false)
+    throw "Serialized and re-read library had change in synthetic flag.";
+
+  lib = new Library(Uri.parse("foo://bar.dart"));
+  lib.isExternal = true;
+  lib.isSynthetic = false;
+  lib2 = libRoundTrip(lib);
+  if (lib2.isExternal != true)
+    throw "Serialized and re-read library had change in external flag.";
+  if (lib2.isSynthetic != false)
+    throw "Serialized and re-read library had change in synthetic flag.";
+
+  lib = new Library(Uri.parse("foo://bar.dart"));
+  lib.isExternal = false;
+  lib.isSynthetic = true;
+  lib2 = libRoundTrip(lib);
+  if (lib2.isExternal != false)
+    throw "Serialized and re-read library had change in external flag.";
+  if (lib2.isSynthetic != true)
+    throw "Serialized and re-read library had change in synthetic flag.";
+
+  lib = new Library(Uri.parse("foo://bar.dart"));
+  lib.isExternal = true;
+  lib.isSynthetic = true;
+  lib2 = libRoundTrip(lib);
+  if (lib2.isExternal != true)
+    throw "Serialized and re-read library had change in external flag.";
+  if (lib2.isSynthetic != true)
+    throw "Serialized and re-read library had change in synthetic flag.";
+}
diff --git a/pkg/kernel/test/binary/utils.dart b/pkg/kernel/test/binary/utils.dart
new file mode 100644
index 0000000..28bf4be
--- /dev/null
+++ b/pkg/kernel/test/binary/utils.dart
@@ -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.
+
+import 'dart:io' show BytesBuilder;
+
+import 'package:kernel/binary/ast_to_binary.dart' show BinaryPrinter;
+import 'package:kernel/kernel.dart';
+export 'package:kernel/kernel.dart';
+
+Library libRoundTrip(Library lib) {
+  return serializationRoundTrip([lib])[0];
+}
+
+List<Library> serializationRoundTrip(List<Library> libraries) {
+  Component c = new Component(libraries: libraries);
+  ByteSink byteSink = new ByteSink();
+  BinaryPrinter printer = new BinaryPrinter(byteSink);
+  printer.writeComponentFile(c);
+  List<int> bytes = byteSink.builder.takeBytes();
+  Component c2 = loadComponentFromBytes(bytes);
+  return c2.libraries;
+}
+
+/// A [Sink] that directly writes data into a byte builder.
+class ByteSink implements Sink<List<int>> {
+  final BytesBuilder builder = new BytesBuilder();
+
+  void add(List<int> data) {
+    builder.add(data);
+  }
+
+  void close() {}
+}
diff --git a/pkg/kernel/test/class_hierarchy_test.dart b/pkg/kernel/test/class_hierarchy_test.dart
index 956c0cf..c195192 100644
--- a/pkg/kernel/test/class_hierarchy_test.dart
+++ b/pkg/kernel/test/class_hierarchy_test.dart
@@ -2,23 +2,96 @@
 // for details. 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/class_hierarchy.dart';
-import 'package:kernel/core_types.dart';
-import 'package:kernel/testing/mock_sdk_component.dart';
-import 'package:kernel/text/ast_to_text.dart';
-import 'package:kernel/type_algebra.dart';
-import 'package:test/test.dart';
-import 'package:test_reflective_loader/test_reflective_loader.dart';
+import "package:expect/matchers_lite.dart";
+
+import "package:kernel/ast.dart";
+import "package:kernel/class_hierarchy.dart";
+import "package:kernel/core_types.dart";
+import "package:kernel/testing/mock_sdk_component.dart";
+import "package:kernel/text/ast_to_text.dart";
 
 main() {
-  defineReflectiveSuite(() {
-    defineReflectiveTests(ClosedWorldClassHierarchyTest);
-  });
+  new ClosedWorldClassHierarchyTest().test_applyTreeChanges();
+
+  new ClosedWorldClassHierarchyTest().test_applyMemberChanges();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getSingleTargetForInterfaceInvocation();
+
+  new ClosedWorldClassHierarchyTest().test_getSubtypesOf();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_forEachOverridePair_supertypeOverridesInterface();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_forEachOverridePair_supertypeOverridesThis();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_forEachOverridePair_supertypeOverridesThisAbstract();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_forEachOverridePair_thisOverridesSupertype();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_forEachOverridePair_thisOverridesSupertype_setter();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getClassAsInstanceOf_generic_extends();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getClassAsInstanceOf_generic_implements();
+
+  new ClosedWorldClassHierarchyTest().test_getClassAsInstanceOf_generic_with();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getClassAsInstanceOf_notGeneric_extends();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getClassAsInstanceOf_notGeneric_implements();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getClassAsInstanceOf_notGeneric_with();
+
+  new ClosedWorldClassHierarchyTest().test_getDeclaredMembers();
+
+  new ClosedWorldClassHierarchyTest().test_getDispatchTarget();
+
+  new ClosedWorldClassHierarchyTest().test_getDispatchTarget_abstract();
+
+  new ClosedWorldClassHierarchyTest().test_getInterfaceMember_extends();
+
+  new ClosedWorldClassHierarchyTest().test_getInterfaceMember_implements();
+
+  new ClosedWorldClassHierarchyTest().test_getInterfaceMembers_in_class();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getInterfaceMembers_inherited_or_mixed_in();
+
+  new ClosedWorldClassHierarchyTest().test_getInterfaceMembers_multiple();
+
+  new ClosedWorldClassHierarchyTest().test_getInterfaceMembers_shadowed();
+
+  new ClosedWorldClassHierarchyTest().test_getOrderedClasses();
+
+  new ClosedWorldClassHierarchyTest()
+      .test_getTypeAsInstanceOf_generic_extends();
 }
 
-@reflectiveTest
-class ClosedWorldClassHierarchyTest extends _ClassHierarchyTest {
+class ClosedWorldClassHierarchyTest {
+  final Component component = createMockSdkComponent();
+  CoreTypes coreTypes;
+
+  final Library library =
+      new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
+
+  ClassHierarchy _hierarchy;
+
+  ClosedWorldClassHierarchyTest() {
+    coreTypes = new CoreTypes(component);
+    library.parent = component;
+    component.libraries.add(library);
+  }
+
   ClassHierarchy createClassHierarchy(Component component) {
     return new ClassHierarchy(component);
   }
@@ -208,16 +281,6 @@
     expect(cwchst.getSubtypesOf(g), unorderedEquals([g, h]));
     expect(cwchst.getSubtypesOf(h), unorderedEquals([h]));
   }
-}
-
-abstract class _ClassHierarchyTest {
-  Component component;
-  CoreTypes coreTypes;
-
-  /// The test library.
-  Library library;
-
-  ClassHierarchy _hierarchy;
 
   /// Return the new or existing instance of [ClassHierarchy].
   ClassHierarchy get hierarchy {
@@ -259,17 +322,6 @@
         implementedTypes: implementedTypes));
   }
 
-  /// Add a new class with the given [name] that extends `Object` and
-  /// [implements_] the given classes.
-  Class addImplementsClass(String name, List<Class> implements_) {
-    return addClass(new Class(
-        name: name,
-        supertype: objectSuper,
-        implementedTypes: implements_.map((c) => c.asThisSupertype).toList()));
-  }
-
-  ClassHierarchy createClassHierarchy(Component component);
-
   Procedure newEmptyGetter(String name,
       {DartType returnType: const DynamicType(), bool isAbstract: false}) {
     var body =
@@ -296,17 +348,6 @@
             positionalParameters: [new VariableDeclaration('_', type: type)]));
   }
 
-  void setUp() {
-    // Start with mock SDK libraries.
-    component = createMockSdkComponent();
-    coreTypes = new CoreTypes(component);
-
-    // Add the test library.
-    library = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'test');
-    library.parent = component;
-    component.libraries.add(library);
-  }
-
   /// 2. A non-abstract member is inherited from a superclass, and in the
   /// context of this class, it overrides an abstract member inheritable through
   /// one of its superinterfaces.
@@ -646,175 +687,6 @@
     expect(hierarchy.getClassAsInstanceOf(z, a), null);
   }
 
-  /// Copy of the tests/language/least_upper_bound_expansive_test.dart test.
-  void test_getLegacyLeastUpperBound_expansive() {
-    var int = coreTypes.intClass.rawType;
-    var string = coreTypes.stringClass.rawType;
-
-    // class N<T> {}
-    var NT = new TypeParameter('T', objectClass.rawType);
-    var N = addClass(
-        new Class(name: 'N', typeParameters: [NT], supertype: objectSuper));
-
-    // class C1<T> extends N<N<C1<T>>> {}
-    Class C1;
-    {
-      var T = new TypeParameter('T', objectClass.rawType);
-      C1 = addClass(
-          new Class(name: 'C1', typeParameters: [T], supertype: objectSuper));
-      DartType C1_T = Substitution.fromMap({T: new TypeParameterType(T)})
-          .substituteType(C1.thisType);
-      DartType N_C1_T =
-          Substitution.fromMap({NT: C1_T}).substituteType(N.thisType);
-      Supertype N_N_C1_T = Substitution.fromMap({NT: N_C1_T})
-          .substituteSupertype(N.asThisSupertype);
-      C1.supertype = N_N_C1_T;
-    }
-
-    // class C2<T> extends N<N<C2<N<C2<T>>>>> {}
-    Class C2;
-    {
-      var T = new TypeParameter('T', objectClass.rawType);
-      C2 = addClass(
-          new Class(name: 'C2', typeParameters: [T], supertype: objectSuper));
-      DartType C2_T = Substitution.fromMap({T: new TypeParameterType(T)})
-          .substituteType(C2.thisType);
-      DartType N_C2_T =
-          Substitution.fromMap({NT: C2_T}).substituteType(N.thisType);
-      DartType C2_N_C2_T =
-          Substitution.fromMap({T: N_C2_T}).substituteType(C2.thisType);
-      DartType N_C2_N_C2_T =
-          Substitution.fromMap({NT: C2_N_C2_T}).substituteType(N.thisType);
-      Supertype N_N_C2_N_C2_T = Substitution.fromMap({NT: N_C2_N_C2_T})
-          .substituteSupertype(N.asThisSupertype);
-      C2.supertype = N_N_C2_N_C2_T;
-    }
-
-    _assertTestLibraryText('''
-class N<T> {}
-class C1<T> extends self::N<self::N<self::C1<self::C1::T>>> {}
-class C2<T> extends self::N<self::N<self::C2<self::N<self::C2<self::C2::T>>>>> {}
-''');
-
-    // The least upper bound of C1<int> and N<C1<String>> is Object since the
-    // supertypes are
-    //     {C1<int>, N<N<C1<int>>>, Object} for C1<int> and
-    //     {N<C1<String>>, Object} for N<C1<String>> and
-    // Object is the most specific type in the intersection of the supertypes.
-    expect(
-        hierarchy.getLegacyLeastUpperBound(
-            new InterfaceType(C1, [int]),
-            new InterfaceType(N, [
-              new InterfaceType(C1, [string])
-            ])),
-        objectClass.thisType);
-
-    // The least upper bound of C2<int> and N<C2<String>> is Object since the
-    // supertypes are
-    //     {C2<int>, N<N<C2<N<C2<int>>>>>, Object} for C2<int> and
-    //     {N<C2<String>>, Object} for N<C2<String>> and
-    // Object is the most specific type in the intersection of the supertypes.
-    expect(
-        hierarchy.getLegacyLeastUpperBound(
-            new InterfaceType(C2, [int]),
-            new InterfaceType(N, [
-              new InterfaceType(C2, [string])
-            ])),
-        objectClass.thisType);
-  }
-
-  void test_getLegacyLeastUpperBound_generic() {
-    var int = coreTypes.intClass.rawType;
-    var double = coreTypes.doubleClass.rawType;
-    var bool = coreTypes.boolClass.rawType;
-
-    var a = addGenericClass('A', []);
-    var b =
-        addGenericClass('B', ['T'], implements_: (_) => [a.asThisSupertype]);
-    var c =
-        addGenericClass('C', ['U'], implements_: (_) => [a.asThisSupertype]);
-    var d = addGenericClass('D', ['T', 'U'], implements_: (typeParameterTypes) {
-      var t = typeParameterTypes[0];
-      var u = typeParameterTypes[1];
-      return [
-        new Supertype(b, [t]),
-        new Supertype(c, [u])
-      ];
-    });
-    var e = addGenericClass('E', [],
-        implements_: (_) => [
-              new Supertype(d, [int, double])
-            ]);
-    var f = addGenericClass('F', [],
-        implements_: (_) => [
-              new Supertype(d, [int, bool])
-            ]);
-
-    _assertTestLibraryText('''
-class A {}
-class B<T> implements self::A {}
-class C<U> implements self::A {}
-class D<T, U> implements self::B<self::D::T>, self::C<self::D::U> {}
-class E implements self::D<core::int, core::double> {}
-class F implements self::D<core::int, core::bool> {}
-''');
-
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [int, double])),
-        new InterfaceType(d, [int, double]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [int, bool])),
-        new InterfaceType(b, [int]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [bool, double])),
-        new InterfaceType(c, [double]));
-    expect(
-        hierarchy.getLegacyLeastUpperBound(new InterfaceType(d, [int, double]),
-            new InterfaceType(d, [bool, int])),
-        a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(e.rawType, f.rawType),
-        new InterfaceType(b, [int]));
-  }
-
-  void test_getLegacyLeastUpperBound_nonGeneric() {
-    var a = addImplementsClass('A', []);
-    var b = addImplementsClass('B', []);
-    var c = addImplementsClass('C', [a]);
-    var d = addImplementsClass('D', [a]);
-    var e = addImplementsClass('E', [a]);
-    var f = addImplementsClass('F', [c, d]);
-    var g = addImplementsClass('G', [c, d]);
-    var h = addImplementsClass('H', [c, d, e]);
-    var i = addImplementsClass('I', [c, d, e]);
-
-    _assertTestLibraryText('''
-class A {}
-class B {}
-class C implements self::A {}
-class D implements self::A {}
-class E implements self::A {}
-class F implements self::C, self::D {}
-class G implements self::C, self::D {}
-class H implements self::C, self::D, self::E {}
-class I implements self::C, self::D, self::E {}
-''');
-
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, b.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, objectClass.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(objectClass.rawType, b.rawType),
-        objectClass.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, d.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(c.rawType, a.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(a.rawType, d.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(f.rawType, g.rawType), a.rawType);
-    expect(hierarchy.getLegacyLeastUpperBound(h.rawType, i.rawType), a.rawType);
-  }
-
   void test_getDeclaredMembers() {
     var method = newEmptyMethod('method');
     var getter = newEmptyGetter('getter');
diff --git a/pkg/kernel/test/text_serializer_test.dart b/pkg/kernel/test/text_serializer_test.dart
index c64ff64..1cd569c 100644
--- a/pkg/kernel/test/text_serializer_test.dart
+++ b/pkg/kernel/test/text_serializer_test.dart
@@ -79,6 +79,11 @@
     "(map (dynamic) (void) ((int 0) (null) (int 1) (null) (int 2) (null)))",
     "(const-map (dynamic) (void) ((int 0) (null) (int 1) (null) "
         "(int 2) (null)))",
+    "(type (-> ((dynamic)) 1 (dynamic)))",
+    "(type (-> ((dynamic)) 0 (dynamic)))",
+    "(type (-> ((dynamic) (dynamic)) 2 (dynamic)))",
+    "(type (-> () 0 (dynamic)))",
+    "(type (-> ((-> ((dynamic)) 1 (dynamic))) 1 (dynamic)))",
   ];
   for (var test in tests) {
     var literal = readExpression(test);
diff --git a/pkg/kernel/test/type_subtype_test.dart b/pkg/kernel/test/type_subtype_test.dart
deleted file mode 100644
index 753e525..0000000
--- a/pkg/kernel/test/type_subtype_test.dart
+++ /dev/null
@@ -1,279 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-import 'package:test/test.dart';
-import 'package:kernel/ast.dart';
-import 'package:kernel/class_hierarchy.dart';
-import 'package:kernel/type_environment.dart';
-import 'type_parser.dart';
-
-/// Description of a small class hierarchy for use in subtype tests.
-var classEnvironment = <String, List<String>>{
-  'Comparable<T>': ['Object'],
-  'num': ['Object', 'Comparable<num>'],
-  'int': ['num'],
-  'double': ['num'],
-  'Iterable<T>': ['Object'],
-  'List<T>': ['Iterable<T>'],
-  'Future<T>': ['Object'],
-  'FutureOr<T>': ['Object'],
-  'Null': ['Object'],
-};
-
-List<TestCase> testCases = <TestCase>[
-  subtype('int', 'num', legacyMode: true),
-  subtype('int', 'Comparable<num>', legacyMode: true),
-  subtype('int', 'Comparable<Object>', legacyMode: true),
-  subtype('int', 'Object', legacyMode: true),
-  subtype('double', 'num', legacyMode: true),
-
-  notSubtype('int', 'double', legacyMode: true),
-  notSubtype('int', 'Comparable<int>', legacyMode: true),
-  notSubtype('int', 'Iterable<int>', legacyMode: true),
-  notSubtype('Comparable<int>', 'Iterable<int>', legacyMode: true),
-
-  subtype('List<int>', 'List<int>', legacyMode: true),
-  subtype('List<int>', 'Iterable<int>', legacyMode: true),
-  subtype('List<int>', 'List<num>', legacyMode: true),
-  subtype('List<int>', 'Iterable<num>', legacyMode: true),
-  subtype('List<int>', 'List<Object>', legacyMode: true),
-  subtype('List<int>', 'Iterable<Object>', legacyMode: true),
-  subtype('List<int>', 'Object', legacyMode: true),
-  subtype('List<int>', 'List<Comparable<Object>>', legacyMode: true),
-  subtype('List<int>', 'List<Comparable<num>>', legacyMode: true),
-  subtype('List<int>', 'List<Comparable<Comparable<num>>>', legacyMode: true),
-
-  notSubtype('List<int>', 'List<double>', legacyMode: true),
-  notSubtype('List<int>', 'Iterable<double>', legacyMode: true),
-  notSubtype('List<int>', 'Comparable<int>', legacyMode: true),
-  notSubtype('List<int>', 'List<Comparable<int>>', legacyMode: true),
-  notSubtype('List<int>', 'List<Comparable<Comparable<int>>>',
-      legacyMode: true),
-
-  subtype('(num) => num', '(int) => num', legacyMode: true),
-  subtype('(num) => int', '(num) => num', legacyMode: true),
-  subtype('(num) => int', '(int) => num', legacyMode: true),
-  notSubtype('(int) => int', '(num) => num', legacyMode: true),
-
-  subtype('(num) => (num) => num', '(num) => (int) => num', legacyMode: true),
-  notSubtype('(num) => (int) => int', '(num) => (num) => num',
-      legacyMode: true),
-
-  subtype('(x:num) => num', '(x:int) => num',
-      legacyMode: true), // named parameters
-  subtype('(num,x:num) => num', '(int,x:int) => num', legacyMode: true),
-  subtype('(x:num) => int', '(x:num) => num', legacyMode: true),
-  notSubtype('(x:int) => int', '(x:num) => num', legacyMode: true),
-
-  subtype('<E>(E) => int', '<E>(E) => num',
-      legacyMode: true), // type parameters
-  subtype('<E>(num) => E', '<E>(int) => E', legacyMode: true),
-  subtype('<E>(E,num) => E', '<E>(E,int) => E', legacyMode: true),
-  notSubtype('<E>(E,num) => E', '<E>(E,E) => E', legacyMode: true),
-
-  subtype('<E>(E) => (E) => E', '<F>(F) => (F) => F', legacyMode: true),
-  subtype('<E>(E, (int,E) => E) => E', '<E>(E, (int,E) => E) => E',
-      legacyMode: true),
-  subtype('<E>(E, (int,E) => E) => E', '<E>(E, (num,E) => E) => E',
-      legacyMode: true),
-  notSubtype('<E,F>(E) => (F) => E', '<E>(E) => <F>(F) => E', legacyMode: true),
-  notSubtype('<E,F>(E) => (F) => E', '<F,E>(E) => (F) => E', legacyMode: true),
-
-  notSubtype('<E>(E,num) => E', '<E:num>(E,E) => E', legacyMode: true),
-  notSubtype('<E:num>(E) => int', '<E:int>(E) => int', legacyMode: true),
-  notSubtype('<E:num>(E) => E', '<E:int>(E) => E', legacyMode: true),
-  notSubtype('<E:num>(int) => E', '<E:int>(int) => E', legacyMode: true),
-  subtype('<E:num>(E) => E', '<F:num>(F) => num', legacyMode: true),
-  subtype('<E:int>(E) => E', '<F:int>(F) => num', legacyMode: true),
-  subtype('<E:int>(E) => E', '<F:int>(F) => int', legacyMode: true),
-  notSubtype('<E>(int) => int', '(int) => int', legacyMode: true),
-  notSubtype('<E,F>(int) => int', '<E>(int) => int', legacyMode: true),
-
-  subtype('<E:List<E>>(E) => E', '<F:List<F>>(F) => F', legacyMode: true),
-  notSubtype('<E:Iterable<E>>(E) => E', '<F:List<F>>(F) => F',
-      legacyMode: true),
-  notSubtype('<E>(E,List<Object>) => E', '<F:List<F>>(F,F) => F',
-      legacyMode: true),
-  notSubtype('<E>(E,List<Object>) => List<E>', '<F:List<F>>(F,F) => F',
-      legacyMode: true),
-  notSubtype('<E>(E,List<Object>) => int', '<F:List<F>>(F,F) => F',
-      legacyMode: true),
-  notSubtype('<E>(E,List<Object>) => E', '<F:List<F>>(F,F) => void',
-      legacyMode: true),
-
-  subtype('int', 'FutureOr<int>'),
-  subtype('int', 'FutureOr<num>'),
-  subtype('Future<int>', 'FutureOr<int>'),
-  subtype('Future<int>', 'FutureOr<num>'),
-  subtype('Future<int>', 'FutureOr<Object>'),
-  subtype('FutureOr<int>', 'FutureOr<int>'),
-  subtype('FutureOr<int>', 'FutureOr<num>'),
-  subtype('FutureOr<int>', 'Object'),
-  notSubtype('int', 'FutureOr<double>'),
-  notSubtype('FutureOr<double>', 'int'),
-  notSubtype('FutureOr<int>', 'Future<num>'),
-  notSubtype('FutureOr<int>', 'num'),
-
-  // T & B <: T & A if B <: A
-  subtype('T & int', 'T & int', legacyMode: true),
-  subtype('T & int', 'T & num', legacyMode: true),
-  subtype('T & num', 'T & num', legacyMode: true),
-  notSubtype('T & num', 'T & int', legacyMode: true),
-
-  // T & B <: T extends A if B <: A
-  // (Trivially satisfied since promoted bounds are always a subtype of the
-  // original bound)
-  subtype('T & int', 'T', legacyMode: true, typeParameters: 'T: int'),
-  subtype('T & int', 'T', legacyMode: true, typeParameters: 'T: num'),
-  subtype('T & num', 'T', legacyMode: true, typeParameters: 'T: num'),
-
-  // T extends B <: T & A if B <: A
-  subtype('T', 'T & int', legacyMode: true, typeParameters: 'T: int'),
-  subtype('T', 'T & num', legacyMode: true, typeParameters: 'T: int'),
-  subtype('T', 'T & num', legacyMode: true, typeParameters: 'T: num'),
-  notSubtype('T', 'T & int', legacyMode: true, typeParameters: 'T: num'),
-
-  // T extends A <: T extends A
-  subtype('T', 'T', legacyMode: true, typeParameters: 'T: num'),
-
-  // S & B <: A if B <: A, A is not S (or a promotion thereof)
-  subtype('S & int', 'int', legacyMode: true),
-  subtype('S & int', 'num', legacyMode: true),
-  subtype('S & num', 'num', legacyMode: true),
-  notSubtype('S & num', 'int', legacyMode: true),
-  notSubtype('S & num', 'T', legacyMode: true),
-  notSubtype('S & num', 'T & num', legacyMode: true),
-
-  // S extends B <: A if B <: A, A is not S (or a promotion thereof)
-  subtype('S', 'int', legacyMode: true, typeParameters: 'S: int'),
-  subtype('S', 'num', legacyMode: true, typeParameters: 'S: int'),
-  subtype('S', 'num', legacyMode: true, typeParameters: 'S: num'),
-  notSubtype('S', 'int', legacyMode: true, typeParameters: 'S: num'),
-  notSubtype('S', 'T', legacyMode: true, typeParameters: 'S: num'),
-  notSubtype('S', 'T & num', legacyMode: true, typeParameters: 'S: num'),
-];
-
-/// Assert that [subtype] is a subtype of [supertype], and that [supertype]
-/// is not a subtype of [subtype] (unless the two strings are equal).
-TestCase subtype(String subtype_, String supertype,
-    {bool legacyMode: false, String typeParameters}) {
-  return new TestCase(subtype_, supertype,
-      isSubtype: true, legacyMode: legacyMode, typeParameters: typeParameters);
-}
-
-/// Assert that neither type is a subtype of the other.
-TestCase notSubtype(String subtype_, String supertype,
-    {bool legacyMode: false, String typeParameters}) {
-  return new TestCase(subtype_, supertype,
-      isSubtype: false, legacyMode: legacyMode, typeParameters: typeParameters);
-}
-
-class TestCase {
-  String subtype;
-  String supertype;
-  String typeParameters;
-  bool isSubtype;
-  bool legacyMode;
-
-  TestCase(this.subtype, this.supertype,
-      {this.isSubtype, this.legacyMode: false, this.typeParameters});
-
-  String toString() {
-    var description =
-        isSubtype ? '$subtype <: $supertype' : '$subtype </: $supertype';
-    if (typeParameters != null) {
-      description += ' (type parameters: $typeParameters)';
-    }
-    if (legacyMode) {
-      description += ' (legacy mode)';
-    }
-    return description;
-  }
-}
-
-class MockSubtypeTester extends SubtypeTester {
-  ClassHierarchy hierarchy;
-  InterfaceType objectType;
-  InterfaceType nullType;
-  InterfaceType rawFunctionType;
-  Class futureClass;
-  Class futureOrClass;
-  LazyTypeEnvironment environment;
-  bool legacyMode = false;
-
-  InterfaceType futureType(DartType type) =>
-      new InterfaceType(futureClass, [type]);
-
-  @override
-  InterfaceType getTypeAsInstanceOf(InterfaceType type, Class superclass) {
-    return hierarchy.getTypeAsInstanceOf(type, superclass);
-  }
-
-  MockSubtypeTester(
-      this.hierarchy,
-      this.objectType,
-      this.nullType,
-      this.rawFunctionType,
-      this.futureClass,
-      this.futureOrClass,
-      this.environment);
-}
-
-MockSubtypeTester makeSubtypeTester(Map<String, List<String>> testcase) {
-  LazyTypeEnvironment environment = new LazyTypeEnvironment();
-  Class objectClass = environment.lookup('Object');
-  Class nullClass = environment.lookup('Null');
-  Class functionClass = environment.lookup('Function');
-  Class futureClass = environment.lookup('Future');
-  Class futureOrClass = environment.lookup('FutureOr');
-  functionClass.supertype = objectClass.asRawSupertype;
-  for (var typeString in testcase.keys) {
-    InterfaceType type = environment.parseFresh(typeString);
-    Class class_ = type.classNode;
-    for (TypeParameterType typeArg in type.typeArguments) {
-      class_.typeParameters.add(typeArg.parameter);
-    }
-    for (var supertypeString in testcase[typeString]) {
-      if (class_.supertype == null) {
-        class_.supertype = environment.parseSuper(supertypeString);
-      } else {
-        class_.implementedTypes.add(environment.parseSuper(supertypeString));
-      }
-    }
-  }
-  var component = new Component(libraries: [environment.dummyLibrary]);
-  var hierarchy = new ClassHierarchy(component);
-  return new MockSubtypeTester(
-      hierarchy,
-      objectClass.rawType,
-      nullClass.rawType,
-      functionClass.rawType,
-      futureClass,
-      futureOrClass,
-      environment);
-}
-
-main() {
-  var tester = makeSubtypeTester(classEnvironment);
-  for (var testCase in testCases) {
-    test('$testCase', () {
-      tester.legacyMode = testCase.legacyMode;
-      var environment = tester.environment;
-      environment.clearTypeParameters();
-      if (testCase.typeParameters != null) {
-        environment.setupTypeParameters(testCase.typeParameters);
-      }
-      var subtype = environment.parse(testCase.subtype);
-      var supertype = environment.parse(testCase.supertype);
-      if (tester.isSubtypeOf(subtype, supertype) != testCase.isSubtype) {
-        fail('isSubtypeOf(${testCase.subtype}, ${testCase.supertype}) returned '
-            '${!testCase.isSubtype} but should return ${testCase.isSubtype}');
-      }
-      if (subtype != supertype && tester.isSubtypeOf(supertype, subtype)) {
-        fail('isSubtypeOf(${testCase.supertype}, ${testCase.subtype}) returned '
-            'true but should return false');
-      }
-    });
-  }
-}
diff --git a/pkg/sourcemap_testing/pubspec.yaml b/pkg/sourcemap_testing/pubspec.yaml
index c12dcf1..a7ee40e 100644
--- a/pkg/sourcemap_testing/pubspec.yaml
+++ b/pkg/sourcemap_testing/pubspec.yaml
@@ -1,6 +1,10 @@
 # Helper package for testing sourcemaps. Used by ddc and dart2js.
 name: sourcemap_testing
-#version: do-not-upload
+publish_to: none
+
+environment:
+  sdk: '>=2.1.0 <3.0.0'
+
 dependencies:
   package_config: '>=0.1.1 <2.0.0'
   pub_semver: ^1.2.1
diff --git a/pkg/vm/bin/compare_sizes.dart b/pkg/vm/bin/compare_sizes.dart
index 1218de8..691566e 100644
--- a/pkg/vm/bin/compare_sizes.dart
+++ b/pkg/vm/bin/compare_sizes.dart
@@ -30,6 +30,8 @@
   final oldSizes = loadSymbolSizes(args[0]);
   final newSizes = loadSymbolSizes(args[1]);
 
+  var totalOld = 0;
+  var totalNew = 0;
   var totalDiff = 0;
   final diffBySymbol = <String, int>{};
 
@@ -37,8 +39,12 @@
   // in size. If symbol is not present in the compilation assume its size to be
   // zero.
   for (var key in Set<String>()..addAll(newSizes.keys)..addAll(oldSizes.keys)) {
-    final diff = (newSizes[key] ?? 0) - (oldSizes[key] ?? 0);
+    final oldSize = oldSizes[key] ?? 0;
+    final newSize = newSizes[key] ?? 0;
+    final diff = newSize - oldSize;
     if (diff != 0) diffBySymbol[key] = diff;
+    totalOld += oldSize;
+    totalNew += newSize;
     totalDiff += diff;
   }
 
@@ -75,9 +81,11 @@
   }
   table.addSeparator();
 
-  print('Comparing ${args[0]} (old) to ${args[1]} (new)');
   table.render();
-  print('Total change ${totalDiff > 0 ? '+' : ''}${totalDiff} bytes.');
+  print('Comparing ${args[0]} (old) to ${args[1]} (new)');
+  print('Old   : ${totalOld} bytes.');
+  print('New   : ${totalNew} bytes.');
+  print('Change: ${totalDiff > 0 ? '+' : ''}${totalDiff} bytes.');
 }
 
 /// A combination of characters that is unlikely to occur in the symbol name.
@@ -90,12 +98,24 @@
 /// by concatenating them with [librarySeparator].
 Map<String, int> loadSymbolSizes(String name) {
   final symbols = jsonDecode(File(name).readAsStringSync());
-  return Map<String, int>.fromIterable(symbols,
-      key: (e) =>
-          (e['l'] ?? '') +
-          librarySeparator +
-          e['n'].replaceAll('[Optimized] ', ''),
-      value: (e) => e['s']);
+  final result = new Map<String, int>();
+  final regexp = new RegExp(r"0x[a-fA-F0-9]+");
+  for (int i = 0, n = symbols.length; i < n; i++) {
+    final e = symbols[i];
+    // Obtain a key by combining library and method name. Strip anything
+    // after the library separator to make sure we can easily decode later.
+    // For method names, also remove non-deterministic parts to avoid
+    // reporting non-existing differences against the same layout.
+    String lib = ((e['l'] ?? '').split(librarySeparator))[0];
+    String name = (e['n'].split(librarySeparator))[0]
+        .replaceAll('[Optimized] ', '')
+        .replaceAll(regexp, '');
+    String key = lib + librarySeparator + name;
+    int val = e['s'];
+    result[key] =
+        (result[key] ?? 0) + val; // add (key,val), accumulate if exists
+  }
+  return result;
 }
 
 /// A row in the [AsciiTable].
diff --git a/pkg/vm/bin/kernel_service.dart b/pkg/vm/bin/kernel_service.dart
index e1e6bc8..141fb61 100644
--- a/pkg/vm/bin/kernel_service.dart
+++ b/pkg/vm/bin/kernel_service.dart
@@ -21,6 +21,7 @@
 library runtime.tools.kernel_service;
 
 import 'dart:async' show Future, ZoneSpecification, runZoned;
+import 'dart:collection' show UnmodifiableMapBase;
 import 'dart:convert' show utf8;
 import 'dart:io' show Platform, stderr hide FileSystemEntity;
 import 'dart:isolate';
@@ -112,6 +113,7 @@
       ..bytecode = bytecode
       ..experimentalFlags =
           parseExperimentalFlags(expFlags, (msg) => errors.add(msg))
+      ..environmentDefines = new EnvironmentMap()
       ..onDiagnostic = (DiagnosticMessage message) {
         bool printMessage;
         switch (message.severity) {
@@ -154,6 +156,25 @@
   Future<Component> compileInternal(Uri script);
 }
 
+// Environment map which looks up environment defines in the VM environment
+// at runtime.
+// TODO(askesc): This is a temporary hack to get hold of the environment during
+// JIT compilation. We use a lazy map accessing the VM runtime environment using
+// new String.fromEnvironment, since the VM currently does not support providing
+// the full (isolate specific) environment as a finite, static map.
+class EnvironmentMap extends UnmodifiableMapBase<String, String> {
+  @override
+  String operator [](Object key) {
+    // The fromEnvironment constructor is specified to throw when called using
+    // new. However, the VM implementation actually looks up the given name in
+    // the environment.
+    return new String.fromEnvironment(key);
+  }
+
+  @override
+  get keys => throw "Environment map iteration not supported";
+}
+
 class FileSink implements Sink<List<int>> {
   MemoryFileSystemEntity entityForUri;
   List<int> bytes = <int>[];
diff --git a/pkg/vm/lib/bytecode/assembler.dart b/pkg/vm/lib/bytecode/assembler.dart
index eaab503..a8d8cb0 100644
--- a/pkg/vm/lib/bytecode/assembler.dart
+++ b/pkg/vm/lib/bytecode/assembler.dart
@@ -271,6 +271,11 @@
     emitWord(_encodeAD(Opcode.kIndirectStaticCall, ra, rd));
   }
 
+  void emitDirectCall(int ra, int rd) {
+    emitSourcePosition();
+    emitWord(_encodeAD(Opcode.kDirectCall, ra, rd));
+  }
+
   void emitInterfaceCall(int ra, int rd) {
     emitSourcePosition();
     emitWord(_encodeAD(Opcode.kInterfaceCall, ra, rd));
diff --git a/pkg/vm/lib/bytecode/bytecode_serialization.dart b/pkg/vm/lib/bytecode/bytecode_serialization.dart
index bce0817..fd577df 100644
--- a/pkg/vm/lib/bytecode/bytecode_serialization.dart
+++ b/pkg/vm/lib/bytecode/bytecode_serialization.dart
@@ -5,7 +5,7 @@
 library vm.bytecode.bytecode_serialization;
 
 import 'dart:io' show BytesBuilder;
-import 'dart:typed_data' show Uint8List, Uint16List;
+import 'dart:typed_data' show ByteData, Endian, Uint8List, Uint16List;
 
 abstract class StringWriter {
   int put(String string);
@@ -361,46 +361,66 @@
   }
 }
 
-class ConstantPoolEntryStatistics {
+int doubleToIntBits(double value) {
+  final buf = new ByteData(8);
+  buf.setFloat64(0, value, Endian.little);
+  return buf.getInt64(0, Endian.little);
+}
+
+double intBitsToDouble(int bits) {
+  final buf = new ByteData(8);
+  buf.setInt64(0, bits, Endian.little);
+  return buf.getFloat64(0, Endian.little);
+}
+
+class NamedEntryStatistics {
   final String name;
   int size = 0;
   int count = 0;
 
-  ConstantPoolEntryStatistics(this.name);
+  NamedEntryStatistics(this.name);
+
+  String toString() => "${name.padRight(40)}:    ${size.toString().padLeft(10)}"
+      "  (count: ${count.toString().padLeft(8)})";
 }
 
 class BytecodeSizeStatistics {
   static int componentSize = 0;
   static int objectTableSize = 0;
+  static int objectTableEntriesCount = 0;
   static int stringTableSize = 0;
   static int membersSize = 0;
   static int constantPoolSize = 0;
   static int instructionsSize = 0;
-  static List<ConstantPoolEntryStatistics> constantPoolStats =
-      <ConstantPoolEntryStatistics>[];
+  static List<NamedEntryStatistics> constantPoolStats =
+      <NamedEntryStatistics>[];
+  static List<NamedEntryStatistics> objectTableStats = <NamedEntryStatistics>[];
 
   static void reset() {
     componentSize = 0;
     objectTableSize = 0;
+    objectTableEntriesCount = 0;
     stringTableSize = 0;
     membersSize = 0;
     constantPoolSize = 0;
     instructionsSize = 0;
-    constantPoolStats = <ConstantPoolEntryStatistics>[];
+    constantPoolStats = <NamedEntryStatistics>[];
+    objectTableStats = <NamedEntryStatistics>[];
   }
 
   static void dump() {
     print("Bytecode size statistics:");
     print("  Bytecode component:  $componentSize");
-    print("   - object table:     $objectTableSize");
+    print(
+        "   - object table:     $objectTableSize   (count: $objectTableEntriesCount)");
+    for (var entry in objectTableStats) {
+      print("       - $entry");
+    }
     print("   - string table:     $stringTableSize");
     print("  Bytecode members:    $membersSize");
     print("   - constant pool:    $constantPoolSize");
-    for (var cpStat in constantPoolStats) {
-      final name = cpStat.name.padRight(40);
-      final size = cpStat.size.toString().padLeft(10);
-      final count = cpStat.count.toString().padLeft(8);
-      print("       - $name:    $size  (count: $count)");
+    for (var entry in constantPoolStats) {
+      print("       - $entry");
     }
     print("   - instructions:     $instructionsSize");
   }
diff --git a/pkg/vm/lib/bytecode/constant_pool.dart b/pkg/vm/lib/bytecode/constant_pool.dart
index a81f5f0..18b1ac1 100644
--- a/pkg/vm/lib/bytecode/constant_pool.dart
+++ b/pkg/vm/lib/bytecode/constant_pool.dart
@@ -14,7 +14,7 @@
         BufferedWriter,
         BufferedReader,
         BytecodeSizeStatistics,
-        ConstantPoolEntryStatistics,
+        NamedEntryStatistics,
         StringTable;
 import 'object_table.dart' show ObjectHandle, ObjectTable;
 
@@ -175,7 +175,7 @@
 }
 
 // Occupies 2 entries in the constant pool.
-type ConstantInterfaceCall extends ConstantPoolEntry {
+type ConstantInterfaceCallV1 extends ConstantPoolEntry {
   Byte tag = 26;
   Byte flags(invocationKindBit0, invocationKindBit1);
              // Where invocationKind is index into InvocationKind.
@@ -183,35 +183,57 @@
   ConstantIndex argDesc;
 }
 
+type ConstantObjectRef extends ConstantPoolEntry {
+  Byte tag = 27;
+  PackedObject object;
+}
+
+// Occupies 2 entries in the constant pool.
+type ConstantDirectCall extends ConstantPoolEntry {
+  Byte tag = 28;
+  PackedObject target;
+  PackedObject argDesc;
+}
+
+// Occupies 2 entries in the constant pool.
+type ConstantInterfaceCall extends ConstantPoolEntry {
+  Byte tag = 29;
+  PackedObject target;
+  PackedObject argDesc;
+}
+
 */
 
 enum ConstantTag {
   kInvalid,
-  kNull,
-  kString,
-  kInt,
-  kDouble,
-  kBool,
-  kArgDesc,
+  kNull, // TODO(alexmarkov): obsolete, remove
+  kString, // TODO(alexmarkov): obsolete, remove
+  kInt, // TODO(alexmarkov): obsolete, remove
+  kDouble, // TODO(alexmarkov): obsolete, remove
+  kBool, // TODO(alexmarkov): obsolete, remove
+  kArgDesc, // TODO(alexmarkov): obsolete, remove
   kICData,
-  kStaticICData,
+  kStaticICData, // TODO(alexmarkov): obsolete, remove
   kStaticField,
   kInstanceField,
   kClass,
   kTypeArgumentsField,
-  kTearOff,
+  kTearOff, // TODO(alexmarkov): obsolete, remove
   kType,
-  kTypeArguments,
-  kList,
-  kInstance,
-  kTypeArgumentsForInstanceAllocation,
+  kTypeArguments, // TODO(alexmarkov): obsolete, remove
+  kList, // TODO(alexmarkov): obsolete, remove
+  kInstance, // TODO(alexmarkov): obsolete, remove
+  kTypeArgumentsForInstanceAllocation, // TODO(alexmarkov): obsolete, remove
   kClosureFunction,
   kEndClosureFunctionScope,
   kNativeEntry,
   kSubtypeTestCache,
-  kPartialTearOffInstantiation,
+  kPartialTearOffInstantiation, // TODO(alexmarkov): obsolete, remove
   kEmptyTypeArguments,
-  kSymbol,
+  kSymbol, // TODO(alexmarkov): obsolete, remove
+  kInterfaceCallV1, // TODO(alexmarkov): obsolete, remove
+  kObjectRef,
+  kDirectCall,
   kInterfaceCall,
 }
 
@@ -289,6 +311,12 @@
         return new ConstantEmptyTypeArguments.read(reader);
       case ConstantTag.kSymbol:
         return new ConstantSymbol.read(reader);
+      case ConstantTag.kInterfaceCallV1:
+        return new ConstantInterfaceCallV1.read(reader);
+      case ConstantTag.kObjectRef:
+        return new ConstantObjectRef.read(reader);
+      case ConstantTag.kDirectCall:
+        return new ConstantDirectCall.read(reader);
       case ConstantTag.kInterfaceCall:
         return new ConstantInterfaceCall.read(reader);
     }
@@ -547,7 +575,7 @@
   String toString() => 'ICData '
       '${isDynamic ? 'dynamic ' : ''}'
       '${_invocationKindToString(invocationKind)}'
-      'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
+      'target-name $targetName, arg-desc CP#$argDescConstantIndex';
 
   // ConstantICData entries are created per call site and should not be merged,
   // so ConstantICData class uses identity [hashCode] and [operator ==].
@@ -1091,19 +1119,19 @@
   bool operator ==(other) => other is ConstantSymbol && this.name == other.name;
 }
 
-class ConstantInterfaceCall extends ConstantPoolEntry {
+class ConstantInterfaceCallV1 extends ConstantPoolEntry {
   final InvocationKind invocationKind;
   final ObjectHandle targetName;
   final int argDescConstantIndex;
 
-  ConstantInterfaceCall(
+  ConstantInterfaceCallV1(
       this.invocationKind, this.targetName, this.argDescConstantIndex);
 
   // Reserve 1 extra slot for arguments descriptor, following target name slot.
   int get numReservedEntries => 1;
 
   @override
-  ConstantTag get tag => ConstantTag.kInterfaceCall;
+  ConstantTag get tag => ConstantTag.kInterfaceCallV1;
 
   @override
   void writeValue(BufferedWriter writer) {
@@ -1112,15 +1140,15 @@
     writer.writePackedUInt30(argDescConstantIndex);
   }
 
-  ConstantInterfaceCall.read(BufferedReader reader)
+  ConstantInterfaceCallV1.read(BufferedReader reader)
       : invocationKind = InvocationKind.values[reader.readByte()],
         targetName = reader.readPackedObject(),
         argDescConstantIndex = reader.readPackedUInt30();
 
   @override
-  String toString() => 'InterfaceCall '
+  String toString() => 'InterfaceCallV1 '
       '${_invocationKindToString(invocationKind)}'
-      'target-name \'$targetName\', arg-desc CP#$argDescConstantIndex';
+      'target-name $targetName, arg-desc CP#$argDescConstantIndex';
 
   @override
   int get hashCode => _combineHashes(
@@ -1129,12 +1157,109 @@
 
   @override
   bool operator ==(other) =>
-      other is ConstantInterfaceCall &&
+      other is ConstantInterfaceCallV1 &&
       this.invocationKind == other.invocationKind &&
       this.targetName == other.targetName &&
       this.argDescConstantIndex == other.argDescConstantIndex;
 }
 
+class ConstantObjectRef extends ConstantPoolEntry {
+  final ObjectHandle object;
+
+  ConstantObjectRef(this.object);
+
+  @override
+  ConstantTag get tag => ConstantTag.kObjectRef;
+
+  @override
+  void writeValue(BufferedWriter writer) {
+    writer.writePackedObject(object);
+  }
+
+  ConstantObjectRef.read(BufferedReader reader)
+      : object = reader.readPackedObject();
+
+  @override
+  String toString() => 'ObjectRef $object';
+
+  @override
+  int get hashCode => object.hashCode;
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantObjectRef && this.object == other.object;
+}
+
+class ConstantDirectCall extends ConstantPoolEntry {
+  final ObjectHandle target;
+  final ObjectHandle argDesc;
+
+  ConstantDirectCall(this.target, this.argDesc);
+
+  // Reserve 1 extra slot for arguments descriptor, following target slot.
+  int get numReservedEntries => 1;
+
+  @override
+  ConstantTag get tag => ConstantTag.kDirectCall;
+
+  @override
+  void writeValue(BufferedWriter writer) {
+    writer.writePackedObject(target);
+    writer.writePackedObject(argDesc);
+  }
+
+  ConstantDirectCall.read(BufferedReader reader)
+      : target = reader.readPackedObject(),
+        argDesc = reader.readPackedObject();
+
+  @override
+  String toString() => "DirectCall '$target', $argDesc";
+
+  @override
+  int get hashCode => _combineHashes(target.hashCode, argDesc.hashCode);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantDirectCall &&
+      this.target == other.target &&
+      this.argDesc == other.argDesc;
+}
+
+class ConstantInterfaceCall extends ConstantPoolEntry {
+  final ObjectHandle target;
+  final ObjectHandle argDesc;
+
+  ConstantInterfaceCall(this.target, this.argDesc);
+
+  // Reserve 1 extra slot for arguments descriptor, following target slot.
+  int get numReservedEntries => 1;
+
+  @override
+  ConstantTag get tag => ConstantTag.kInterfaceCall;
+
+  @override
+  void writeValue(BufferedWriter writer) {
+    writer.writePackedObject(target);
+    writer.writePackedObject(argDesc);
+  }
+
+  ConstantInterfaceCall.read(BufferedReader reader)
+      : target = reader.readPackedObject(),
+        argDesc = reader.readPackedObject();
+
+  @override
+  String toString() => "InterfaceCall '$target', $argDesc";
+
+  @override
+  int get hashCode => _combineHashes(target.hashCode, argDesc.hashCode);
+
+  @override
+  bool operator ==(other) =>
+      other is ConstantInterfaceCall &&
+      this.target == other.target &&
+      this.argDesc == other.argDesc;
+}
+
 /// Reserved constant pool entry.
 class _ReservedConstantPoolEntry extends ConstantPoolEntry {
   const _ReservedConstantPoolEntry();
@@ -1156,25 +1281,17 @@
 
   ConstantPool(this.stringTable, this.objectTable);
 
-  int addNull() => _add(const ConstantNull());
-
-  int addString(String value) => _add(new ConstantString(_indexString(value)));
-
-  int addInt(int value) => _add(new ConstantInt(value));
-
-  int addDouble(double value) => _add(new ConstantDouble(value));
-
-  int addBool(bool value) => _add(new ConstantBool(value));
+  int addString(String value) => addObjectRef(new StringConstant(value));
 
   int addArgDesc(int numArguments,
           {int numTypeArgs = 0, List<String> argNames = const <String>[]}) =>
-      _add(new ConstantArgDesc(
-          numArguments, numTypeArgs, _indexStrings(argNames)));
+      _add(new ConstantObjectRef(
+          objectTable.getArgDescHandle(numArguments, numTypeArgs, argNames)));
 
   int addArgDescByArguments(Arguments args,
           {bool hasReceiver: false, bool isFactory: false}) =>
-      _add(new ConstantArgDesc.fromArguments(
-          _indexArgNames(args), hasReceiver, isFactory));
+      _add(new ConstantObjectRef(objectTable.getArgDescHandleByArguments(args,
+          hasReceiver: hasReceiver, isFactory: isFactory)));
 
   int addICData(
           InvocationKind invocationKind, Name targetName, int argDescCpIndex,
@@ -1187,30 +1304,29 @@
           argDescCpIndex,
           isDynamic));
 
-  int addStaticICData(
-          InvocationKind invocationKind, Member target, int argDescCpIndex) =>
-      _add(new ConstantStaticICData(
+  int addDirectCall(
+          InvocationKind invocationKind, Member target, ObjectHandle argDesc) =>
+      _add(new ConstantDirectCall(
           objectTable.getMemberHandle(target,
               isGetter: invocationKind == InvocationKind.getter,
               isSetter: invocationKind == InvocationKind.setter),
-          argDescCpIndex));
+          argDesc));
 
   int addInterfaceCall(
-          InvocationKind invocationKind, Name targetName, int argDescCpIndex) =>
+          InvocationKind invocationKind, Member target, ObjectHandle argDesc) =>
       _add(new ConstantInterfaceCall(
-          invocationKind,
-          objectTable.getSelectorNameHandle(targetName,
+          objectTable.getMemberHandle(target,
               isGetter: invocationKind == InvocationKind.getter,
               isSetter: invocationKind == InvocationKind.setter),
-          argDescCpIndex));
+          argDesc));
 
-  int addInstanceCall(
-          InvocationKind invocationKind, Name targetName, int argDescCpIndex,
-          {bool isDynamic: false}) =>
-      isDynamic
-          ? addICData(invocationKind, targetName, argDescCpIndex,
+  int addInstanceCall(InvocationKind invocationKind, Member target,
+          Name targetName, ObjectHandle argDesc) =>
+      (target == null)
+          ? addICData(
+              invocationKind, targetName, _add(new ConstantObjectRef(argDesc)),
               isDynamic: true)
-          : addInterfaceCall(invocationKind, targetName, argDescCpIndex);
+          : addInterfaceCall(invocationKind, target, argDesc);
 
   int addStaticField(Field field) =>
       _add(new ConstantStaticField(objectTable.getHandle(field)));
@@ -1224,30 +1340,11 @@
   int addTypeArgumentsField(Class node) =>
       _add(new ConstantTypeArgumentsField(objectTable.getHandle(node)));
 
-  int addTearOff(Procedure node) =>
-      _add(new ConstantTearOff(objectTable.getHandle(node)));
-
   int addType(DartType type) =>
       _add(new ConstantType(objectTable.getHandle(type)));
 
   int addTypeArguments(List<DartType> typeArgs) =>
-      _add(new ConstantTypeArguments(objectTable.getHandles(typeArgs)));
-
-  int addList(DartType typeArgument, List<int> entries) =>
-      _add(new ConstantList(objectTable.getHandle(typeArgument), entries));
-
-  int addInstance(
-          Class klass, int typeArgumentsCpIndex, Map<Field, int> fieldValues) =>
-      _add(new ConstantInstance(
-          objectTable.getHandle(klass),
-          typeArgumentsCpIndex,
-          fieldValues.map<ObjectHandle, int>((Field field, int valueCpIndex) =>
-              new MapEntry(objectTable.getHandle(field), valueCpIndex))));
-
-  int addTypeArgumentsForInstanceAllocation(
-          Class classNode, List<DartType> typeArgs) =>
-      _add(new ConstantTypeArgumentsForInstanceAllocation(
-          objectTable.getHandle(classNode), objectTable.getHandles(typeArgs)));
+      _add(new ConstantObjectRef(objectTable.getTypeArgumentsHandle(typeArgs)));
 
   int addClosureFunction(int closureIndex) =>
       _add(new ConstantClosureFunction(closureIndex));
@@ -1260,15 +1357,10 @@
 
   int addSubtypeTestCache() => _add(new ConstantSubtypeTestCache());
 
-  int addPartialTearOffInstantiation(
-          int tearOffCpIndex, int typeArgumentsCpIndex) =>
-      _add(new ConstantPartialTearOffInstantiation(
-          tearOffCpIndex, typeArgumentsCpIndex));
-
   int addEmptyTypeArguments() => _add(const ConstantEmptyTypeArguments());
 
-  int addSymbol(Library library, String name) =>
-      _add(new ConstantSymbol(objectTable.getNameHandle(library, name)));
+  int addObjectRef(Node node) =>
+      _add(new ConstantObjectRef(objectTable.getHandle(node)));
 
   int _add(ConstantPoolEntry entry) {
     return _canonicalizationCache.putIfAbsent(entry, () {
@@ -1296,26 +1388,12 @@
     return str;
   }
 
-  List<String> _indexStrings(List<String> strings) {
-    for (var str in strings) {
-      stringTable.put(str);
-    }
-    return strings;
-  }
-
-  Arguments _indexArgNames(Arguments args) {
-    for (var arg in args.named) {
-      stringTable.put(arg.name);
-    }
-    return args;
-  }
-
   void write(BufferedWriter writer) {
     final start = writer.offset;
     if (BytecodeSizeStatistics.constantPoolStats.isEmpty) {
       for (var tag in ConstantTag.values) {
         BytecodeSizeStatistics.constantPoolStats
-            .add(new ConstantPoolEntryStatistics(constantTagToString(tag)));
+            .add(new NamedEntryStatistics(constantTagToString(tag)));
       }
     }
     writer.writePackedUInt30(entries.length);
diff --git a/pkg/vm/lib/bytecode/dbc.dart b/pkg/vm/lib/bytecode/dbc.dart
index 6f7923a..c4b55c6 100644
--- a/pkg/vm/lib/bytecode/dbc.dart
+++ b/pkg/vm/lib/bytecode/dbc.dart
@@ -6,11 +6,11 @@
 
 library vm.bytecode.dbc;
 
-/// Version of stable bytecode format, produced by default.
-/// Before bumping stable bytecode version format, make sure that
+/// Version of bytecode format, produced by default.
+/// Before bumping current bytecode version format, make sure that
 /// all users have switched to a VM which is able to consume next
 /// version of bytecode.
-const int stableBytecodeFormatVersion = 1;
+const int stableBytecodeFormatVersion = 2;
 
 /// Version of bleeding edge bytecode format.
 /// Produced by bytecode generator when --use-future-bytecode-format
@@ -123,6 +123,8 @@
   kCompareIntLt,
   kCompareIntGe,
   kCompareIntLe,
+
+  kDirectCall,
 }
 
 enum Encoding {
@@ -298,6 +300,8 @@
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
   Opcode.kCompareIntLe: const Format(
       Encoding.k0, const [Operand.none, Operand.none, Operand.none]),
+  Opcode.kDirectCall: const Format(
+      Encoding.kAD, const [Operand.imm, Operand.lit, Operand.none]),
 };
 
 // Should match constant in runtime/vm/stack_frame_dbc.h.
@@ -318,6 +322,7 @@
     case Opcode.kInterfaceCall:
     case Opcode.kDynamicCall:
     case Opcode.kNativeCall:
+    case Opcode.kDirectCall:
       return true;
     default:
       return false;
diff --git a/pkg/vm/lib/bytecode/gen_bytecode.dart b/pkg/vm/lib/bytecode/gen_bytecode.dart
index cfbfd76..cecadf5 100644
--- a/pkg/vm/lib/bytecode/gen_bytecode.dart
+++ b/pkg/vm/lib/bytecode/gen_bytecode.dart
@@ -4,8 +4,6 @@
 
 library vm.bytecode.gen_bytecode;
 
-import 'dart:math' show min;
-
 import 'package:kernel/ast.dart' hide MapEntry;
 import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
 import 'package:kernel/core_types.dart' show CoreTypes;
@@ -27,6 +25,12 @@
 import 'constant_pool.dart';
 import 'dbc.dart';
 import 'exceptions.dart';
+import 'generics.dart'
+    show
+        flattenInstantiatorTypeArguments,
+        getInstantiatorTypeArguments,
+        hasFreeTypeParameters,
+        hasInstantiatorTypeArguments;
 import 'local_vars.dart' show LocalVariables;
 import 'nullability_detector.dart' show NullabilityDetector;
 import 'object_table.dart' show ObjectHandle, ObjectTable, NameAndType;
@@ -44,7 +48,7 @@
   bool emitSourcePositions: false,
   bool omitAssertSourcePositions: false,
   bool useFutureBytecodeFormat: false,
-  Map<String, String> environmentDefines,
+  Map<String, String> environmentDefines: const <String, String>{},
   ErrorReporter errorReporter,
   List<Library> libraries,
 }) {
@@ -53,8 +57,7 @@
   final hierarchy = new ClassHierarchy(component,
       onAmbiguousSupertypes: ignoreAmbiguousSupertypes);
   final typeEnvironment = new TypeEnvironment(coreTypes, hierarchy);
-  final constantsBackend =
-      new VmConstantsBackend(environmentDefines, coreTypes);
+  final constantsBackend = new VmConstantsBackend(coreTypes);
   final errorReporter = new ForwardConstantEvaluationErrors(typeEnvironment);
   libraries ??= component.libraries;
   final bytecodeGenerator = new BytecodeGenerator(
@@ -63,6 +66,7 @@
       hierarchy,
       typeEnvironment,
       constantsBackend,
+      environmentDefines,
       emitSourcePositions,
       omitAssertSourcePositions,
       useFutureBytecodeFormat,
@@ -78,6 +82,7 @@
   final ClassHierarchy hierarchy;
   final TypeEnvironment typeEnvironment;
   final ConstantsBackend constantsBackend;
+  final Map<String, String> environmentDefines;
   final bool emitSourcePositions;
   final bool omitAssertSourcePositions;
   final bool useFutureBytecodeFormat;
@@ -110,7 +115,6 @@
   Set<Field> initializedFields;
   List<ObjectHandle> nullableFields;
   ConstantPool cp;
-  ConstantEmitter constantEmitter;
   BytecodeAssembler asm;
   List<BytecodeAssembler> savedAssemblers;
   bool hasErrors;
@@ -122,6 +126,7 @@
       this.hierarchy,
       this.typeEnvironment,
       this.constantsBackend,
+      this.environmentDefines,
       this.emitSourcePositions,
       this.omitAssertSourcePositions,
       this.useFutureBytecodeFormat,
@@ -307,6 +312,18 @@
   Procedure get unsafeCast => _unsafeCast ??=
       libraryIndex.getTopLevelMember('dart:_internal', 'unsafeCast');
 
+  Procedure _iterableIterator;
+  Procedure get iterableIterator => _iterableIterator ??=
+      libraryIndex.getMember('dart:core', 'Iterable', 'get:iterator');
+
+  Procedure _iteratorMoveNext;
+  Procedure get iteratorMoveNext => _iteratorMoveNext ??=
+      libraryIndex.getMember('dart:core', 'Iterator', 'moveNext');
+
+  Procedure _iteratorCurrent;
+  Procedure get iteratorCurrent => _iteratorCurrent ??=
+      libraryIndex.getMember('dart:core', 'Iterator', 'get:current');
+
   void _recordSourcePosition(TreeNode node) {
     if (emitSourcePositions) {
       asm.currentSourcePosition = node.fileOffset;
@@ -390,7 +407,7 @@
     if (value.bitLength + 1 <= 16) {
       asm.emitPushInt(value);
     } else {
-      asm.emitPushConstant(cp.addInt(value));
+      asm.emitPushConstant(cp.addObjectRef(new IntConstant(value)));
     }
   }
 
@@ -418,7 +435,7 @@
     } else if (constant is IntConstant) {
       _genPushInt(constant.value);
     } else {
-      asm.emitPushConstant(constant.accept(constantEmitter));
+      asm.emitPushConstant(cp.addObjectRef(constant));
     }
   }
 
@@ -426,21 +443,20 @@
     asm.emitReturnTOS();
   }
 
-  void _genStaticCall(Member target, int argDescIndex, int totalArgCount,
+  void _genDirectCall(Member target, ObjectHandle argDesc, int totalArgCount,
       {bool isGet: false, bool isSet: false}) {
     assert(!isGet || !isSet);
     final kind = isGet
         ? InvocationKind.getter
         : (isSet ? InvocationKind.setter : InvocationKind.method);
-    final icdataIndex = cp.addStaticICData(kind, target, argDescIndex);
+    final cpIndex = cp.addDirectCall(kind, target, argDesc);
 
-    asm.emitPushConstant(icdataIndex);
-    asm.emitIndirectStaticCall(totalArgCount, argDescIndex);
+    asm.emitDirectCall(totalArgCount, cpIndex);
   }
 
-  void _genStaticCallWithArgs(Member target, Arguments args,
+  void _genDirectCallWithArgs(Member target, Arguments args,
       {bool hasReceiver: false, bool isFactory: false}) {
-    final int argDescIndex = cp.addArgDescByArguments(args,
+    final argDesc = objectTable.getArgDescHandleByArguments(args,
         hasReceiver: hasReceiver, isFactory: isFactory);
 
     int totalArgCount = args.positional.length + args.named.length;
@@ -453,22 +469,15 @@
       totalArgCount++;
     }
 
-    _genStaticCall(target, argDescIndex, totalArgCount);
-  }
-
-  bool hasFreeTypeParameters(List<DartType> typeArgs) {
-    final findTypeParams = new FindFreeTypeParametersVisitor();
-    return typeArgs.any((t) => t.accept(findTypeParams));
+    _genDirectCall(target, argDesc, totalArgCount);
   }
 
   void _genTypeArguments(List<DartType> typeArgs, {Class instantiatingClass}) {
     int typeArgsCPIndex() {
       if (instantiatingClass != null) {
-        return cp.addTypeArgumentsForInstanceAllocation(
-            instantiatingClass, typeArgs);
-      } else {
-        return cp.addTypeArguments(typeArgs);
+        typeArgs = getInstantiatorTypeArguments(instantiatingClass, typeArgs);
       }
+      return cp.addTypeArguments(typeArgs);
     }
 
     if (typeArgs.isEmpty || !hasFreeTypeParameters(typeArgs)) {
@@ -477,7 +486,7 @@
       final flattenedTypeArgs = (instantiatingClass != null &&
               (instantiatorTypeArguments != null ||
                   functionTypeParameters != null))
-          ? _flattenInstantiatorTypeArguments(instantiatingClass, typeArgs)
+          ? flattenInstantiatorTypeArguments(instantiatingClass, typeArgs)
           : typeArgs;
       if (_canReuseInstantiatorTypeArguments(flattenedTypeArgs)) {
         _genPushInstantiatorTypeArguments();
@@ -529,52 +538,6 @@
     }
   }
 
-  bool _canReuseSuperclassTypeArguments(List<DartType> superTypeArgs,
-      List<TypeParameter> typeParameters, int overlap) {
-    for (int i = 0; i < overlap; ++i) {
-      final superTypeArg = superTypeArgs[superTypeArgs.length - overlap + i];
-      if (!(superTypeArg is TypeParameterType &&
-          superTypeArg.parameter == typeParameters[i])) {
-        return false;
-      }
-    }
-    return true;
-  }
-
-  List<DartType> _flattenInstantiatorTypeArguments(
-      Class instantiatedClass, List<DartType> typeArgs) {
-    final typeParameters = instantiatedClass.typeParameters;
-    assert(typeArgs.length == typeParameters.length);
-
-    final supertype = instantiatedClass.supertype;
-    if (supertype == null) {
-      return typeArgs;
-    }
-
-    final superTypeArgs = _flattenInstantiatorTypeArguments(
-        supertype.classNode, supertype.typeArguments);
-
-    // Shrink type arguments by reusing portion of superclass type arguments
-    // if there is an overlapping. This optimization should be consistent with
-    // VM in order to correctly reuse instantiator type arguments.
-    int overlap = min(superTypeArgs.length, typeArgs.length);
-    for (; overlap > 0; --overlap) {
-      if (_canReuseSuperclassTypeArguments(
-          superTypeArgs, typeParameters, overlap)) {
-        break;
-      }
-    }
-
-    final substitution = Substitution.fromPairs(typeParameters, typeArgs);
-
-    List<DartType> flatTypeArgs = <DartType>[];
-    flatTypeArgs
-        .addAll(superTypeArgs.map((t) => substitution.substituteType(t)));
-    flatTypeArgs.addAll(typeArgs.getRange(overlap, typeArgs.length));
-
-    return flatTypeArgs;
-  }
-
   bool _canReuseInstantiatorTypeArguments(List<DartType> typeArgs) {
     if (instantiatorTypeArguments == null) {
       return false;
@@ -738,10 +701,10 @@
 
   int _getDefaultParamConstIndex(VariableDeclaration param) {
     if (param.initializer == null) {
-      return cp.addNull();
+      return cp.addObjectRef(null);
     }
     final constant = _evaluateConstantExpression(param.initializer);
-    return constant.accept(constantEmitter);
+    return cp.addObjectRef(constant);
   }
 
   // Duplicates value on top of the stack using temporary variable with
@@ -764,10 +727,10 @@
     if (type is InterfaceType && type.typeArguments.isEmpty) {
       assert(type.classNode.typeParameters.isEmpty);
       asm.emitPushConstant(cp.addType(type));
-      final argDescIndex = cp.addArgDesc(2);
-      final icdataIndex = cp.addInterfaceCall(
-          InvocationKind.method, objectSimpleInstanceOf.name, argDescIndex);
-      asm.emitInterfaceCall(2, icdataIndex);
+      final argDesc = objectTable.getArgDescHandle(2);
+      final cpIndex = cp.addInterfaceCall(
+          InvocationKind.method, objectSimpleInstanceOf, argDesc);
+      asm.emitInterfaceCall(2, cpIndex);
       return;
     }
 
@@ -778,10 +741,10 @@
       asm.emitPushNull(); // Function type arguments.
     }
     asm.emitPushConstant(cp.addType(type));
-    final argDescIndex = cp.addArgDesc(4);
-    final icdataIndex = cp.addInterfaceCall(
-        InvocationKind.method, objectInstanceOf.name, argDescIndex);
-    asm.emitInterfaceCall(4, icdataIndex);
+    final argDesc = objectTable.getArgDescHandle(4);
+    final cpIndex =
+        cp.addInterfaceCall(InvocationKind.method, objectInstanceOf, argDesc);
+    asm.emitInterfaceCall(4, cpIndex);
   }
 
   void start(Member node) {
@@ -812,7 +775,7 @@
             .map((p) => new TypeParameterType(p))
             .toList();
         instantiatorTypeArguments =
-            _flattenInstantiatorTypeArguments(enclosingClass, typeParameters);
+            flattenInstantiatorTypeArguments(enclosingClass, typeParameters);
       }
     }
     if (enclosingFunction != null &&
@@ -823,8 +786,12 @@
     }
     locals = new LocalVariables(node);
     // TODO(alexmarkov): improve caching in ConstantEvaluator and reuse it
-    constantEvaluator = new ConstantEvaluator(constantsBackend, typeEnvironment,
-        coreTypes, /* enableAsserts = */ true, errorReporter)
+    constantEvaluator = new ConstantEvaluator(
+        constantsBackend,
+        environmentDefines,
+        typeEnvironment,
+        /* enableAsserts = */ true,
+        errorReporter)
       ..env = new EvaluationEnvironment();
     labeledStatements = <LabeledStatement, Label>{};
     switchCases = <SwitchCase, Label>{};
@@ -836,7 +803,6 @@
     initializedFields = null; // Tracked for constructors only.
     nullableFields = const <ObjectHandle>[];
     cp = new ConstantPool(stringTable, objectTable);
-    constantEmitter = new ConstantEmitter(cp);
     asm = new BytecodeAssembler();
     savedAssemblers = <BytecodeAssembler>[];
     currentLoopDepth = 0;
@@ -900,7 +866,6 @@
     initializedFields = null;
     nullableFields = null;
     cp = null;
-    constantEmitter = null;
     asm = null;
     savedAssemblers = null;
     hasErrors = false;
@@ -973,7 +938,8 @@
               cp.addInstanceField(closureFunctionTypeArguments));
           _genPushInt(numParentTypeArgs);
           _genPushInt(numParentTypeArgs + function.typeParameters.length);
-          _genStaticCall(prependTypeArguments, cp.addArgDesc(4), 4);
+          _genDirectCall(
+              prependTypeArguments, objectTable.getArgDescHandle(4), 4);
           asm.emitPopLocal(locals.functionTypeArgsVarIndexInFrame);
         } else {
           asm.emitPush(locals.closureVarIndexInFrame);
@@ -1600,12 +1566,13 @@
     // Argument 3 for _allocateInvocationMirror(): isSuperInvocation flag.
     asm.emitPushTrue();
 
-    _genStaticCall(allocateInvocationMirror, cp.addArgDesc(4), 4);
+    _genDirectCall(
+        allocateInvocationMirror, objectTable.getArgDescHandle(4), 4);
 
     final Member target = hierarchy.getDispatchTarget(
         enclosingClass.superclass, new Name('noSuchMethod'));
     assert(target != null);
-    _genStaticCall(target, cp.addArgDesc(2), 2);
+    _genDirectCall(target, objectTable.getArgDescHandle(2), 2);
   }
 
   @override
@@ -1636,7 +1603,7 @@
 
   @override
   visitDoubleLiteral(DoubleLiteral node) {
-    final cpIndex = cp.addDouble(node.value);
+    final cpIndex = cp.addObjectRef(new DoubleConstant(node.value));
     asm.emitPushConstant(cpIndex);
   }
 
@@ -1688,7 +1655,7 @@
         new Arguments(node.arguments.positional, named: node.arguments.named)
           ..parent = node;
     _genArguments(null, args);
-    _genStaticCallWithArgs(node.target, args, hasReceiver: true);
+    _genDirectCallWithArgs(node.target, args, hasReceiver: true);
     asm.emitDrop1();
   }
 
@@ -1698,7 +1665,7 @@
     _genArguments(node.receiver, args);
     final target = node.target;
     if (target is Procedure && !target.isGetter && !target.isSetter) {
-      _genStaticCallWithArgs(target, args, hasReceiver: true);
+      _genDirectCallWithArgs(target, args, hasReceiver: true);
     } else {
       throw new UnsupportedOperationError(
           'Unsupported DirectMethodInvocation with target ${target.runtimeType} $target');
@@ -1710,7 +1677,7 @@
     _generateNode(node.receiver);
     final target = node.target;
     if (target is Field || (target is Procedure && target.isGetter)) {
-      _genStaticCall(target, cp.addArgDesc(1), 1, isGet: true);
+      _genDirectCall(target, objectTable.getArgDescHandle(1), 1, isGet: true);
     } else {
       throw new UnsupportedOperationError(
           'Unsupported DirectPropertyGet with ${target.runtimeType} $target');
@@ -1731,7 +1698,7 @@
 
     final target = node.target;
     assert(target is Field || (target is Procedure && target.isSetter));
-    _genStaticCall(target, cp.addArgDesc(2), 2, isSet: true);
+    _genDirectCall(target, objectTable.getArgDescHandle(2), 2, isSet: true);
     asm.emitDrop1();
 
     if (hasResult) {
@@ -1756,7 +1723,8 @@
     _genTypeArguments(node.typeArguments);
     asm.emitStoreLocal(typeArguments);
 
-    _genStaticCall(boundsCheckForPartialInstantiation, cp.addArgDesc(2), 2);
+    _genDirectCall(
+        boundsCheckForPartialInstantiation, objectTable.getArgDescHandle(2), 2);
     asm.emitDrop1();
 
     assert(closureClass.typeParameters.isEmpty);
@@ -1827,7 +1795,7 @@
     // Type arguments passed to a factory constructor are counted as a normal
     // argument and not counted in number of type arguments.
     assert(listFromLiteral.isFactory);
-    _genStaticCall(listFromLiteral, cp.addArgDesc(2, numTypeArgs: 0), 2);
+    _genDirectCall(listFromLiteral, objectTable.getArgDescHandle(2), 2);
   }
 
   @override
@@ -1866,7 +1834,8 @@
     _genTypeArguments([node.keyType, node.valueType]);
 
     if (node.entries.isEmpty) {
-      asm.emitPushConstant(cp.addList(const DynamicType(), const []));
+      asm.emitPushConstant(
+          cp.addObjectRef(new ListConstant(const DynamicType(), const [])));
     } else {
       _genTypeArguments([const DynamicType()]);
       _genPushInt(node.entries.length * 2);
@@ -1893,7 +1862,7 @@
     // Type arguments passed to a factory constructor are counted as a normal
     // argument and not counted in number of type arguments.
     assert(mapFromLiteral.isFactory);
-    _genStaticCall(mapFromLiteral, cp.addArgDesc(2, numTypeArgs: 0), 2);
+    _genDirectCall(mapFromLiteral, objectTable.getArgDescHandle(2), 2);
   }
 
   void _genMethodInvocationUsingSpecializedBytecode(
@@ -1937,11 +1906,11 @@
     asm.emitBytecode0(opcode);
   }
 
-  void _genInstanceCall(int totalArgCount, int icdataCpIndex, bool isDynamic) {
+  void _genInstanceCall(int totalArgCount, int callCpIndex, bool isDynamic) {
     if (isDynamic) {
-      asm.emitDynamicCall(totalArgCount, icdataCpIndex);
+      asm.emitDynamicCall(totalArgCount, callCpIndex);
     } else {
-      asm.emitInterfaceCall(totalArgCount, icdataCpIndex);
+      asm.emitInterfaceCall(totalArgCount, callCpIndex);
     }
   }
 
@@ -1953,28 +1922,34 @@
       return;
     }
     final args = node.arguments;
-    final isDynamic = node.interfaceTarget == null;
+    Member interfaceTarget = node.interfaceTarget;
+    if (interfaceTarget is Field ||
+        interfaceTarget is Procedure && interfaceTarget.isGetter) {
+      // Call via field or getter. Treat it as a dynamic call because
+      // interface target doesn't fully represent what is being called.
+      interfaceTarget = null;
+    }
+    final isDynamic = interfaceTarget == null;
     _genArguments(node.receiver, args);
-    final argDescIndex = cp.addArgDescByArguments(args, hasReceiver: true);
-    final icdataIndex = cp.addInstanceCall(
-        InvocationKind.method, node.name, argDescIndex,
-        isDynamic: isDynamic);
+    final argDesc =
+        objectTable.getArgDescHandleByArguments(args, hasReceiver: true);
+    final callCpIndex = cp.addInstanceCall(
+        InvocationKind.method, interfaceTarget, node.name, argDesc);
     final totalArgCount = args.positional.length +
         args.named.length +
         1 /* receiver */ +
         (args.types.isNotEmpty ? 1 : 0) /* type arguments */;
-    _genInstanceCall(totalArgCount, icdataIndex, isDynamic);
+    _genInstanceCall(totalArgCount, callCpIndex, isDynamic);
   }
 
   @override
   visitPropertyGet(PropertyGet node) {
     _generateNode(node.receiver);
     final isDynamic = node.interfaceTarget == null;
-    final argDescIndex = cp.addArgDesc(1);
-    final icdataIndex = cp.addInstanceCall(
-        InvocationKind.getter, node.name, argDescIndex,
-        isDynamic: isDynamic);
-    _genInstanceCall(1, icdataIndex, isDynamic);
+    final argDesc = objectTable.getArgDescHandle(1);
+    final callCpIndex = cp.addInstanceCall(
+        InvocationKind.getter, node.interfaceTarget, node.name, argDesc);
+    _genInstanceCall(1, callCpIndex, isDynamic);
   }
 
   @override
@@ -1990,11 +1965,10 @@
     }
 
     final isDynamic = node.interfaceTarget == null;
-    final argDescIndex = cp.addArgDesc(2);
-    final icdataIndex = cp.addInstanceCall(
-        InvocationKind.setter, node.name, argDescIndex,
-        isDynamic: isDynamic);
-    _genInstanceCall(2, icdataIndex, isDynamic);
+    final argDesc = objectTable.getArgDescHandle(2);
+    final callCpIndex = cp.addInstanceCall(
+        InvocationKind.setter, node.interfaceTarget, node.name, argDesc);
+    _genInstanceCall(2, callCpIndex, isDynamic);
     asm.emitDrop1();
 
     if (hasResult) {
@@ -2020,7 +1994,7 @@
       return;
     }
     _genArguments(new ThisExpression(), args);
-    _genStaticCallWithArgs(target, args, hasReceiver: true);
+    _genDirectCallWithArgs(target, args, hasReceiver: true);
   }
 
   @override
@@ -2034,7 +2008,7 @@
       return;
     }
     _genPushReceiver();
-    _genStaticCall(target, cp.addArgDesc(1), 1, isGet: true);
+    _genDirectCall(target, objectTable.getArgDescHandle(1), 1, isGet: true);
   }
 
   @override
@@ -2057,7 +2031,7 @@
       }
 
       assert(target is Field || (target is Procedure && target.isSetter));
-      _genStaticCall(target, cp.addArgDesc(2), 2, isSet: true);
+      _genDirectCall(target, objectTable.getArgDescHandle(2), 2, isSet: true);
     }
 
     asm.emitDrop1();
@@ -2116,14 +2090,13 @@
             fieldIndex); // TODO(alexmarkov): do we really need this?
         asm.emitPushStatic(fieldIndex);
       } else {
-        _genStaticCall(target, cp.addArgDesc(0), 0, isGet: true);
+        _genDirectCall(target, objectTable.getArgDescHandle(0), 0, isGet: true);
       }
     } else if (target is Procedure) {
       if (target.isGetter) {
-        _genStaticCall(target, cp.addArgDesc(0), 0, isGet: true);
+        _genDirectCall(target, objectTable.getArgDescHandle(0), 0, isGet: true);
       } else {
-        final tearOffIndex = cp.addTearOff(target);
-        asm.emitPushConstant(tearOffIndex);
+        asm.emitPushConstant(cp.addObjectRef(new TearOffConstant(target)));
       }
     } else {
       throw 'Unexpected target for StaticGet: ${target.runtimeType} $target';
@@ -2160,7 +2133,7 @@
             ..parent = node;
     }
     _genArguments(null, args);
-    _genStaticCallWithArgs(target, args, isFactory: target.isFactory);
+    _genDirectCallWithArgs(target, args, isFactory: target.isFactory);
   }
 
   @override
@@ -2178,7 +2151,7 @@
       int cpIndex = cp.addStaticField(target);
       asm.emitStoreStaticTOS(cpIndex);
     } else {
-      _genStaticCall(target, cp.addArgDesc(1), 1, isSet: true);
+      _genDirectCall(target, objectTable.getArgDescHandle(1), 1, isSet: true);
       asm.emitDrop1();
     }
   }
@@ -2187,7 +2160,7 @@
   visitStringConcatenation(StringConcatenation node) {
     if (node.expressions.length == 1) {
       _generateNode(node.expressions.single);
-      _genStaticCall(interpolateSingle, cp.addArgDesc(1), 1);
+      _genDirectCall(interpolateSingle, objectTable.getArgDescHandle(1), 1);
     } else {
       asm.emitPushNull();
       _genPushInt(node.expressions.length);
@@ -2203,7 +2176,7 @@
         asm.emitStoreIndexedTOS();
       }
 
-      _genStaticCall(interpolate, cp.addArgDesc(1), 1);
+      _genDirectCall(interpolate, objectTable.getArgDescHandle(1), 1);
     }
   }
 
@@ -2285,7 +2258,7 @@
 
   void _genFutureNull() {
     asm.emitPushNull();
-    _genStaticCall(futureValue, cp.addArgDesc(1), 1);
+    _genDirectCall(futureValue, objectTable.getArgDescHandle(1), 1);
   }
 
   @override
@@ -2314,7 +2287,7 @@
       asm.emitPushNull();
     }
 
-    _genStaticCall(throwNewAssertionError, cp.addArgDesc(3), 3);
+    _genDirectCall(throwNewAssertionError, objectTable.getArgDescHandle(3), 3);
     asm.emitDrop1();
 
     asm.bind(done);
@@ -2401,16 +2374,12 @@
   visitForInStatement(ForInStatement node) {
     _generateNode(node.iterable);
 
-    const kIterator = 'iterator'; // Iterable.iterator
-    const kMoveNext = 'moveNext'; // Iterator.moveNext
-    const kCurrent = 'current'; // Iterator.current
-
     // Front-end inserts implicit cast (type check) which ensures that
     // result of iterable expression is Iterable<dynamic>.
     asm.emitInterfaceCall(
         1,
-        cp.addInterfaceCall(
-            InvocationKind.getter, new Name(kIterator), cp.addArgDesc(1)));
+        cp.addInterfaceCall(InvocationKind.getter, iterableIterator,
+            objectTable.getArgDescHandle(1)));
 
     final iteratorTemp = locals.tempIndexInFrame(node);
     asm.emitPopLocal(iteratorTemp);
@@ -2443,8 +2412,8 @@
 
     asm.emitInterfaceCall(
         1,
-        cp.addInterfaceCall(
-            InvocationKind.method, new Name(kMoveNext), cp.addArgDesc(1)));
+        cp.addInterfaceCall(InvocationKind.method, iteratorMoveNext,
+            objectTable.getArgDescHandle(1)));
     _genJumpIfFalse(/* negated = */ false, done);
 
     _enterScope(node);
@@ -2454,8 +2423,8 @@
     asm.emitPush(iteratorTemp);
     asm.emitInterfaceCall(
         1,
-        cp.addInterfaceCall(
-            InvocationKind.getter, new Name(kCurrent), cp.addArgDesc(1)));
+        cp.addInterfaceCall(InvocationKind.getter, iteratorCurrent,
+            objectTable.getArgDescHandle(1)));
 
     _genStoreVar(node.variable);
 
@@ -2597,7 +2566,7 @@
     final Label done = new Label();
     final List<Label> caseLabels = new List<Label>.generate(
         node.cases.length, (_) => new Label(allowsBackwardJumps: true));
-    final equalsArgDesc = cp.addArgDesc(2);
+    final equalsArgDesc = objectTable.getArgDescHandle(2);
 
     Label defaultLabel = done;
     for (int i = 0; i < node.cases.length; i++) {
@@ -2613,8 +2582,8 @@
           _genPushConstExpr(expr);
           asm.emitInterfaceCall(
               2,
-              cp.addInterfaceCall(
-                  InvocationKind.method, new Name('=='), equalsArgDesc));
+              cp.addInterfaceCall(InvocationKind.method, coreTypes.objectEquals,
+                  equalsArgDesc));
           _genJumpIfTrue(/* negated = */ false, caseLabel);
         }
       }
@@ -2968,7 +2937,7 @@
     final args = node.arguments;
     assert(args.types.isEmpty);
     _genArguments(new ThisExpression(), args);
-    _genStaticCallWithArgs(node.target, args, hasReceiver: true);
+    _genDirectCallWithArgs(node.target, args, hasReceiver: true);
     asm.emitDrop1();
   }
 
@@ -2986,7 +2955,7 @@
       }
     }
     assert(target != null);
-    _genStaticCallWithArgs(target, args, hasReceiver: true);
+    _genDirectCallWithArgs(target, args, hasReceiver: true);
     asm.emitDrop1();
   }
 
@@ -3006,62 +2975,6 @@
   }
 }
 
-class ConstantEmitter extends ConstantVisitor<int> {
-  final ConstantPool cp;
-
-  ConstantEmitter(this.cp);
-
-  @override
-  int defaultConstant(Constant node) => throw new UnsupportedOperationError(
-      'Unsupported constant node ${node.runtimeType}');
-
-  @override
-  int visitNullConstant(NullConstant node) => cp.addNull();
-
-  @override
-  int visitBoolConstant(BoolConstant node) => cp.addBool(node.value);
-
-  @override
-  int visitIntConstant(IntConstant node) => cp.addInt(node.value);
-
-  @override
-  int visitDoubleConstant(DoubleConstant node) => cp.addDouble(node.value);
-
-  @override
-  int visitStringConstant(StringConstant node) => cp.addString(node.value);
-
-  @override
-  int visitSymbolConstant(SymbolConstant node) =>
-      cp.addSymbol(node.libraryReference?.asLibrary, node.name);
-
-  @override
-  int visitListConstant(ListConstant node) => cp.addList(node.typeArgument,
-      new List<int>.from(node.entries.map((Constant c) => c.accept(this))));
-
-  @override
-  int visitInstanceConstant(InstanceConstant node) => cp.addInstance(
-      node.classNode,
-      hasInstantiatorTypeArguments(node.classNode)
-          ? cp.addTypeArgumentsForInstanceAllocation(
-              node.classNode, node.typeArguments)
-          : cp.addNull(),
-      node.fieldValues.map<Field, int>((Reference fieldRef, Constant value) =>
-          new MapEntry(fieldRef.asField, value.accept(this))));
-
-  @override
-  int visitTearOffConstant(TearOffConstant node) =>
-      cp.addTearOff(node.procedure);
-
-  @override
-  int visitTypeLiteralConstant(TypeLiteralConstant node) =>
-      cp.addType(node.type);
-
-  @override
-  int visitPartialInstantiationConstant(PartialInstantiationConstant node) =>
-      cp.addPartialTearOffInstantiation(
-          node.tearOffConstant.accept(this), cp.addTypeArguments(node.types));
-}
-
 class UnsupportedOperationError {
   final String message;
   UnsupportedOperationError(this.message);
@@ -3070,59 +2983,6 @@
   String toString() => message;
 }
 
-class FindFreeTypeParametersVisitor extends DartTypeVisitor<bool> {
-  Set<TypeParameter> _declaredTypeParameters;
-
-  bool visit(DartType type) => type.accept(this);
-
-  @override
-  bool defaultDartType(DartType node) =>
-      throw 'Unexpected type ${node.runtimeType} $node';
-
-  @override
-  bool visitInvalidType(InvalidType node) => false;
-
-  @override
-  bool visitDynamicType(DynamicType node) => false;
-
-  @override
-  bool visitVoidType(VoidType node) => false;
-
-  @override
-  bool visitBottomType(BottomType node) => false;
-
-  @override
-  bool visitTypeParameterType(TypeParameterType node) =>
-      _declaredTypeParameters == null ||
-      !_declaredTypeParameters.contains(node.parameter);
-
-  @override
-  bool visitInterfaceType(InterfaceType node) =>
-      node.typeArguments.any((t) => t.accept(this));
-
-  @override
-  bool visitTypedefType(TypedefType node) =>
-      node.typeArguments.any((t) => t.accept(this));
-
-  @override
-  bool visitFunctionType(FunctionType node) {
-    if (node.typeParameters.isNotEmpty) {
-      _declaredTypeParameters ??= new Set<TypeParameter>();
-      _declaredTypeParameters.addAll(node.typeParameters);
-    }
-
-    final bool result = node.positionalParameters.any((t) => t.accept(this)) ||
-        node.namedParameters.any((p) => p.type.accept(this)) ||
-        node.returnType.accept(this);
-
-    if (node.typeParameters.isNotEmpty) {
-      _declaredTypeParameters.removeAll(node.typeParameters);
-    }
-
-    return result;
-  }
-}
-
 typedef void GenerateContinuation();
 
 class FinallyBlock {
@@ -3131,8 +2991,3 @@
 
   FinallyBlock(this.generateContinuation);
 }
-
-bool hasInstantiatorTypeArguments(Class c) {
-  return c.typeParameters.isNotEmpty ||
-      (c.superclass != null && hasInstantiatorTypeArguments(c.superclass));
-}
diff --git a/pkg/vm/lib/bytecode/generics.dart b/pkg/vm/lib/bytecode/generics.dart
new file mode 100644
index 0000000..70b6327
--- /dev/null
+++ b/pkg/vm/lib/bytecode/generics.dart
@@ -0,0 +1,228 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library vm.bytecode.generics;
+
+import 'dart:math' show min;
+
+import 'package:kernel/ast.dart' hide MapEntry;
+import 'package:kernel/type_algebra.dart' show Substitution;
+
+bool hasInstantiatorTypeArguments(Class c) {
+  for (; c != null; c = c.superclass) {
+    if (c.typeParameters.isNotEmpty) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool _canReuseSuperclassTypeArguments(List<DartType> superTypeArgs,
+    List<TypeParameter> typeParameters, int overlap) {
+  for (int i = 0; i < overlap; ++i) {
+    final superTypeArg = superTypeArgs[superTypeArgs.length - overlap + i];
+    if (!(superTypeArg is TypeParameterType &&
+        superTypeArg.parameter == typeParameters[i])) {
+      return false;
+    }
+  }
+  return true;
+}
+
+List<DartType> flattenInstantiatorTypeArguments(
+    Class instantiatedClass, List<DartType> typeArgs) {
+  final typeParameters = instantiatedClass.typeParameters;
+  assert(typeArgs.length == typeParameters.length);
+
+  final supertype = instantiatedClass.supertype;
+  if (supertype == null) {
+    return typeArgs;
+  }
+
+  final superTypeArgs = flattenInstantiatorTypeArguments(
+      supertype.classNode, supertype.typeArguments);
+
+  // Shrink type arguments by reusing portion of superclass type arguments
+  // if there is an overlapping. This optimization should be consistent with
+  // VM in order to correctly reuse instantiator type arguments.
+  int overlap = min(superTypeArgs.length, typeArgs.length);
+  for (; overlap > 0; --overlap) {
+    if (_canReuseSuperclassTypeArguments(
+        superTypeArgs, typeParameters, overlap)) {
+      break;
+    }
+  }
+
+  final substitution = Substitution.fromPairs(typeParameters, typeArgs);
+
+  List<DartType> flatTypeArgs = <DartType>[];
+  flatTypeArgs.addAll(superTypeArgs.map((t) => substitution.substituteType(t)));
+  flatTypeArgs.addAll(typeArgs.getRange(overlap, typeArgs.length));
+
+  return flatTypeArgs;
+}
+
+List<DartType> getInstantiatorTypeArguments(
+    Class instantiatedClass, List<DartType> typeArgs) {
+  final flatTypeArgs =
+      flattenInstantiatorTypeArguments(instantiatedClass, typeArgs);
+  if (_isAllDynamic(flatTypeArgs)) {
+    return null;
+  }
+  return flatTypeArgs;
+}
+
+bool _isAllDynamic(List<DartType> typeArgs) {
+  for (var t in typeArgs) {
+    if (t != const DynamicType()) {
+      return false;
+    }
+  }
+  return true;
+}
+
+bool hasFreeTypeParameters(List<DartType> typeArgs) {
+  final findTypeParams = new FindFreeTypeParametersVisitor();
+  return typeArgs.any((t) => t.accept(findTypeParams));
+}
+
+class FindFreeTypeParametersVisitor extends DartTypeVisitor<bool> {
+  Set<TypeParameter> _declaredTypeParameters;
+
+  bool visit(DartType type) => type.accept(this);
+
+  @override
+  bool defaultDartType(DartType node) =>
+      throw 'Unexpected type ${node.runtimeType} $node';
+
+  @override
+  bool visitInvalidType(InvalidType node) => false;
+
+  @override
+  bool visitDynamicType(DynamicType node) => false;
+
+  @override
+  bool visitVoidType(VoidType node) => false;
+
+  @override
+  bool visitBottomType(BottomType node) => false;
+
+  @override
+  bool visitTypeParameterType(TypeParameterType node) =>
+      _declaredTypeParameters == null ||
+      !_declaredTypeParameters.contains(node.parameter);
+
+  @override
+  bool visitInterfaceType(InterfaceType node) =>
+      node.typeArguments.any((t) => t.accept(this));
+
+  @override
+  bool visitTypedefType(TypedefType node) =>
+      node.typeArguments.any((t) => t.accept(this));
+
+  @override
+  bool visitFunctionType(FunctionType node) {
+    if (node.typeParameters.isNotEmpty) {
+      _declaredTypeParameters ??= new Set<TypeParameter>();
+      _declaredTypeParameters.addAll(node.typeParameters);
+    }
+
+    final bool result = node.positionalParameters.any((t) => t.accept(this)) ||
+        node.namedParameters.any((p) => p.type.accept(this)) ||
+        node.returnType.accept(this);
+
+    if (node.typeParameters.isNotEmpty) {
+      _declaredTypeParameters.removeAll(node.typeParameters);
+    }
+
+    return result;
+  }
+}
+
+/// Returns true if the given type is recursive after its type arguments
+/// are flattened.
+bool isRecursiveAfterFlattening(InterfaceType type) {
+  final visitor = new IsRecursiveAfterFlatteningVisitor();
+  visitor.visit(type);
+  return visitor.isRecursive(type);
+}
+
+class IsRecursiveAfterFlatteningVisitor extends DartTypeVisitor<void> {
+  Set<DartType> _visited = new Set<DartType>();
+  List<DartType> _stack = <DartType>[];
+  Set<DartType> _recursive;
+
+  bool isRecursive(DartType type) =>
+      _recursive != null && _recursive.contains(type);
+
+  void visit(DartType type) {
+    if (!_visited.add(type)) {
+      _recordRecursiveType(type);
+      return;
+    }
+    _stack.add(type);
+
+    type.accept(this);
+
+    _stack.removeLast();
+    _visited.remove(type);
+  }
+
+  void _recordRecursiveType(DartType type) {
+    final int start = _stack.lastIndexOf(type);
+    final recursive = (_recursive ??= new Set<DartType>());
+    for (int i = start; i < _stack.length; ++i) {
+      recursive.add(_stack[i]);
+    }
+  }
+
+  @override
+  void defaultDartType(DartType node) =>
+      throw 'Unexpected type ${node.runtimeType} $node';
+
+  @override
+  void visitInvalidType(InvalidType node) {}
+
+  @override
+  void visitDynamicType(DynamicType node) {}
+
+  @override
+  void visitVoidType(VoidType node) {}
+
+  @override
+  void visitBottomType(BottomType node) {}
+
+  @override
+  void visitTypeParameterType(TypeParameterType node) {}
+
+  @override
+  void visitInterfaceType(InterfaceType node) {
+    for (var typeArg in node.typeArguments) {
+      visit(typeArg);
+    }
+    if (isRecursive(node)) {
+      return;
+    }
+    final flatTypeArgs =
+        flattenInstantiatorTypeArguments(node.classNode, node.typeArguments);
+    for (var typeArg in flatTypeArgs.getRange(
+        0, flatTypeArgs.length - node.typeArguments.length)) {
+      visit(typeArg);
+    }
+  }
+
+  @override
+  void visitTypedefType(TypedefType node) => visit(node.unalias);
+
+  @override
+  void visitFunctionType(FunctionType node) {
+    for (var p in node.positionalParameters) {
+      visit(p);
+    }
+    for (var p in node.namedParameters) {
+      visit(p.type);
+    }
+    visit(node.returnType);
+  }
+}
diff --git a/pkg/vm/lib/bytecode/object_table.dart b/pkg/vm/lib/bytecode/object_table.dart
index baa1460..fd54b70 100644
--- a/pkg/vm/lib/bytecode/object_table.dart
+++ b/pkg/vm/lib/bytecode/object_table.dart
@@ -13,9 +13,14 @@
         BufferedReader,
         BytecodeObject,
         BytecodeSizeStatistics,
+        NamedEntryStatistics,
+        doubleToIntBits,
+        intBitsToDouble,
         ObjectReader,
         ObjectWriter,
         StringWriter;
+import 'generics.dart'
+    show getInstantiatorTypeArguments, isRecursiveAfterFlattening;
 
 /*
 
@@ -142,6 +147,88 @@
   PackedString string;
 }
 
+// Type arguments vector.
+type TypeArguments extends ObjectContents {
+  kind = 10;
+  List<PackedObject> args;
+}
+
+type FinalizedGenericType extends ObjectContents {
+  kind = 11;
+  PackedObject class;
+  PackedObject typeArgs;
+}
+
+abstract type ConstObject extends ObjectContents {
+  kind = 12;
+  flags = constantTag (4 bits)
+}
+
+type ConstInstance extends ConstObject {
+  kind = 12
+  constantTag (flags) = 1
+  PackedObject type;
+  List<Pair<PackedObject, PackedObject>> fieldValues;
+}
+
+type ConstInt extends ConstValue {
+  kind = 12
+  constantTag (flags) = 2
+  SLEB128 value;
+}
+
+type ConstDouble extends ConstValue {
+  kind = 12
+  constantTag (flags) = 3
+  // double bits are converted to int
+  SLEB128 value;
+}
+
+type ConstList extends ConstObject {
+  kind = 12
+  constantTag (flags) = 4
+  PackedObject elemType;
+  List<PackedObject> entries;
+}
+
+type ConstTearOff extends ConstObject {
+  kind = 12
+  constantTag (flags) = 5
+  PackedObject target;
+}
+
+type ConstBool extends ConstValue {
+  kind = 12
+  constantTag = 6
+  Byte isTrue;
+}
+
+type ConstSymbol extends ConstObject {
+  kind = 12
+  constantTag (flags) = 7
+  PackedObject name;
+}
+
+type ConstTearOffInstantiation extends ConstObject {
+  kind = 12
+  constantTag (flags) = 8
+  PackedObject tearOff;
+  PackedObject typeArguments;
+}
+
+type ArgDesc extends ObjectContents {
+  kind = 13;
+  flags = (hasNamedArgs, hasTypeArgs)
+
+  UInt numArguments
+
+  if hasTypeArgs
+    UInt numTypeArguments
+
+  if hasNamedArgs
+    List<PackedObject> argNames;
+}
+
 */
 
 enum ObjectKind {
@@ -155,6 +242,22 @@
   kGenericType,
   kFunctionType,
   kName,
+  kTypeArguments,
+  kFinalizedGenericType,
+  kConstObject,
+  kArgDesc,
+}
+
+enum ConstTag {
+  kInvalid,
+  kInstance,
+  kInt,
+  kDouble,
+  kList,
+  kTearOff,
+  kBool,
+  kSymbol,
+  kTearOffInstantiation,
 }
 
 String objectKindToString(ObjectKind kind) =>
@@ -173,7 +276,8 @@
   static const int flagBit0 = 1 << 5;
   static const int flagBit1 = 1 << 6;
   static const int flagBit2 = 1 << 7;
-  static const int flagsMask = flagBit0 | flagBit1 | flagBit2;
+  static const int flagBit3 = 1 << 8;
+  static const int flagsMask = flagBit0 | flagBit1 | flagBit2 | flagBit3;
 
   static int _makeReference(int index) => (index << indexShift) | referenceBit;
 
@@ -232,6 +336,14 @@
         return new _FunctionTypeHandle._empty();
       case ObjectKind.kName:
         return new _NameHandle._empty();
+      case ObjectKind.kTypeArguments:
+        return new _TypeArgumentsHandle._empty();
+      case ObjectKind.kFinalizedGenericType:
+        return new _FinalizedGenericTypeHandle._empty();
+      case ObjectKind.kConstObject:
+        return new _ConstObjectHandle._empty();
+      case ObjectKind.kArgDesc:
+        return new _ArgDescHandle._empty();
     }
     throw 'Unexpected object kind $kind';
   }
@@ -355,7 +467,7 @@
 
   @override
   String toString() =>
-      name.name == topLevelClassName ? '$library' : '$library::$name';
+      name.name == topLevelClassName ? '$library' : '$library::${name.name}';
 }
 
 class _MemberHandle extends ObjectHandle {
@@ -417,7 +529,7 @@
 
   @override
   String toString() =>
-      '$parent::$name' +
+      '$parent::${name.name}' +
       (flags & flagIsField != 0 ? ' (field)' : '') +
       (flags & flagIsConstructor != 0 ? ' (constructor)' : '');
 }
@@ -639,7 +751,7 @@
       this.type == other.type;
 
   @override
-  String toString() => '$type $name';
+  String toString() => '$type ${name.name}';
 }
 
 class _FunctionTypeHandle extends _TypeHandle {
@@ -846,7 +958,408 @@
       this.library == other.library;
 
   @override
-  String toString() => name.isEmpty ? "''" : name;
+  String toString() => "'$name'";
+}
+
+class _TypeArgumentsHandle extends ObjectHandle {
+  List<_TypeHandle> args;
+
+  _TypeArgumentsHandle._empty();
+
+  _TypeArgumentsHandle(this.args);
+
+  @override
+  ObjectKind get kind => ObjectKind.kTypeArguments;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writePackedList(args);
+  }
+
+  @override
+  void readContents(BufferedReader reader) {
+    args = reader.readPackedList<_TypeHandle>();
+  }
+
+  @override
+  void accountUsesForObjectCopies(int numCopies) {
+    args.forEach((t) {
+      t._useCount += numCopies;
+    });
+  }
+
+  @override
+  int get hashCode => listHashCode(args);
+
+  @override
+  bool operator ==(other) =>
+      other is _TypeArgumentsHandle && listEquals(this.args, other.args);
+
+  @override
+  String toString() => '< ${args.join(', ')} >';
+}
+
+class _FinalizedGenericTypeHandle extends _TypeHandle {
+  _ClassHandle class_;
+  _TypeArgumentsHandle typeArgs;
+
+  _FinalizedGenericTypeHandle._empty();
+
+  _FinalizedGenericTypeHandle(this.class_, this.typeArgs);
+
+  @override
+  ObjectKind get kind => ObjectKind.kFinalizedGenericType;
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writePackedObject(class_);
+    writer.writePackedObject(typeArgs);
+  }
+
+  @override
+  void readContents(BufferedReader reader) {
+    class_ = reader.readPackedObject();
+    typeArgs = reader.readPackedObject();
+  }
+
+  @override
+  void accountUsesForObjectCopies(int numCopies) {
+    class_._useCount += numCopies;
+    if (typeArgs != null) {
+      typeArgs._useCount += numCopies;
+    }
+  }
+
+  @override
+  int get hashCode => _combineHashes(class_.hashCode, typeArgs.hashCode);
+
+  @override
+  bool operator ==(other) =>
+      other is _FinalizedGenericTypeHandle &&
+      this.class_ == other.class_ &&
+      this.typeArgs == other.typeArgs;
+
+  @override
+  String toString() => '$class_ $typeArgs';
+}
+
+class _ConstObjectHandle extends ObjectHandle {
+  ConstTag tag;
+  dynamic value;
+  ObjectHandle type;
+
+  _ConstObjectHandle._empty();
+
+  _ConstObjectHandle(this.tag, this.value, [this.type]);
+
+  @override
+  ObjectKind get kind => ObjectKind.kConstObject;
+
+  @override
+  int get flags => tag.index * ObjectHandle.flagBit0;
+
+  @override
+  set flags(int value) {
+    tag = ConstTag.values[value ~/ ObjectHandle.flagBit0];
+    assert(tag != ConstTag.kInvalid);
+  }
+
+  bool get isCacheable => (tag != ConstTag.kInt) && (tag != ConstTag.kBool);
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    switch (tag) {
+      case ConstTag.kInt:
+        writer.writeSLEB128(value as int);
+        break;
+      case ConstTag.kDouble:
+        writer.writeSLEB128(doubleToIntBits(value as double));
+        break;
+      case ConstTag.kBool:
+        writer.writeByte((value as bool) ? 1 : 0);
+        break;
+      case ConstTag.kInstance:
+        {
+          final fieldValues = value as Map<ObjectHandle, ObjectHandle>;
+          writer.writePackedObject(type);
+          writer.writePackedUInt30(fieldValues.length);
+          fieldValues.forEach((ObjectHandle field, ObjectHandle value) {
+            writer.writePackedObject(field);
+            writer.writePackedObject(value);
+          });
+        }
+        break;
+      case ConstTag.kList:
+        {
+          final elems = value as List<ObjectHandle>;
+          writer.writePackedObject(type);
+          writer.writePackedList(elems);
+        }
+        break;
+      case ConstTag.kTearOff:
+        {
+          final target = value as ObjectHandle;
+          writer.writePackedObject(target);
+        }
+        break;
+      case ConstTag.kSymbol:
+        {
+          final name = value as ObjectHandle;
+          writer.writePackedObject(name);
+        }
+        break;
+      case ConstTag.kTearOffInstantiation:
+        {
+          final tearOff = value as ObjectHandle;
+          writer.writePackedObject(tearOff);
+          writer.writePackedObject(type as _TypeArgumentsHandle);
+        }
+        break;
+      default:
+        throw 'Unexpected constant tag: $tag';
+    }
+  }
+
+  @override
+  void readContents(BufferedReader reader) {
+    switch (tag) {
+      case ConstTag.kInt:
+        value = reader.readSLEB128();
+        break;
+      case ConstTag.kDouble:
+        value = intBitsToDouble(reader.readSLEB128());
+        break;
+      case ConstTag.kBool:
+        value = reader.readByte() != 0;
+        break;
+      case ConstTag.kInstance:
+        type = reader.readPackedObject();
+        value = Map<ObjectHandle, ObjectHandle>.fromEntries(
+            new List<MapEntry<ObjectHandle, ObjectHandle>>.generate(
+                reader.readPackedUInt30(),
+                (_) => new MapEntry<ObjectHandle, ObjectHandle>(
+                    reader.readPackedObject(), reader.readPackedObject())));
+        break;
+      case ConstTag.kList:
+        type = reader.readPackedObject();
+        value = reader.readPackedList<ObjectHandle>();
+        break;
+      case ConstTag.kTearOff:
+        value = reader.readPackedObject();
+        break;
+      case ConstTag.kSymbol:
+        value = reader.readPackedObject();
+        break;
+      case ConstTag.kTearOffInstantiation:
+        value = reader.readPackedObject();
+        type = reader.readPackedObject();
+        break;
+      default:
+        throw 'Unexpected constant tag: $tag';
+    }
+  }
+
+  @override
+  void accountUsesForObjectCopies(int numCopies) {
+    switch (tag) {
+      case ConstTag.kInt:
+      case ConstTag.kDouble:
+      case ConstTag.kBool:
+        break;
+      case ConstTag.kInstance:
+        {
+          type._useCount += numCopies;
+          final fieldValues = value as Map<ObjectHandle, ObjectHandle>;
+          fieldValues.forEach((ObjectHandle field, ObjectHandle value) {
+            field._useCount += numCopies;
+            value?._useCount += numCopies;
+          });
+        }
+        break;
+      case ConstTag.kList:
+        {
+          final elems = value as List<ObjectHandle>;
+          for (var elem in elems) {
+            elem?._useCount += numCopies;
+          }
+          type._useCount += numCopies;
+        }
+        break;
+      case ConstTag.kTearOff:
+        {
+          final target = value as ObjectHandle;
+          target._useCount += numCopies;
+        }
+        break;
+      case ConstTag.kSymbol:
+        {
+          final name = value as ObjectHandle;
+          name._useCount += numCopies;
+        }
+        break;
+      case ConstTag.kTearOffInstantiation:
+        {
+          final tearOff = value as ObjectHandle;
+          tearOff._useCount += numCopies;
+          if (type != null) {
+            type._useCount += numCopies;
+          }
+        }
+        break;
+      default:
+        throw 'Unexpected constant tag: $tag';
+    }
+  }
+
+  @override
+  int get hashCode {
+    switch (tag) {
+      case ConstTag.kInt:
+      case ConstTag.kDouble:
+      case ConstTag.kBool:
+      case ConstTag.kTearOff:
+      case ConstTag.kSymbol:
+        return value.hashCode;
+      case ConstTag.kInstance:
+        {
+          final fieldValues = value as Map<ObjectHandle, ObjectHandle>;
+          return _combineHashes(type.hashCode, mapHashCode(fieldValues));
+        }
+        break;
+      case ConstTag.kList:
+        {
+          final elems = value as List<ObjectHandle>;
+          return _combineHashes(type.hashCode, listHashCode(elems));
+        }
+        break;
+      case ConstTag.kTearOffInstantiation:
+        return _combineHashes(value.hashCode, type.hashCode);
+      default:
+        throw 'Unexpected constant tag: $tag';
+    }
+  }
+
+  @override
+  bool operator ==(other) {
+    if (other is _ConstObjectHandle && this.tag == other.tag) {
+      switch (tag) {
+        case ConstTag.kInt:
+        case ConstTag.kBool:
+        case ConstTag.kTearOff:
+        case ConstTag.kSymbol:
+          return this.value == other.value;
+        case ConstTag.kDouble:
+          return this.value.compareTo(other.value) == 0;
+        case ConstTag.kInstance:
+          return this.type == other.type && mapEquals(this.value, other.value);
+        case ConstTag.kList:
+          return this.type == other.type && listEquals(this.value, other.value);
+        case ConstTag.kTearOffInstantiation:
+          return this.type == other.type && this.value == other.value;
+        default:
+          throw 'Unexpected constant tag: $tag';
+      }
+    }
+    return false;
+  }
+
+  @override
+  String toString() {
+    switch (tag) {
+      case ConstTag.kInt:
+      case ConstTag.kDouble:
+      case ConstTag.kBool:
+      case ConstTag.kSymbol:
+        return 'const $value';
+      case ConstTag.kInstance:
+        return 'const $type $value';
+      case ConstTag.kList:
+        return 'const <$type> $value';
+      case ConstTag.kTearOff:
+        return 'const tear-off $value';
+      case ConstTag.kTearOffInstantiation:
+        return 'const $type $value';
+      default:
+        throw 'Unexpected constant tag: $tag';
+    }
+  }
+}
+
+class _ArgDescHandle extends _TypeHandle {
+  static const int flagHasNamedArgs = ObjectHandle.flagBit0;
+  static const int flagHasTypeArgs = ObjectHandle.flagBit1;
+
+  int _flags = 0;
+  int numArguments;
+  int numTypeArguments;
+  List<_NameHandle> argNames;
+
+  _ArgDescHandle._empty();
+
+  _ArgDescHandle(this.numArguments, this.numTypeArguments, this.argNames) {
+    if (argNames.isNotEmpty) {
+      _flags |= flagHasNamedArgs;
+    }
+    if (numTypeArguments > 0) {
+      _flags |= flagHasTypeArgs;
+    }
+  }
+
+  @override
+  ObjectKind get kind => ObjectKind.kArgDesc;
+
+  @override
+  int get flags => _flags;
+
+  @override
+  set flags(int value) {
+    _flags = value;
+  }
+
+  @override
+  void writeContents(BufferedWriter writer) {
+    writer.writePackedUInt30(numArguments);
+    if ((_flags & flagHasTypeArgs) != 0) {
+      writer.writePackedUInt30(numTypeArguments);
+    }
+    if ((_flags & flagHasNamedArgs) != 0) {
+      writer.writePackedList(argNames);
+    }
+  }
+
+  @override
+  void readContents(BufferedReader reader) {
+    numArguments = reader.readPackedUInt30();
+    numTypeArguments =
+        ((_flags & flagHasTypeArgs) != 0) ? reader.readPackedUInt30() : 0;
+    argNames = ((_flags & flagHasNamedArgs) != 0)
+        ? reader.readPackedList<_NameHandle>()
+        : null;
+  }
+
+  @override
+  void accountUsesForObjectCopies(int numCopies) {
+    if (argNames != null) {
+      for (var name in argNames) {
+        name._useCount += numCopies;
+      }
+    }
+  }
+
+  @override
+  int get hashCode => _combineHashes(
+      numArguments, _combineHashes(numTypeArguments, listHashCode(argNames)));
+
+  @override
+  bool operator ==(other) =>
+      other is _ArgDescHandle &&
+      this.numArguments == other.numArguments &&
+      this.numTypeArguments == other.numTypeArguments &&
+      listEquals(this.argNames, other.argNames);
+
+  @override
+  String toString() =>
+      'ArgDesc num-args $numArguments, num-type-args $numTypeArguments, names $argNames';
 }
 
 class ObjectTable implements ObjectWriter, ObjectReader {
@@ -946,6 +1459,40 @@
         new _MemberHandle(classHandle, nameHandle, isField, isConstructor));
   }
 
+  ObjectHandle getTypeArgumentsHandle(List<DartType> typeArgs) {
+    if (typeArgs == null) {
+      return null;
+    }
+    final List<_TypeHandle> handles =
+        typeArgs.map((t) => getHandle(t) as _TypeHandle).toList();
+    return getOrAddObject(new _TypeArgumentsHandle(handles));
+  }
+
+  ObjectHandle getArgDescHandle(int numArguments,
+      [int numTypeArguments = 0, List<String> argNames = const <String>[]]) {
+    return getOrAddObject(new _ArgDescHandle(
+        numArguments,
+        numTypeArguments,
+        argNames
+            .map<_NameHandle>((name) => getNameHandle(null, name))
+            .toList()));
+  }
+
+  ObjectHandle getArgDescHandleByArguments(Arguments args,
+      {bool hasReceiver: false, bool isFactory: false}) {
+    return getArgDescHandle(
+        args.positional.length +
+            args.named.length +
+            (hasReceiver ? 1 : 0) +
+            // VM expects that type arguments vector passed to a factory
+            // constructor is counted in numArguments, and not counted in
+            // numTypeArgs.
+            // TODO(alexmarkov): Clean this up.
+            (isFactory ? 1 : 0),
+        isFactory ? 0 : args.types.length,
+        new List<String>.from(args.named.map((ne) => ne.name)));
+  }
+
   void declareClosure(
       FunctionNode function, Member enclosingMember, int closureIndex) {
     final handle = getOrAddObject(
@@ -1024,6 +1571,12 @@
     assert(writer.objectWriter == this);
     assert(_indexTable != null);
     final start = writer.offset;
+    if (BytecodeSizeStatistics.objectTableStats.isEmpty) {
+      for (var kind in ObjectKind.values) {
+        BytecodeSizeStatistics.objectTableStats
+            .add(new NamedEntryStatistics(objectKindToString(kind)));
+      }
+    }
 
     BufferedWriter contentsWriter = new BufferedWriter.fromWriter(writer);
     List<int> offsets = new List<int>(_indexTable.length);
@@ -1031,6 +1584,11 @@
     for (int i = 0; i < _indexTable.length; ++i) {
       offsets[i] = contentsWriter.offset;
       _indexTable[i]._write(contentsWriter);
+
+      final entryStat =
+          BytecodeSizeStatistics.objectTableStats[_indexTable[i].kind.index];
+      entryStat.size += (contentsWriter.offset - offsets[i]);
+      ++entryStat.count;
     }
 
     writer.writePackedUInt30(_indexTable.length);
@@ -1047,7 +1605,9 @@
         obj.indexStrings(writer.stringWriter);
       }
     }
+
     BytecodeSizeStatistics.objectTableSize += (writer.offset - start);
+    BytecodeSizeStatistics.objectTableEntriesCount += _indexTable.length;
   }
 
   ObjectTable.read(BufferedReader reader) {
@@ -1122,11 +1682,41 @@
     if (node.typeArguments.isEmpty) {
       return objectTable.getOrAddObject(new _SimpleTypeHandle(classHandle));
     }
-    final List<_TypeHandle> typeArgs = node.typeArguments
-        .map((t) => objectTable.getHandle(t) as _TypeHandle)
-        .toList();
-    return objectTable
-        .getOrAddObject(new _GenericTypeHandle(classHandle, typeArgs));
+    // In order to save loading time, generic types are written out in
+    // finalized form, if possible.
+    //
+    // Object table serialization/deserialization cannot handle cycles between
+    // objects. Non-finalized types are not recursive, but finalization of
+    // generic types includes flattening of type arguments and types could
+    // become recursive. Consider the following example:
+    //
+    //  class Base<T> {}
+    //  class Foo<T> extends Base<Foo<T>> {}
+    //
+    //  Foo<int> is not recursive, but finalized type is recursive:
+    //  Foo<int>* = Foo [ Base [ Foo<int>* ], int ]
+    //
+    // Recursive types are very rare, so object table includes such types in
+    // non-finalized form.
+    //
+    // VM handles recursive types by introducing placeholder
+    // TypeRef objects. Also, VM ensures that recursive types are contractive
+    // (e.g. their fully finalized representation should be finite).
+    //
+    if (!isRecursiveAfterFlattening(node)) {
+      List<DartType> instantiatorArgs =
+          getInstantiatorTypeArguments(node.classNode, node.typeArguments);
+      ObjectHandle typeArgsHandle =
+          objectTable.getTypeArgumentsHandle(instantiatorArgs);
+      return objectTable.getOrAddObject(
+          new _FinalizedGenericTypeHandle(classHandle, typeArgsHandle));
+    } else {
+      final List<_TypeHandle> typeArgs = node.typeArguments
+          .map((t) => objectTable.getHandle(t) as _TypeHandle)
+          .toList();
+      return objectTable
+          .getOrAddObject(new _GenericTypeHandle(classHandle, typeArgs));
+    }
   }
 
   @override
@@ -1211,6 +1801,68 @@
   @override
   ObjectHandle visitTypedefType(TypedefType node) =>
       objectTable.getHandle(node.unalias);
+
+  @override
+  ObjectHandle visitNullConstant(NullConstant node) => null;
+
+  @override
+  ObjectHandle visitBoolConstant(BoolConstant node) => objectTable
+      .getOrAddObject(new _ConstObjectHandle(ConstTag.kBool, node.value));
+
+  @override
+  ObjectHandle visitIntConstant(IntConstant node) => objectTable
+      .getOrAddObject(new _ConstObjectHandle(ConstTag.kInt, node.value));
+
+  @override
+  ObjectHandle visitDoubleConstant(DoubleConstant node) => objectTable
+      .getOrAddObject(new _ConstObjectHandle(ConstTag.kDouble, node.value));
+
+  @override
+  ObjectHandle visitStringConstant(StringConstant node) =>
+      objectTable.getNameHandle(null, node.value);
+
+  @override
+  ObjectHandle visitSymbolConstant(SymbolConstant node) =>
+      objectTable.getOrAddObject(new _ConstObjectHandle(
+          ConstTag.kSymbol,
+          objectTable.getNameHandle(
+              node.libraryReference?.asLibrary, node.name)));
+
+  @override
+  ObjectHandle visitListConstant(ListConstant node) =>
+      objectTable.getOrAddObject(new _ConstObjectHandle(
+          ConstTag.kList,
+          new List<ObjectHandle>.from(
+              node.entries.map((Constant c) => objectTable.getHandle(c))),
+          objectTable.getHandle(node.typeArgument)));
+
+  @override
+  ObjectHandle visitInstanceConstant(InstanceConstant node) =>
+      objectTable.getOrAddObject(new _ConstObjectHandle(
+          ConstTag.kInstance,
+          node.fieldValues.map<ObjectHandle, ObjectHandle>(
+              (Reference fieldRef, Constant value) => new MapEntry(
+                  objectTable.getHandle(fieldRef.asField),
+                  objectTable.getHandle(value))),
+          objectTable.getHandle(
+              new InterfaceType(node.classNode, node.typeArguments))));
+
+  @override
+  ObjectHandle visitTearOffConstant(TearOffConstant node) =>
+      objectTable.getOrAddObject(new _ConstObjectHandle(
+          ConstTag.kTearOff, objectTable.getHandle(node.procedure)));
+
+  @override
+  ObjectHandle visitTypeLiteralConstant(TypeLiteralConstant node) =>
+      objectTable.getHandle(node.type);
+
+  @override
+  ObjectHandle visitPartialInstantiationConstant(
+          PartialInstantiationConstant node) =>
+      objectTable.getOrAddObject(new _ConstObjectHandle(
+          ConstTag.kTearOffInstantiation,
+          objectTable.getHandle(node.tearOffConstant),
+          objectTable.getTypeArgumentsHandle(node.types)));
 }
 
 int _combineHashes(int hash1, int hash2) =>
diff --git a/pkg/vm/lib/kernel_front_end.dart b/pkg/vm/lib/kernel_front_end.dart
index eb56144..088a723 100644
--- a/pkg/vm/lib/kernel_front_end.dart
+++ b/pkg/vm/lib/kernel_front_end.dart
@@ -246,6 +246,7 @@
       emitBytecodeSourcePositions: emitBytecodeSourcePositions,
       dropAST: dropAST,
       showBytecodeSizeStat: showBytecodeSizeStat,
+      useFutureBytecodeFormat: useFutureBytecodeFormat,
     );
   }
 
@@ -397,8 +398,7 @@
     CoreTypes coreTypes,
     Map<String, String> environmentDefines,
     bool enableAsserts) async {
-  final vmConstants =
-      new vm_constants.VmConstantsBackend(environmentDefines, coreTypes);
+  final vmConstants = new vm_constants.VmConstantsBackend(coreTypes);
 
   await runWithFrontEndCompilerContext(source, compilerOptions, component, () {
     final hierarchy = new ClassHierarchy(component);
@@ -406,7 +406,7 @@
 
     // TFA will remove constants fields which are unused (and respects the
     // vm/embedder entrypoints).
-    constants.transformComponent(component, vmConstants,
+    constants.transformComponent(component, vmConstants, environmentDefines,
         new ForwardConstantEvaluationErrors(typeEnvironment),
         keepFields: true,
         evaluateAnnotations: true,
diff --git a/pkg/vm/lib/target/dart_runner.dart b/pkg/vm/lib/target/dart_runner.dart
index ba877f2..923898e 100644
--- a/pkg/vm/lib/target/dart_runner.dart
+++ b/pkg/vm/lib/target/dart_runner.dart
@@ -23,6 +23,7 @@
         'dart:collection',
         'dart:convert',
         'dart:developer',
+        'dart:ffi',
         'dart:_internal',
         'dart:isolate',
         'dart:math',
diff --git a/pkg/vm/lib/target/flutter.dart b/pkg/vm/lib/target/flutter.dart
index 3be0d7c..1faa9a2 100644
--- a/pkg/vm/lib/target/flutter.dart
+++ b/pkg/vm/lib/target/flutter.dart
@@ -23,6 +23,7 @@
         'dart:collection',
         'dart:convert',
         'dart:developer',
+        'dart:ffi',
         'dart:_internal',
         'dart:isolate',
         'dart:math',
diff --git a/pkg/vm/lib/target/flutter_runner.dart b/pkg/vm/lib/target/flutter_runner.dart
index acb04e8..3ffde3c 100644
--- a/pkg/vm/lib/target/flutter_runner.dart
+++ b/pkg/vm/lib/target/flutter_runner.dart
@@ -23,6 +23,7 @@
         'dart:collection',
         'dart:convert',
         'dart:developer',
+        'dart:ffi',
         'dart:_internal',
         'dart:isolate',
         'dart:math',
diff --git a/pkg/vm/lib/target/vm.dart b/pkg/vm/lib/target/vm.dart
index 0a33c87..1682f35 100644
--- a/pkg/vm/lib/target/vm.dart
+++ b/pkg/vm/lib/target/vm.dart
@@ -11,12 +11,20 @@
 import 'package:kernel/target/targets.dart';
 import 'package:kernel/transformations/mixin_full_resolution.dart'
     as transformMixins show transformLibraries;
+import 'package:kernel/transformations/constants.dart' show ConstantsBackend;
 import 'package:kernel/transformations/continuation.dart' as transformAsync
     show transformLibraries, transformProcedure;
+import 'package:kernel/vm/constants_native_effects.dart'
+    show VmConstantsBackend;
 
 import '../transformations/call_site_annotator.dart' as callSiteAnnotator;
 import '../transformations/list_factory_specializer.dart'
     as listFactorySpecializer;
+import '../transformations/ffi.dart' as transformFfi show ReplacedMembers;
+import '../transformations/ffi_definitions.dart' as transformFfiDefinitions
+    show transformLibraries;
+import '../transformations/ffi_use_sites.dart' as transformFfiUseSites
+    show transformLibraries;
 
 /// Specializes the kernel IR to the Dart VM.
 class VmTarget extends Target {
@@ -49,6 +57,7 @@
         'dart:collection',
         'dart:convert',
         'dart:developer',
+        'dart:ffi',
         'dart:_internal',
         'dart:isolate',
         'dart:math',
@@ -79,6 +88,13 @@
         doSuperResolution: false /* resolution is done in Dart VM */);
     logger?.call("Transformed mixin applications");
 
+    transformFfi.ReplacedMembers replacedFields =
+        transformFfiDefinitions.transformLibraries(
+            coreTypes, hierarchy, libraries, diagnosticReporter);
+    transformFfiUseSites.transformLibraries(
+        coreTypes, hierarchy, libraries, diagnosticReporter, replacedFields);
+    logger?.call("Transformed ffi annotations");
+
     // TODO(kmillikin): Make this run on a per-method basis.
     transformAsync.transformLibraries(coreTypes, libraries);
     logger?.call("Transformed async methods");
@@ -349,4 +365,8 @@
     return _oneByteString ??=
         coreTypes.index.getClass('dart:core', '_OneByteString');
   }
+
+  @override
+  ConstantsBackend constantsBackend(CoreTypes coreTypes) =>
+      new VmConstantsBackend(coreTypes);
 }
diff --git a/pkg/vm/lib/transformations/ffi.dart b/pkg/vm/lib/transformations/ffi.dart
new file mode 100644
index 0000000..f79ce37
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi.dart
@@ -0,0 +1,196 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file contains logic which is shared between the ffi_definition and
+// ffi_use_site transformers.
+
+library vm.transformations.ffi;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+import 'package:kernel/core_types.dart';
+import 'package:kernel/target/targets.dart' show DiagnosticReporter;
+import 'package:kernel/type_environment.dart' show TypeEnvironment;
+
+/// Represents the (instantiated) ffi.NativeType.
+enum NativeType {
+  kPointer,
+  kNativeFunction,
+  kInt8,
+  kInt16,
+  kInt32,
+  kInt64,
+  kUint8,
+  kUint16,
+  kUint32,
+  kUnit64,
+  kIntptr,
+  kFloat,
+  kDouble,
+  kVoid
+}
+
+const NativeType kNativeTypeIntStart = NativeType.kInt8;
+const NativeType kNativeTypeIntEnd = NativeType.kIntptr;
+
+/// The [NativeType] class names, indexed by [NativeType].
+const List<String> nativeTypeClassNames = [
+  'Pointer',
+  'NativeFunction',
+  'Int8',
+  'Int16',
+  'Int32',
+  'Int64',
+  'Uint8',
+  'Uint16',
+  'Uint32',
+  'Uint64',
+  'IntPtr',
+  'Float',
+  'Double',
+  'Void'
+];
+
+const int UNKNOWN = 0;
+const int WORD_SIZE = -1;
+
+/// The [NativeType] sizes in bytes, indexed by [NativeType].
+const List<int> nativeTypeSizes = [
+  WORD_SIZE, // Pointer
+  UNKNOWN, // NativeFunction
+  1, // Int8
+  2, // Int16
+  4, // Int32
+  8, // Int64
+  1, // Uint8
+  2, // Uint16
+  4, // Uint32
+  8, // Uint64
+  WORD_SIZE, // IntPtr
+  4, // Float
+  8, // Double
+  UNKNOWN, // Void
+];
+
+/// [FfiTransformer] contains logic which is shared between
+/// _FfiUseSiteTransformer and _FfiDefinitionTransformer.
+class FfiTransformer extends Transformer {
+  final TypeEnvironment env;
+  final ClassHierarchy hierarchy;
+  final DiagnosticReporter diagnosticReporter;
+
+  final Class intClass;
+  final Class doubleClass;
+  final Constructor pragmaConstructor;
+
+  final Library ffiLibrary;
+  final Class nativeFunctionClass;
+  final Class pointerClass;
+  final Procedure castMethod;
+  final Procedure loadMethod;
+  final Procedure storeMethod;
+  final Procedure offsetByMethod;
+  final Procedure asFunctionMethod;
+  final Procedure lookupFunctionMethod;
+  final Procedure fromFunctionMethod;
+  final Field structField;
+
+  /// Classes corresponding to [NativeType], indexed by [NativeType].
+  final List<Class> nativeTypesClasses;
+
+  FfiTransformer(this.hierarchy, CoreTypes coreTypes, this.diagnosticReporter)
+      : env = new TypeEnvironment(coreTypes, hierarchy),
+        intClass = coreTypes.intClass,
+        doubleClass = coreTypes.doubleClass,
+        ffiLibrary = coreTypes.ffiLibrary,
+        nativeFunctionClass = coreTypes.ffiNativeFunctionClass,
+        pointerClass = coreTypes.ffiPointerClass,
+        castMethod = coreTypes.ffiPointerCastProcedure,
+        loadMethod = coreTypes.ffiPointerLoadProcedure,
+        storeMethod = coreTypes.ffiPointerStoreProcedure,
+        offsetByMethod = coreTypes.ffiPointerOffsetByProcedure,
+        asFunctionMethod = coreTypes.ffiPointerAsFunctionProcedure,
+        lookupFunctionMethod =
+            coreTypes.ffiDynamicLibraryLookupFunctionProcedure,
+        fromFunctionMethod = coreTypes.ffiFromFunctionProcedure,
+        structField = coreTypes.ffiStructField,
+        pragmaConstructor = coreTypes.pragmaConstructor,
+        nativeTypesClasses =
+            nativeTypeClassNames.map(coreTypes.ffiNativeTypeClass).toList() {}
+
+  /// Computes the Dart type corresponding to a ffi.[NativeType], returns null
+  /// if it is not a valid NativeType.
+  ///
+  /// [Int8]                               -> [int]
+  /// [Int16]                              -> [int]
+  /// [Int32]                              -> [int]
+  /// [Int64]                              -> [int]
+  /// [Uint8]                              -> [int]
+  /// [Uint16]                             -> [int]
+  /// [Uint32]                             -> [int]
+  /// [Uint64]                             -> [int]
+  /// [IntPtr]                             -> [int]
+  /// [Double]                             -> [double]
+  /// [Float]                              -> [double]
+  /// [Pointer]<T>                         -> [Pointer]<T>
+  /// T extends [Pointer]                  -> T
+  /// [NativeFunction]<T1 Function(T2, T3) -> S1 Function(S2, S3)
+  ///    where DartRepresentationOf(Tn) -> Sn
+  DartType convertNativeTypeToDartType(DartType nativeType) {
+    if (nativeType is! InterfaceType) {
+      return null;
+    }
+    Class nativeClass = (nativeType as InterfaceType).classNode;
+    if (env.isSubtypeOf(
+        InterfaceType(nativeClass), InterfaceType(pointerClass))) {
+      return nativeType;
+    }
+    NativeType nativeType_ = getType(nativeClass);
+    if (nativeType_ == null) {
+      return null;
+    }
+    if (kNativeTypeIntStart.index <= nativeType_.index &&
+        nativeType_.index <= kNativeTypeIntEnd.index) {
+      return InterfaceType(intClass);
+    }
+    if (nativeType_ == NativeType.kFloat || nativeType_ == NativeType.kDouble) {
+      return InterfaceType(doubleClass);
+    }
+    if (nativeType_ == NativeType.kNativeFunction) {
+      DartType fun = (nativeType as InterfaceType).typeArguments[0];
+      if (fun is FunctionType) {
+        if (fun.namedParameters.isNotEmpty) return null;
+        if (fun.positionalParameters.length != fun.requiredParameterCount)
+          return null;
+        if (fun.typeParameters.length != 0) return null;
+        DartType returnType = convertNativeTypeToDartType(fun.returnType);
+        if (returnType == null) return null;
+        List<DartType> argumentTypes = fun.positionalParameters
+            .map(this.convertNativeTypeToDartType)
+            .toList();
+        if (argumentTypes.contains(null)) return null;
+        return FunctionType(argumentTypes, returnType);
+      }
+    }
+    return null;
+  }
+
+  NativeType getType(Class c) {
+    int index = nativeTypesClasses.indexOf(c);
+    if (index == -1) {
+      return null;
+    }
+    return NativeType.values[index];
+  }
+}
+
+/// Contains replaced members, of which all the call sites need to be replaced.
+///
+/// [ReplacedMembers] is populated by _FfiDefinitionTransformer and consumed by
+/// _FfiUseSiteTransformer.
+class ReplacedMembers {
+  final Map<Field, Procedure> replacedGetters;
+  final Map<Field, Procedure> replacedSetters;
+  ReplacedMembers(this.replacedGetters, this.replacedSetters);
+}
diff --git a/pkg/vm/lib/transformations/ffi_definitions.dart b/pkg/vm/lib/transformations/ffi_definitions.dart
new file mode 100644
index 0000000..e738406
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi_definitions.dart
@@ -0,0 +1,372 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library kernel.transformations.ffi_definitions;
+
+import 'dart:math' as math;
+
+import 'package:front_end/src/api_unstable/vm.dart'
+    show
+        templateFfiFieldAnnotation,
+        templateFfiStructAnnotation,
+        templateFfiTypeMismatch,
+        templateFfiFieldInitializer;
+
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/target/targets.dart' show DiagnosticReporter;
+
+import 'ffi.dart'
+    show
+        ReplacedMembers,
+        NativeType,
+        FfiTransformer,
+        nativeTypeSizes,
+        WORD_SIZE;
+
+/// Checks and expands the dart:ffi @struct and field annotations.
+///
+/// Sample input:
+/// @ffi.struct
+/// class Coord extends ffi.Pointer<Void> {
+///   @ffi.Double()
+///   double x;
+///
+///   @ffi.Double()
+///   double y;
+///
+///   @ffi.Pointer()
+///   Coord next;
+///
+///   external static int sizeOf();
+/// }
+///
+/// Sample output:
+/// class Coordinate extends ffi.Pointer<ffi.Void> {
+///   ffi.Pointer<ffi.Double> get _xPtr => cast();
+///   set x(double v) => _xPtr.store(v);
+///   double get x => _xPtr.load();
+///
+///   ffi.Pointer<ffi.Double> get _yPtr =>
+///       offsetBy(ffi.sizeOf<ffi.Double>() * 1).cast();
+///   set y(double v) => _yPtr.store(v);
+///   double get y => _yPtr.load();
+///
+///   ffi.Pointer<Coordinate> get _nextPtr =>
+///       offsetBy(ffi.sizeOf<ffi.Double>() * 2).cast();
+///   set next(Coordinate v) => _nextPtr.store(v);
+///   Coordinate get next => _nextPtr.load();
+///
+///   static int sizeOf() => 24;
+/// }
+ReplacedMembers transformLibraries(
+    CoreTypes coreTypes,
+    ClassHierarchy hierarchy,
+    List<Library> libraries,
+    DiagnosticReporter diagnosticReporter) {
+  final transformer =
+      new _FfiDefinitionTransformer(hierarchy, coreTypes, diagnosticReporter);
+  libraries.forEach(transformer.visitLibrary);
+  return ReplacedMembers(
+      transformer.replacedGetters, transformer.replacedSetters);
+}
+
+/// Checks and expands the dart:ffi @struct and field annotations.
+class _FfiDefinitionTransformer extends FfiTransformer {
+  Map<Field, Procedure> replacedGetters = {};
+  Map<Field, Procedure> replacedSetters = {};
+
+  _FfiDefinitionTransformer(ClassHierarchy hierarchy, CoreTypes coreTypes,
+      DiagnosticReporter diagnosticReporter)
+      : super(hierarchy, coreTypes, diagnosticReporter) {}
+
+  @override
+  visitClass(Class node) {
+    if (node == pointerClass || !hierarchy.isSubtypeOf(node, pointerClass)) {
+      return node;
+    }
+
+    // Because subtypes of Pointer are only allocated by allocate<Pointer<..>>()
+    // and fromAddress<Pointer<..>>() which are not recognized as constructor
+    // calls, we need to prevent these classes from being tree shaken out.
+    _preventTreeShaking(node);
+
+    _checkFieldAnnotations(node);
+    _checkConstructors(node);
+
+    bool isStruct = _checkStructAnnotation(node);
+    if (isStruct) {
+      int size = _replaceFields(node);
+      _replaceSizeOfMethod(node, size);
+    }
+
+    return node;
+  }
+
+  bool _checkStructAnnotation(Class node) {
+    bool isStruct = _hasAnnotation(node);
+    if (!isStruct && node.fields.isNotEmpty) {
+      diagnosticReporter.report(
+          templateFfiStructAnnotation.withArguments(node.name),
+          node.fileOffset,
+          1,
+          node.fileUri);
+    }
+    return isStruct;
+  }
+
+  void _checkFieldAnnotations(Class node) {
+    for (Field f in node.fields) {
+      if (f.initializer is! NullLiteral) {
+        diagnosticReporter.report(
+            templateFfiFieldInitializer.withArguments(f.name.name),
+            f.fileOffset,
+            f.name.name.length,
+            f.fileUri);
+      }
+      List<NativeType> annos = _getAnnotations(f).toList();
+      if (annos.length != 1) {
+        diagnosticReporter.report(
+            templateFfiFieldAnnotation.withArguments(f.name.name),
+            f.fileOffset,
+            f.name.name.length,
+            f.fileUri);
+      } else {
+        DartType dartType = f.type;
+        DartType nativeType =
+            InterfaceType(nativeTypesClasses[annos.first.index]);
+        DartType shouldBeDartType = convertNativeTypeToDartType(nativeType);
+        if (!env.isSubtypeOf(dartType, shouldBeDartType)) {
+          diagnosticReporter.report(
+              templateFfiTypeMismatch.withArguments(
+                  dartType, shouldBeDartType, nativeType),
+              f.fileOffset,
+              1,
+              f.location.file);
+        }
+      }
+    }
+  }
+
+  void _checkConstructors(Class node) {
+    List<Initializer> toRemove = [];
+    for (Constructor c in node.constructors) {
+      for (Initializer i in c.initializers) {
+        if (i is FieldInitializer) {
+          toRemove.add(i);
+          diagnosticReporter.report(
+              templateFfiFieldInitializer.withArguments(i.field.name.name),
+              i.fileOffset,
+              1,
+              i.location.file);
+        }
+      }
+    }
+    // Remove initializers referring to fields to prevent cascading errors.
+    for (Initializer i in toRemove) {
+      i.remove();
+    }
+  }
+
+  /// Computes the field offsets in the struct and replaces the fields with
+  /// getters and setters using these offsets.
+  ///
+  /// Returns the total size of the struct.
+  int _replaceFields(Class node) {
+    List<Field> fields = [];
+    List<NativeType> types = [];
+
+    for (Field f in node.fields) {
+      List<NativeType> annos = _getAnnotations(f).toList();
+      if (annos.length == 1) {
+        NativeType t = annos.first;
+        fields.add(f);
+        types.add(t);
+      }
+    }
+
+    List<int> offsets = _calculateOffsets(types);
+    int size = _calculateSize(offsets, types);
+
+    for (int i = 0; i < fields.length; i++) {
+      List<Procedure> methods =
+          _generateMethodsForField(fields[i], types[i], offsets[i]);
+      for (Procedure p in methods) {
+        node.addMember(p);
+      }
+    }
+
+    for (Field f in fields) {
+      f.remove();
+    }
+
+    return size;
+  }
+
+  /// Sample output:
+  /// ffi.Pointer<ffi.Double> get _xPtr => cast();
+  /// double get x => _xPtr.load();
+  /// set x(double v) => _xPtr.store(v);
+  List<Procedure> _generateMethodsForField(
+      Field field, NativeType type, int offset) {
+    DartType nativeType = type == NativeType.kPointer
+        ? field.type
+        : InterfaceType(nativeTypesClasses[type.index]);
+    DartType pointerType = InterfaceType(pointerClass, [nativeType]);
+    Name pointerName = Name('#_ptr_${field.name.name}');
+
+    // Sample output for primitives:
+    // ffi.Pointer<ffi.Double> get _xPtr => cast<ffi.Pointer<ffi.Double>>();
+    // Sample output for structs:
+    // ffi.Pointer<Coordinate> get _xPtr => offsetBy(16).cast<...>();
+    Expression offsetExpression = ThisExpression();
+    if (offset != 0) {
+      offsetExpression = MethodInvocation(offsetExpression, offsetByMethod.name,
+          Arguments([IntLiteral(offset)]), offsetByMethod);
+    }
+    Procedure pointerGetter = Procedure(
+        pointerName,
+        ProcedureKind.Getter,
+        FunctionNode(
+            ReturnStatement(MethodInvocation(offsetExpression, castMethod.name,
+                Arguments([], types: [pointerType]), castMethod)),
+            returnType: pointerType));
+
+    // Sample output:
+    // double get x => _xPtr.load<double>();
+    Procedure getter = Procedure(
+        field.name,
+        ProcedureKind.Getter,
+        FunctionNode(
+            ReturnStatement(MethodInvocation(
+                PropertyGet(ThisExpression(), pointerName, pointerGetter),
+                loadMethod.name,
+                Arguments([], types: [field.type]),
+                loadMethod)),
+            returnType: field.type));
+
+    // Sample output:
+    // set x(double v) => _xPtr.store(v);
+    VariableDeclaration argument = VariableDeclaration('#v', type: field.type);
+    Procedure setter = Procedure(
+        field.name,
+        ProcedureKind.Setter,
+        FunctionNode(
+            ReturnStatement(MethodInvocation(
+                PropertyGet(ThisExpression(), pointerName, pointerGetter),
+                storeMethod.name,
+                Arguments([VariableGet(argument)]),
+                storeMethod)),
+            returnType: VoidType(),
+            positionalParameters: [argument]));
+
+    replacedGetters[field] = getter;
+    replacedSetters[field] = setter;
+
+    return [pointerGetter, getter, setter];
+  }
+
+  /// Sample input:
+  /// external static int sizeOf();
+  ///
+  /// Sample output:
+  /// static int sizeOf() => 24;
+  void _replaceSizeOfMethod(Class struct, int size) {
+    Procedure sizeOf = _findProcedure(struct, 'sizeOf');
+    if (sizeOf == null || !sizeOf.isExternal || !sizeOf.isStatic) {
+      return;
+    }
+
+    // replace in place to avoid going over use sites
+    sizeOf.function = FunctionNode(ReturnStatement(IntLiteral(size)),
+        returnType: InterfaceType(intClass));
+    sizeOf.isExternal = false;
+  }
+
+  // TODO(dacoharkes): move to VM, take into account architecture
+  // https://github.com/dart-lang/sdk/issues/35768
+  int _sizeInBytes(NativeType t) {
+    int size = nativeTypeSizes[t.index];
+    if (size == WORD_SIZE) {
+      size = 8;
+    }
+    return size;
+  }
+
+  int _align(int offset, int size) {
+    int remainder = offset % size;
+    if (remainder != 0) {
+      offset -= remainder;
+      offset += size;
+    }
+    return offset;
+  }
+
+  // TODO(dacoharkes): move to VM, take into account architecture
+  // https://github.com/dart-lang/sdk/issues/35768
+  List<int> _calculateOffsets(List<NativeType> types) {
+    int offset = 0;
+    List<int> offsets = [];
+    for (NativeType t in types) {
+      int size = _sizeInBytes(t);
+      offset = _align(offset, size);
+      offsets.add(offset);
+      offset += size;
+    }
+    return offsets;
+  }
+
+  // TODO(dacoharkes): move to VM, take into account architecture
+  // https://github.com/dart-lang/sdk/issues/35768
+  int _calculateSize(List<int> offsets, List<NativeType> types) {
+    if (offsets.isEmpty) {
+      return 0;
+    }
+    int largestElement = types.map((e) => _sizeInBytes(e)).reduce(math.max);
+    int highestOffsetIndex = types.length - 1;
+    int highestOffset = offsets[highestOffsetIndex];
+    int highestOffsetSize = _sizeInBytes(types[highestOffsetIndex]);
+    return _align(highestOffset + highestOffsetSize, largestElement);
+  }
+
+  bool _hasAnnotation(Class node) {
+    for (Expression e in node.annotations) {
+      if (e is StaticGet) {
+        if (e.target == structField) {
+          return true;
+        }
+      }
+    }
+    return false;
+  }
+
+  void _preventTreeShaking(Class node) {
+    node.addAnnotation(ConstructorInvocation(
+        pragmaConstructor, Arguments([StringLiteral("vm:entry-point")])));
+  }
+
+  NativeType _getFieldType(Class c) {
+    NativeType fieldType = getType(c);
+
+    if (fieldType == NativeType.kVoid) {
+      // Fields cannot have Void types.
+      return null;
+    }
+    return fieldType;
+  }
+
+  Iterable<NativeType> _getAnnotations(Field node) {
+    return node.annotations
+        .whereType<ConstructorInvocation>()
+        .map((expr) => expr.target.parent)
+        .map((klass) => _getFieldType(klass))
+        .where((type) => type != null);
+  }
+}
+
+/// Finds procedure with name, otherwise returns null.
+Procedure _findProcedure(Class c, String name) =>
+    c.procedures.firstWhere((p) => p.name.name == name, orElse: () => null);
diff --git a/pkg/vm/lib/transformations/ffi_use_sites.dart b/pkg/vm/lib/transformations/ffi_use_sites.dart
new file mode 100644
index 0000000..8e9227c
--- /dev/null
+++ b/pkg/vm/lib/transformations/ffi_use_sites.dart
@@ -0,0 +1,270 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library kernel.transformations.ffi_use_sites;
+
+import 'package:front_end/src/api_unstable/vm.dart'
+    show
+        templateFfiTypeInvalid,
+        templateFfiTypeMismatch,
+        templateFfiTypeUnsized,
+        templateFfiNotStatic;
+
+import 'package:kernel/class_hierarchy.dart' show ClassHierarchy;
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart';
+import 'package:kernel/target/targets.dart' show DiagnosticReporter;
+
+import 'ffi.dart'
+    show
+        ReplacedMembers,
+        NativeType,
+        kNativeTypeIntStart,
+        kNativeTypeIntEnd,
+        FfiTransformer;
+
+/// Checks and replaces calls to dart:ffi struct fields and methods.
+void transformLibraries(
+    CoreTypes coreTypes,
+    ClassHierarchy hierarchy,
+    List<Library> libraries,
+    DiagnosticReporter diagnosticReporter,
+    ReplacedMembers replacedFields) {
+  final transformer = new _FfiUseSiteTransformer(
+      hierarchy,
+      coreTypes,
+      diagnosticReporter,
+      replacedFields.replacedGetters,
+      replacedFields.replacedSetters);
+  libraries.forEach(transformer.visitLibrary);
+}
+
+/// Checks and replaces calls to dart:ffi struct fields and methods.
+class _FfiUseSiteTransformer extends FfiTransformer {
+  final Map<Field, Procedure> replacedGetters;
+  final Map<Field, Procedure> replacedSetters;
+
+  _FfiUseSiteTransformer(
+      ClassHierarchy hierarchy,
+      CoreTypes coreTypes,
+      DiagnosticReporter diagnosticReporter,
+      this.replacedGetters,
+      this.replacedSetters)
+      : super(hierarchy, coreTypes, diagnosticReporter) {}
+
+  @override
+  visitClass(Class node) {
+    env.thisType = InterfaceType(node);
+    try {
+      return super.visitClass(node);
+    } finally {
+      env.thisType = null;
+    }
+  }
+
+  @override
+  visitPropertyGet(PropertyGet node) {
+    super.visitPropertyGet(node);
+
+    Procedure replacedWith = replacedGetters[node.interfaceTarget];
+    if (replacedWith != null) {
+      node = PropertyGet(node.receiver, replacedWith.name, replacedWith);
+    }
+
+    return node;
+  }
+
+  @override
+  visitPropertySet(PropertySet node) {
+    super.visitPropertySet(node);
+
+    Procedure replacedWith = replacedSetters[node.interfaceTarget];
+    if (replacedWith != null) {
+      node = PropertySet(
+          node.receiver, replacedWith.name, node.value, replacedWith);
+    }
+
+    return node;
+  }
+
+  @override
+  visitStaticInvocation(StaticInvocation node) {
+    super.visitStaticInvocation(node);
+
+    Member target = node.target;
+    try {
+      if (target == fromFunctionMethod) {
+        DartType nativeType =
+            InterfaceType(nativeFunctionClass, [node.arguments.types[0]]);
+        Expression func = node.arguments.positional[0];
+        DartType dartType = func.getStaticType(env);
+
+        _ensureIsStatic(func);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+      }
+    } catch (_FfiStaticTypeError) {}
+
+    return node;
+  }
+
+  @override
+  visitMethodInvocation(MethodInvocation node) {
+    super.visitMethodInvocation(node);
+
+    Member target = node.interfaceTarget;
+    try {
+      if (target == lookupFunctionMethod) {
+        DartType nativeType =
+            InterfaceType(nativeFunctionClass, [node.arguments.types[0]]);
+        DartType dartType = node.arguments.types[1];
+
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+      } else if (target == asFunctionMethod) {
+        if (node.enclosingLibrary == ffiLibrary) {
+          // Library code of dart:ffi uses asFunction to implement
+          // lookupFunction. Since we treat lookupFunction as well, this call
+          // can be generic and still support AOT.
+          return node;
+        }
+
+        DartType dartType = node.arguments.types[0];
+        DartType pointerType = node.receiver.getStaticType(env);
+        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+
+        _ensureNativeTypeValid(pointerType, node);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+      } else if (target == loadMethod) {
+        // TODO(dacoharkes): should load and store permitted to be generic?
+        // https://github.com/dart-lang/sdk/issues/35902
+        DartType dartType = node.arguments.types[0];
+        DartType pointerType = node.receiver.getStaticType(env);
+        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+
+        _ensureNativeTypeValid(pointerType, node);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeSized(nativeType, node, target.name);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+      } else if (target == storeMethod) {
+        // TODO(dacoharkes): should load and store permitted to be generic?
+        // https://github.com/dart-lang/sdk/issues/35902
+        DartType dartType = node.arguments.positional[0].getStaticType(env);
+        DartType pointerType = node.receiver.getStaticType(env);
+        DartType nativeType = _pointerTypeGetTypeArg(pointerType);
+
+        _ensureNativeTypeValid(pointerType, node);
+        _ensureNativeTypeValid(nativeType, node);
+        _ensureNativeTypeSized(nativeType, node, target.name);
+        _ensureNativeTypeToDartType(nativeType, dartType, node);
+      }
+    } catch (_FfiStaticTypeError) {}
+
+    return node;
+  }
+
+  DartType _pointerTypeGetTypeArg(DartType pointerType) {
+    if (pointerType is InterfaceType) {
+      InterfaceType superType =
+          hierarchy.getTypeAsInstanceOf(pointerType, pointerClass);
+      return superType?.typeArguments[0];
+    }
+    return null;
+  }
+
+  void _ensureNativeTypeToDartType(
+      DartType nativeType, DartType dartType, Expression node) {
+    DartType shouldBeDartType = convertNativeTypeToDartType(nativeType);
+    if (dartType != shouldBeDartType) {
+      diagnosticReporter.report(
+          templateFfiTypeMismatch.withArguments(
+              dartType, shouldBeDartType, nativeType),
+          node.fileOffset,
+          1,
+          node.location.file);
+      throw _FfiStaticTypeError();
+    }
+  }
+
+  void _ensureNativeTypeValid(DartType nativeType, Expression node) {
+    if (!_nativeTypeValid(nativeType)) {
+      diagnosticReporter.report(
+          templateFfiTypeInvalid.withArguments(nativeType),
+          node.fileOffset,
+          1,
+          node.location.file);
+      throw _FfiStaticTypeError();
+    }
+  }
+
+  /// The Dart type system does not enforce that NativeFunction return and
+  /// parameter types are only NativeTypes, so we need to check this.
+  bool _nativeTypeValid(DartType nativeType) {
+    return convertNativeTypeToDartType(nativeType) != null;
+  }
+
+  void _ensureNativeTypeSized(
+      DartType nativeType, Expression node, Name targetName) {
+    if (!_nativeTypeSized(nativeType)) {
+      diagnosticReporter.report(
+          templateFfiTypeUnsized.withArguments(targetName.name, nativeType),
+          node.fileOffset,
+          1,
+          node.location.file);
+      throw _FfiStaticTypeError();
+    }
+  }
+
+  /// Unsized NativeTypes do not support [sizeOf] because their size is unknown.
+  /// Consequently, [allocate], [Pointer.load], [Pointer.store], and
+  /// [Pointer.elementAt] are not available.
+  bool _nativeTypeSized(DartType nativeType) {
+    if (!(nativeType is InterfaceType)) {
+      return false;
+    }
+    Class nativeClass = (nativeType as InterfaceType).classNode;
+    if (env.isSubtypeOf(
+        InterfaceType(nativeClass), InterfaceType(pointerClass))) {
+      return true;
+    }
+    NativeType nativeType_ = getType(nativeClass);
+    if (nativeType_ == null) {
+      return false;
+    }
+    if (kNativeTypeIntStart.index <= nativeType_.index &&
+        nativeType_.index <= kNativeTypeIntEnd.index) {
+      return true;
+    }
+    if (nativeType_ == NativeType.kFloat || nativeType_ == NativeType.kDouble) {
+      return true;
+    }
+    if (nativeType_ == NativeType.kPointer) {
+      return true;
+    }
+    return false;
+  }
+
+  void _ensureIsStatic(Expression node) {
+    if (!_isStatic(node)) {
+      diagnosticReporter.report(
+          templateFfiNotStatic.withArguments(fromFunctionMethod.name.name),
+          node.fileOffset,
+          1,
+          node.location.file);
+      throw _FfiStaticTypeError();
+    }
+  }
+
+  bool _isStatic(Expression node) {
+    if (node is! StaticGet) return false;
+
+    return (node as StaticGet).target is Procedure;
+  }
+}
+
+/// Used internally for abnormal control flow to prevent cascading error
+/// messages.
+class _FfiStaticTypeError implements Exception {}
diff --git a/pkg/vm/test/bytecode/generics_test.dart b/pkg/vm/test/bytecode/generics_test.dart
new file mode 100644
index 0000000..6b0a75f
--- /dev/null
+++ b/pkg/vm/test/bytecode/generics_test.dart
@@ -0,0 +1,113 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:kernel/ast.dart';
+import 'package:kernel/core_types.dart' show CoreTypes;
+import 'package:kernel/testing/mock_sdk_component.dart';
+import 'package:test/test.dart';
+import 'package:vm/bytecode/generics.dart';
+
+main() {
+  Library lib;
+  Supertype objectSuper;
+  DartType intType;
+  Class base;
+
+  Class addClass(String name, List<TypeParameter> typeParameters) {
+    Class cls = new Class(
+        name: name, supertype: objectSuper, typeParameters: typeParameters);
+    lib.addClass(cls);
+    return cls;
+  }
+
+  setUp(() {
+    // Start with mock SDK libraries.
+    Component component = createMockSdkComponent();
+    CoreTypes coreTypes = new CoreTypes(component);
+    objectSuper = coreTypes.objectClass.asThisSupertype;
+    intType = new InterfaceType(coreTypes.intClass);
+
+    // Add the test library.
+    lib = new Library(Uri.parse('org-dartlang:///test.dart'), name: 'lib');
+    lib.parent = component;
+    component.libraries.add(lib);
+
+    // class Base<T>
+    base = addClass('Base', [new TypeParameter('T')]);
+  });
+
+  tearDown(() {});
+
+  test('isRecursiveAfterFlattening-00', () async {
+    // class Derived<T> extends Base<Derived<T>>
+    TypeParameter t = new TypeParameter('T');
+    Class derived = addClass('Derived', [t]);
+    DartType derivedOfT =
+        new InterfaceType(derived, [new TypeParameterType(t)]);
+    DartType derivedOfInt = new InterfaceType(derived, [intType]);
+    derived.supertype = new Supertype(base, [derivedOfT]);
+
+    expect(isRecursiveAfterFlattening(derivedOfT), isTrue);
+    expect(isRecursiveAfterFlattening(derivedOfInt), isTrue);
+  });
+
+  test('isRecursiveAfterFlattening-01', () async {
+    // class Derived<T> extends Base<Derived<Derived<int>>>
+    TypeParameter t = new TypeParameter('T');
+    Class derived = addClass('Derived', [t]);
+    DartType derivedOfT =
+        new InterfaceType(derived, [new TypeParameterType(t)]);
+    DartType derivedOfInt = new InterfaceType(derived, [intType]);
+    DartType derivedOfDerivedOfInt = new InterfaceType(derived, [derivedOfInt]);
+    derived.supertype = new Supertype(base, [derivedOfDerivedOfInt]);
+
+    expect(isRecursiveAfterFlattening(derivedOfT), isFalse);
+    expect(isRecursiveAfterFlattening(derivedOfInt), isTrue);
+  });
+
+  test('isRecursiveAfterFlattening-02', () async {
+    // class Derived<T> extends Base<Derived<Derived<T>>>
+    TypeParameter t = new TypeParameter('T');
+    Class derived = addClass('Derived', [t]);
+    DartType derivedOfT =
+        new InterfaceType(derived, [new TypeParameterType(t)]);
+    DartType derivedOfInt = new InterfaceType(derived, [intType]);
+    DartType derivedOfDerivedOfT = new InterfaceType(derived, [derivedOfT]);
+    derived.supertype = new Supertype(base, [derivedOfDerivedOfT]);
+
+    expect(isRecursiveAfterFlattening(derivedOfT), isTrue);
+    expect(isRecursiveAfterFlattening(derivedOfInt), isTrue);
+  });
+
+  test('isRecursiveAfterFlattening-03', () async {
+    // class Derived1<U> extends Base<Derived2<U>>
+    // class Derived2<V> extends Base<Derived1<V>>
+    TypeParameter u = new TypeParameter('U');
+    Class derived1 = addClass('Derived1', [u]);
+
+    TypeParameter v = new TypeParameter('V');
+    Class derived2 = addClass('Derived2', [v]);
+
+    DartType derived2OfU =
+        new InterfaceType(derived2, [new TypeParameterType(u)]);
+    derived1.supertype = new Supertype(base, [derived2OfU]);
+
+    DartType derived1OfV =
+        new InterfaceType(derived1, [new TypeParameterType(v)]);
+    derived2.supertype = new Supertype(base, [derived1OfV]);
+
+    DartType derived1OfU =
+        new InterfaceType(derived1, [new TypeParameterType(u)]);
+    DartType derived1OfInt = new InterfaceType(derived1, [intType]);
+
+    DartType derived2OfV =
+        new InterfaceType(derived2, [new TypeParameterType(v)]);
+    DartType derived2OfInt = new InterfaceType(derived2, [intType]);
+
+    expect(isRecursiveAfterFlattening(derived1OfU), isTrue);
+    expect(isRecursiveAfterFlattening(derived1OfInt), isTrue);
+    expect(isRecursiveAfterFlattening(derived2OfV), isTrue);
+    expect(isRecursiveAfterFlattening(derived2OfInt), isTrue);
+  });
+}
diff --git a/pkg/vm/testcases/bytecode/asserts.dart.expect b/pkg/vm/testcases/bytecode/asserts.dart.expect
index 575ae5f..0c5afe3 100644
--- a/pkg/vm/testcases/bytecode/asserts.dart.expect
+++ b/pkg/vm/testcases/bytecode/asserts.dart.expect
@@ -13,16 +13,15 @@
   PushInt              0
   PushInt              0
   PushNull
-  PushConstant         CP#1
-  IndirectStaticCall   3, CP#0
+  DirectCall           3, CP#0
   Drop1
 L1:
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 3, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::_AssertionError::_throwNew', arg-desc CP#0
+  [0] = DirectCall 'dart:core::_AssertionError::_throwNew', ArgDesc num-args 3, num-type-args 0, names []
+  [1] = Reserved
 }
 ]static method test1(core::bool condition) → void {
   assert(condition);
@@ -40,19 +39,18 @@
   PushInt              0
   Push                 FP[-5]
   DynamicCall          1, CP#2
-  PushConstant         CP#4
-  IndirectStaticCall   3, CP#3
+  DirectCall           3, CP#3
   Drop1
 L1:
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
+  [0] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
   [1] = ICData dynamic target-name 'call', arg-desc CP#0
   [2] = ICData dynamic target-name 'call', arg-desc CP#0
-  [3] = ArgDesc num-args 3, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::_AssertionError::_throwNew', arg-desc CP#3
+  [3] = DirectCall 'dart:core::_AssertionError::_throwNew', ArgDesc num-args 3, num-type-args 0, names []
+  [4] = Reserved
 }
 ]static method test2(() → core::bool condition, () → core::String message) → void {
   assert([@vm.call-site-attributes.metadata=receiverType:() → dart.core::bool] condition.call(), [@vm.call-site-attributes.metadata=receiverType:() → dart.core::String] message.call());
diff --git a/pkg/vm/testcases/bytecode/async.dart.expect b/pkg/vm/testcases/bytecode/async.dart.expect
index 9218869..a9c151f 100644
--- a/pkg/vm/testcases/bytecode/async.dart.expect
+++ b/pkg/vm/testcases/bytecode/async.dart.expect
@@ -9,20 +9,20 @@
 Bytecode {
   Entry                3
   CheckStack           0
-  Allocate             CP#21
+  Allocate             CP#20
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#21
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#24
+  StoreFieldTOS        CP#23
   Push                 r2
-  PushConstant         CP#26
-  StoreFieldTOS        CP#27
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r2
   PushConstant         CP#0
-  StoreFieldTOS        CP#29
+  StoreFieldTOS        CP#28
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -33,42 +33,45 @@
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
   [3] = Type dart:async::Future < dart:core::int >
-  [4] = String 'x'
+  [4] = ObjectRef 'x'
   [5] = SubtypeTestCache
   [6] = Class dart:async::_AsyncAwaitCompleter
-  [7] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::Null]
-  [8] = ArgDesc num-args 1, num-type-args 0, names []
-  [9] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#8
+  [7] = ObjectRef < dart:core::Null >
+  [8] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [9] = Reserved
   [10] = ClosureFunction 1
-  [11] = Null
-  [12] = ArgDesc num-args 4, num-type-args 0, names []
-  [13] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#12
-  [14] = ArgDesc num-args 2, num-type-args 0, names []
-  [15] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#14
+  [11] = ObjectRef null
+  [12] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [13] = Reserved
+  [14] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [15] = Reserved
   [16] = Type dynamic
-  [17] = ArgDesc num-args 3, num-type-args 0, names []
-  [18] = InterfaceCall target-name 'completeError', arg-desc CP#17
-  [19] = Reserved
-  [20] = EndClosureFunctionScope
-  [21] = Class dart:core::_Closure
-  [22] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [23] = Reserved
-  [24] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [25] = Reserved
-  [26] = EmptyTypeArguments
-  [27] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [28] = Reserved
-  [29] = InstanceField dart:core::_Closure::_function (field)
-  [30] = Reserved
-  [31] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#8
-  [32] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#8
-  [33] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#8
-  [34] = ICData dynamic target-name 'start', arg-desc CP#14
-  [35] = InterfaceCall get target-name 'get:future', arg-desc CP#8
-  [36] = Reserved
-  [37] = EndClosureFunctionScope
+  [17] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [18] = Reserved
+  [19] = EndClosureFunctionScope
+  [20] = Class dart:core::_Closure
+  [21] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [22] = Reserved
+  [23] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [24] = Reserved
+  [25] = EmptyTypeArguments
+  [26] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [27] = Reserved
+  [28] = InstanceField dart:core::_Closure::_function (field)
+  [29] = Reserved
+  [30] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [35] = Reserved
+  [36] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [37] = ICData dynamic target-name 'start', arg-desc CP#36
+  [38] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [39] = Reserved
+  [40] = EndClosureFunctionScope
 }
-Closure #lib::asyncInFieldInitializer (field)::<anonymous closure> (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
+Closure #lib::asyncInFieldInitializer (field)::'<anonymous closure>' (dart:async::Future < dart:core::int > x) -> dart:async::Future < dart:core::Null >
 ClosureBytecode {
   EntryFixed           2, 4
   CheckStack           0
@@ -93,8 +96,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#8
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -118,55 +120,52 @@
   PushNull
   StoreContextVar      0, 7
   Push                 r0
-  Allocate             CP#21
+  Allocate             CP#20
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#21
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#24
+  StoreFieldTOS        CP#23
   Push                 r2
-  PushConstant         CP#26
-  StoreFieldTOS        CP#27
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r2
   PushConstant         CP#10
-  StoreFieldTOS        CP#29
+  StoreFieldTOS        CP#28
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#31
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#30
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#32
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#33
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#34
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          2, CP#34
+  DynamicCall          2, CP#37
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#35
+  InterfaceCall        1, CP#38
   ReturnTOS
 
 }
 
-Closure #lib::asyncInFieldInitializer (field)::Closure/0:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::asyncInFieldInitializer (field)::Closure/0::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#11
@@ -200,8 +199,7 @@
   LoadContextVar       0, 4
   Push                 r4
   LoadContextVar       0, 8
-  PushConstant         CP#13
-  IndirectStaticCall   4, CP#12
+  DirectCall           4, CP#12
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -218,8 +216,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  PushConstant         CP#15
-  IndirectStaticCall   2, CP#14
+  DirectCall           2, CP#14
   Drop1
   PushNull
   ReturnTOS
@@ -242,7 +239,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#18
+  InterfaceCall        3, CP#17
   Drop1
   Jump                 L3
 L3:
@@ -295,8 +292,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   StoreContextVar      0, 0
   Push                 r0
@@ -314,80 +310,80 @@
   Push                 r0
   PushNull
   StoreContextVar      0, 3
-  Allocate             CP#15
+  Allocate             CP#14
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#16
+  StoreFieldTOS        CP#15
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#18
+  StoreFieldTOS        CP#17
   Push                 r2
-  PushConstant         CP#20
-  StoreFieldTOS        CP#21
+  PushConstant         CP#19
+  StoreFieldTOS        CP#20
   Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#23
+  StoreFieldTOS        CP#22
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
   PopLocal             r6
   Push                 r6
-  PushConstant         CP#25
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#24
   PopLocal             r3
   Push                 r6
-  PushConstant         CP#26
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#26
   PopLocal             r4
   Push                 r6
-  PushConstant         CP#27
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#28
   PopLocal             r5
   Push                 r0
   LoadContextVar       0, 0
   Push                 r6
-  DynamicCall          2, CP#28
+  DynamicCall          2, CP#31
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  InterfaceCall        1, CP#29
+  InterfaceCall        1, CP#32
   ReturnTOS
 }
 ConstantPool {
   [0] = Class dart:async::_AsyncAwaitCompleter
-  [1] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::int >
+  [2] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
   [4] = ClosureFunction 0
-  [5] = Null
+  [5] = ObjectRef null
   [6] = InstanceField dart:core::_Closure::_context (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 2, num-type-args 0, names []
-  [9] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#8
+  [8] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [9] = Reserved
   [10] = Type dynamic
-  [11] = ArgDesc num-args 3, num-type-args 0, names []
-  [12] = InterfaceCall target-name 'completeError', arg-desc CP#11
-  [13] = Reserved
-  [14] = EndClosureFunctionScope
-  [15] = Class dart:core::_Closure
-  [16] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [17] = Reserved
-  [18] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [19] = Reserved
-  [20] = EmptyTypeArguments
-  [21] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [22] = Reserved
-  [23] = InstanceField dart:core::_Closure::_function (field)
-  [24] = Reserved
-  [25] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#2
-  [26] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#2
-  [27] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#2
-  [28] = ICData dynamic target-name 'start', arg-desc CP#8
-  [29] = InterfaceCall get target-name 'get:future', arg-desc CP#2
-  [30] = Reserved
+  [11] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [12] = Reserved
+  [13] = EndClosureFunctionScope
+  [14] = Class dart:core::_Closure
+  [15] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [16] = Reserved
+  [17] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [18] = Reserved
+  [19] = EmptyTypeArguments
+  [20] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [21] = Reserved
+  [22] = InstanceField dart:core::_Closure::_function (field)
+  [23] = Reserved
+  [24] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [25] = Reserved
+  [26] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [27] = Reserved
+  [28] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [29] = Reserved
+  [30] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [31] = ICData dynamic target-name 'start', arg-desc CP#30
+  [32] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
 }
-Closure #lib::foo:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::foo::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#5
@@ -415,8 +411,7 @@
   LoadContextVar       0, 0
   Push                 r4
   LoadContextVar       0, 1
-  PushConstant         CP#9
-  IndirectStaticCall   2, CP#8
+  DirectCall           2, CP#8
   Drop1
   PushNull
   ReturnTOS
@@ -435,7 +430,7 @@
   LoadContextVar       0, 0
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#12
+  InterfaceCall        3, CP#11
   Drop1
   Jump                 L3
 L3:
@@ -490,8 +485,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   StoreContextVar      0, 2
   Push                 r0
@@ -518,91 +512,90 @@
   PushNull
   StoreContextVar      0, 9
   Push                 r0
-  Allocate             CP#20
+  Allocate             CP#18
   StoreLocal           r2
   Push                 r2
   PushNull
+  StoreFieldTOS        CP#19
+  Push                 r2
+  PushNull
   StoreFieldTOS        CP#21
   Push                 r2
-  PushNull
-  StoreFieldTOS        CP#23
-  Push                 r2
-  PushConstant         CP#25
-  StoreFieldTOS        CP#26
+  PushConstant         CP#23
+  StoreFieldTOS        CP#24
   Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#28
+  StoreFieldTOS        CP#26
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#30
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#28
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#31
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#30
   StoreContextVar      0, 4
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#32
   StoreContextVar      0, 5
   Push                 r0
   LoadContextVar       0, 2
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          2, CP#33
+  DynamicCall          2, CP#35
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  InterfaceCall        1, CP#34
+  InterfaceCall        1, CP#36
   ReturnTOS
 }
 ConstantPool {
   [0] = Class dart:async::_AsyncAwaitCompleter
-  [1] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::int >
+  [2] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
   [4] = ClosureFunction 0
-  [5] = Null
+  [5] = ObjectRef null
   [6] = InstanceField dart:core::_Closure::_context (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [10] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [11] = ArgDesc num-args 2, num-type-args 0, names []
-  [12] = InterfaceCall target-name '+', arg-desc CP#11
+  [8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [9] = Reserved
+  [10] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
+  [11] = Reserved
+  [12] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
   [13] = Reserved
-  [14] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#11
-  [15] = Type dynamic
-  [16] = ArgDesc num-args 3, num-type-args 0, names []
-  [17] = InterfaceCall target-name 'completeError', arg-desc CP#16
-  [18] = Reserved
-  [19] = EndClosureFunctionScope
-  [20] = Class dart:core::_Closure
-  [21] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [14] = Type dynamic
+  [15] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [16] = Reserved
+  [17] = EndClosureFunctionScope
+  [18] = Class dart:core::_Closure
+  [19] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [20] = Reserved
+  [21] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [22] = Reserved
-  [23] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [24] = Reserved
-  [25] = EmptyTypeArguments
-  [26] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [23] = EmptyTypeArguments
+  [24] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [25] = Reserved
+  [26] = InstanceField dart:core::_Closure::_function (field)
   [27] = Reserved
-  [28] = InstanceField dart:core::_Closure::_function (field)
+  [28] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
   [29] = Reserved
-  [30] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#2
-  [31] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#2
-  [32] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#2
-  [33] = ICData dynamic target-name 'start', arg-desc CP#11
-  [34] = InterfaceCall get target-name 'get:future', arg-desc CP#2
-  [35] = Reserved
+  [30] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [35] = ICData dynamic target-name 'start', arg-desc CP#34
+  [36] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [37] = Reserved
 }
-Closure #lib::simpleAsyncAwait:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::simpleAsyncAwait::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#5
@@ -636,8 +629,7 @@
   LoadContextVar       0, 5
   Push                 r4
   LoadContextVar       0, 10
-  PushConstant         CP#9
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -665,8 +657,7 @@
   LoadContextVar       0, 5
   Push                 r4
   LoadContextVar       0, 10
-  PushConstant         CP#10
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r9
   PushNull
   ReturnTOS
@@ -681,7 +672,7 @@
   Push                 r4
   LoadContextVar       0, 9
   Push                 r1
-  InterfaceCall        2, CP#12
+  InterfaceCall        2, CP#10
   StoreContextVar      0, 3
   Jump                 L4
 L4:
@@ -689,8 +680,7 @@
   LoadContextVar       0, 2
   Push                 r4
   LoadContextVar       0, 3
-  PushConstant         CP#14
-  IndirectStaticCall   2, CP#11
+  DirectCall           2, CP#12
   Drop1
   PushNull
   ReturnTOS
@@ -713,7 +703,7 @@
   LoadContextVar       0, 2
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#17
+  InterfaceCall        3, CP#15
   Drop1
   Jump                 L5
 L5:
@@ -776,8 +766,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -807,98 +796,98 @@
   PushNull
   StoreContextVar      0, 9
   Push                 r0
-  Allocate             CP#27
+  Allocate             CP#26
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#28
+  StoreFieldTOS        CP#27
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#30
+  StoreFieldTOS        CP#29
   Push                 r2
-  PushConstant         CP#32
-  StoreFieldTOS        CP#33
+  PushConstant         CP#31
+  StoreFieldTOS        CP#32
   Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#35
+  StoreFieldTOS        CP#34
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
   StoreContextVar      0, 10
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#37
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#36
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#38
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#38
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 10
-  PushConstant         CP#39
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#40
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 10
-  DynamicCall          2, CP#40
+  DynamicCall          2, CP#43
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#41
+  InterfaceCall        1, CP#44
   ReturnTOS
 }
 ConstantPool {
   [0] = Class dart:async::_AsyncAwaitCompleter
-  [1] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::int >
+  [2] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
   [4] = ClosureFunction 0
-  [5] = Null
+  [5] = ObjectRef null
   [6] = InstanceField dart:core::_Closure::_context (field)
   [7] = Reserved
-  [8] = InterfaceCall get target-name 'get:iterator', arg-desc CP#2
+  [8] = InterfaceCall 'dart:core::Iterable::get:iterator', ArgDesc num-args 1, num-type-args 0, names []
   [9] = Reserved
-  [10] = InterfaceCall target-name 'moveNext', arg-desc CP#2
+  [10] = InterfaceCall 'dart:core::Iterator::moveNext', ArgDesc num-args 1, num-type-args 0, names []
   [11] = Reserved
-  [12] = InterfaceCall get target-name 'get:current', arg-desc CP#2
+  [12] = InterfaceCall 'dart:core::Iterator::get:current', ArgDesc num-args 1, num-type-args 0, names []
   [13] = Reserved
-  [14] = ArgDesc num-args 0, num-type-args 0, names []
-  [15] = StaticICData target '#lib::foo', arg-desc CP#14
-  [16] = ArgDesc num-args 4, num-type-args 0, names []
-  [17] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#16
-  [18] = ArgDesc num-args 2, num-type-args 0, names []
-  [19] = InterfaceCall target-name '+', arg-desc CP#18
-  [20] = Reserved
-  [21] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#18
+  [14] = DirectCall '#lib::foo', ArgDesc num-args 0, num-type-args 0, names []
+  [15] = Reserved
+  [16] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [17] = Reserved
+  [18] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
+  [19] = Reserved
+  [20] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [21] = Reserved
   [22] = Type dynamic
-  [23] = ArgDesc num-args 3, num-type-args 0, names []
-  [24] = InterfaceCall target-name 'completeError', arg-desc CP#23
-  [25] = Reserved
-  [26] = EndClosureFunctionScope
-  [27] = Class dart:core::_Closure
-  [28] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [29] = Reserved
-  [30] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [31] = Reserved
-  [32] = EmptyTypeArguments
-  [33] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [34] = Reserved
-  [35] = InstanceField dart:core::_Closure::_function (field)
-  [36] = Reserved
-  [37] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#2
-  [38] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#2
-  [39] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#2
-  [40] = ICData dynamic target-name 'start', arg-desc CP#18
-  [41] = InterfaceCall get target-name 'get:future', arg-desc CP#2
-  [42] = Reserved
+  [23] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [24] = Reserved
+  [25] = EndClosureFunctionScope
+  [26] = Class dart:core::_Closure
+  [27] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [28] = Reserved
+  [29] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [30] = Reserved
+  [31] = EmptyTypeArguments
+  [32] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [33] = Reserved
+  [34] = InstanceField dart:core::_Closure::_function (field)
+  [35] = Reserved
+  [36] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [37] = Reserved
+  [38] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [39] = Reserved
+  [40] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [41] = Reserved
+  [42] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [43] = ICData dynamic target-name 'start', arg-desc CP#42
+  [44] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [45] = Reserved
 }
-Closure #lib::loops:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::loops::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#5
@@ -1001,8 +990,7 @@
   LoadContextParent
   Push                 r4
   StoreContextVar      0, 6
-  PushConstant         CP#15
-  IndirectStaticCall   0, CP#14
+  DirectCall           0, CP#14
   Push                 r4
   LoadContextParent
   LoadContextParent
@@ -1018,8 +1006,7 @@
   LoadContextParent
   LoadContextParent
   LoadContextVar       0, 10
-  PushConstant         CP#17
-  IndirectStaticCall   4, CP#16
+  DirectCall           4, CP#16
   PopLocal             r10
   PushNull
   ReturnTOS
@@ -1044,8 +1031,8 @@
   LoadContextParent
   LoadContextVar       0, 8
   Push                 r1
-  InterfaceCall        2, CP#19
-  InterfaceCall        2, CP#19
+  InterfaceCall        2, CP#18
+  InterfaceCall        2, CP#18
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1104,8 +1091,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  PushConstant         CP#21
-  IndirectStaticCall   2, CP#18
+  DirectCall           2, CP#20
   Drop1
   PushNull
   ReturnTOS
@@ -1128,7 +1114,7 @@
   LoadContextVar       0, 1
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#24
+  InterfaceCall        3, CP#23
   Drop1
   Jump                 L10
 L10:
@@ -1204,8 +1190,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   StoreContextVar      0, 3
   Push                 r0
@@ -1244,101 +1229,96 @@
   PushNull
   StoreContextVar      0, 14
   Push                 r0
-  Allocate             CP#30
+  Allocate             CP#24
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#31
+  StoreFieldTOS        CP#25
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#33
+  StoreFieldTOS        CP#27
   Push                 r2
-  PushConstant         CP#35
-  StoreFieldTOS        CP#36
+  PushConstant         CP#29
+  StoreFieldTOS        CP#30
   Push                 r2
   PushConstant         CP#4
-  StoreFieldTOS        CP#38
+  StoreFieldTOS        CP#32
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#6
   StoreContextVar      0, 15
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#40
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#34
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#41
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#36
   StoreContextVar      0, 5
   Push                 r0
   Push                 r0
   LoadContextVar       0, 15
-  PushConstant         CP#42
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#38
   StoreContextVar      0, 6
   Push                 r0
   LoadContextVar       0, 3
   Push                 r0
   LoadContextVar       0, 15
-  DynamicCall          2, CP#43
+  DynamicCall          2, CP#41
   Drop1
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        1, CP#44
+  InterfaceCall        1, CP#42
   ReturnTOS
 }
 ConstantPool {
   [0] = Class dart:async::_AsyncAwaitCompleter
-  [1] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::int >
+  [2] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
   [4] = ClosureFunction 0
-  [5] = Null
+  [5] = ObjectRef null
   [6] = InstanceField dart:core::_Closure::_context (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [10] = ArgDesc num-args 2, num-type-args 0, names []
-  [11] = InterfaceCall target-name '+', arg-desc CP#10
-  [12] = Reserved
-  [13] = Type dynamic
-  [14] = Type dart:core::Error
-  [15] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#10
-  [16] = Reserved
-  [17] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [18] = String 'fin'
-  [19] = StaticICData target 'dart:core::print', arg-desc CP#2
-  [20] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [21] = StaticICData target 'dart:core::print', arg-desc CP#2
-  [22] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [23] = StaticICData target 'dart:core::print', arg-desc CP#2
-  [24] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [25] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#10
-  [26] = ArgDesc num-args 3, num-type-args 0, names []
-  [27] = InterfaceCall target-name 'completeError', arg-desc CP#26
+  [8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [9] = Reserved
+  [10] = InterfaceCall 'dart:core::num::+', ArgDesc num-args 2, num-type-args 0, names []
+  [11] = Reserved
+  [12] = Type dynamic
+  [13] = Type dart:core::Error
+  [14] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+  [15] = Reserved
+  [16] = ObjectRef 'fin'
+  [17] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [18] = Reserved
+  [19] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [20] = Reserved
+  [21] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [22] = Reserved
+  [23] = EndClosureFunctionScope
+  [24] = Class dart:core::_Closure
+  [25] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [26] = Reserved
+  [27] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [28] = Reserved
-  [29] = EndClosureFunctionScope
-  [30] = Class dart:core::_Closure
-  [31] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [32] = Reserved
-  [33] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [34] = Reserved
-  [35] = EmptyTypeArguments
-  [36] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [29] = EmptyTypeArguments
+  [30] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [31] = Reserved
+  [32] = InstanceField dart:core::_Closure::_function (field)
+  [33] = Reserved
+  [34] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [35] = Reserved
+  [36] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [37] = Reserved
-  [38] = InstanceField dart:core::_Closure::_function (field)
+  [38] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [39] = Reserved
-  [40] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#2
-  [41] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#2
-  [42] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#2
-  [43] = ICData dynamic target-name 'start', arg-desc CP#10
-  [44] = InterfaceCall get target-name 'get:future', arg-desc CP#2
-  [45] = Reserved
+  [40] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [41] = ICData dynamic target-name 'start', arg-desc CP#40
+  [42] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [43] = Reserved
 }
-Closure #lib::tryCatchRethrow:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::tryCatchRethrow::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#5
@@ -1402,8 +1382,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#9
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r13
   PushNull
   ReturnTOS
@@ -1419,7 +1398,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Jump                 L3
 Try #2 end:
@@ -1446,8 +1425,8 @@
   StoreContextVar      1, 1
   Push                 r4
   LoadContextVar       1, 1
-  PushConstant         CP#14
-  InterfaceCall        2, CP#15
+  PushConstant         CP#13
+  InterfaceCall        2, CP#14
   JumpIfFalse          L4
   Push                 r4
   LoadContextParent
@@ -1480,8 +1459,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#17
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r13
   PushNull
   ReturnTOS
@@ -1497,7 +1475,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1527,9 +1505,8 @@
   LoadContextParent
   Push                 r9
   StoreContextVar      0, 13
-  PushConstant         CP#18
-  PushConstant         CP#19
-  IndirectStaticCall   1, CP#2
+  PushConstant         CP#16
+  DirectCall           1, CP#17
   Drop1
   Push                 r4
   LoadContextParent
@@ -1556,8 +1533,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#20
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1573,7 +1549,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1591,9 +1567,8 @@
   Push                 r4
   LoadContextVar       0, 10
   PopLocal             r4
-  PushConstant         CP#18
-  PushConstant         CP#21
-  IndirectStaticCall   1, CP#2
+  PushConstant         CP#16
+  DirectCall           1, CP#17
   Drop1
   Push                 r4
   LoadContextParent
@@ -1620,8 +1595,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#22
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1637,7 +1611,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1655,9 +1629,8 @@
   Push                 r4
   LoadContextVar       0, 10
   PopLocal             r4
-  PushConstant         CP#18
-  PushConstant         CP#23
-  IndirectStaticCall   1, CP#2
+  PushConstant         CP#16
+  DirectCall           1, CP#17
   Drop1
   Push                 r4
   LoadContextParent
@@ -1684,8 +1657,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       0, 15
-  PushConstant         CP#24
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r12
   PushNull
   ReturnTOS
@@ -1701,7 +1673,7 @@
   LoadContextParent
   LoadContextVar       0, 14
   Push                 r1
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   StoreContextVar      1, 0
   Push                 r4
   LoadContextParent
@@ -1717,8 +1689,7 @@
   LoadContextVar       0, 3
   Push                 r4
   LoadContextVar       0, 4
-  PushConstant         CP#25
-  IndirectStaticCall   2, CP#10
+  DirectCall           2, CP#19
   Drop1
   PushNull
   ReturnTOS
@@ -1741,7 +1712,7 @@
   LoadContextVar       0, 3
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#27
+  InterfaceCall        3, CP#21
   Drop1
   Jump                 L12
 L12:
@@ -1834,20 +1805,20 @@
   Push                 r0
   PushInt              3
   StoreContextVar      0, 1
-  Allocate             CP#21
+  Allocate             CP#20
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#21
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#24
+  StoreFieldTOS        CP#23
   Push                 r3
-  PushConstant         CP#26
-  StoreFieldTOS        CP#27
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r3
   PushConstant         CP#0
-  StoreFieldTOS        CP#29
+  StoreFieldTOS        CP#28
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
@@ -1860,42 +1831,45 @@
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
   [3] = Class dart:async::_AsyncAwaitCompleter
-  [4] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#5
+  [4] = ObjectRef < dart:core::int >
+  [5] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
   [7] = ClosureFunction 1
-  [8] = Null
-  [9] = ArgDesc num-args 4, num-type-args 0, names []
-  [10] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#9
+  [8] = ObjectRef null
+  [9] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [10] = Reserved
   [11] = Type dynamic
-  [12] = String 'fin'
-  [13] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [14] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [15] = ArgDesc num-args 2, num-type-args 0, names []
-  [16] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#15
-  [17] = ArgDesc num-args 3, num-type-args 0, names []
-  [18] = InterfaceCall target-name 'completeError', arg-desc CP#17
-  [19] = Reserved
-  [20] = EndClosureFunctionScope
-  [21] = Class dart:core::_Closure
-  [22] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [23] = Reserved
-  [24] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [25] = Reserved
-  [26] = EmptyTypeArguments
-  [27] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [28] = Reserved
-  [29] = InstanceField dart:core::_Closure::_function (field)
-  [30] = Reserved
-  [31] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#5
-  [32] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#5
-  [33] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#5
-  [34] = ICData dynamic target-name 'start', arg-desc CP#15
-  [35] = InterfaceCall get target-name 'get:future', arg-desc CP#5
-  [36] = Reserved
-  [37] = EndClosureFunctionScope
+  [12] = ObjectRef 'fin'
+  [13] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [14] = Reserved
+  [15] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [16] = Reserved
+  [17] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
+  [18] = Reserved
+  [19] = EndClosureFunctionScope
+  [20] = Class dart:core::_Closure
+  [21] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [22] = Reserved
+  [23] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [24] = Reserved
+  [25] = EmptyTypeArguments
+  [26] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [27] = Reserved
+  [28] = InstanceField dart:core::_Closure::_function (field)
+  [29] = Reserved
+  [30] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [35] = Reserved
+  [36] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [37] = ICData dynamic target-name 'start', arg-desc CP#36
+  [38] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [39] = Reserved
+  [40] = EndClosureFunctionScope
 }
-Closure #lib::closure::nested () -> dart:async::Future < dart:core::int >
+Closure #lib::closure::'nested' () -> dart:async::Future < dart:core::int >
 ClosureBytecode {
   EntryFixed           1, 4
   CheckStack           0
@@ -1914,8 +1888,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#5
   Drop1
   StoreContextVar      1, 0
   Push                 r0
@@ -1942,55 +1915,52 @@
   PushNull
   StoreContextVar      1, 7
   Push                 r0
-  Allocate             CP#21
+  Allocate             CP#20
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#22
+  StoreFieldTOS        CP#21
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#24
+  StoreFieldTOS        CP#23
   Push                 r2
-  PushConstant         CP#26
-  StoreFieldTOS        CP#27
+  PushConstant         CP#25
+  StoreFieldTOS        CP#26
   Push                 r2
   PushConstant         CP#7
-  StoreFieldTOS        CP#29
+  StoreFieldTOS        CP#28
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
   StoreContextVar      1, 8
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#31
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#30
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#32
   StoreContextVar      1, 2
   Push                 r0
   Push                 r0
   LoadContextVar       1, 8
-  PushConstant         CP#33
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#34
   StoreContextVar      1, 3
   Push                 r0
   LoadContextVar       1, 0
   Push                 r0
   LoadContextVar       1, 8
-  DynamicCall          2, CP#34
+  DynamicCall          2, CP#37
   Drop1
   Push                 r0
   LoadContextVar       1, 0
-  InterfaceCall        1, CP#35
+  InterfaceCall        1, CP#38
   ReturnTOS
 
 }
 
-Closure #lib::closure::Closure/0:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::closure::Closure/0::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#8
@@ -2050,8 +2020,7 @@
   Push                 r4
   LoadContextParent
   LoadContextVar       1, 8
-  PushConstant         CP#10
-  IndirectStaticCall   4, CP#9
+  DirectCall           4, CP#9
   PopLocal             r11
   PushNull
   ReturnTOS
@@ -2088,8 +2057,7 @@
   MoveSpecial          exception, r8
   MoveSpecial          stackTrace, r9
   PushConstant         CP#12
-  PushConstant         CP#13
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#13
   Drop1
   Push                 r8
   Push                 r9
@@ -2102,8 +2070,7 @@
   LoadContextVar       1, 7
   PopLocal             r4
   PushConstant         CP#12
-  PushConstant         CP#14
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#13
   Drop1
   Push                 r4
   LoadContextParent
@@ -2114,8 +2081,7 @@
   LoadContextVar       1, 0
   Push                 r4
   LoadContextVar       1, 1
-  PushConstant         CP#16
-  IndirectStaticCall   2, CP#15
+  DirectCall           2, CP#15
   Drop1
   PushNull
   ReturnTOS
@@ -2138,7 +2104,7 @@
   LoadContextVar       1, 0
   Push                 r8
   Push                 r9
-  InterfaceCall        3, CP#18
+  InterfaceCall        3, CP#17
   Drop1
   Jump                 L5
 L5:
@@ -2208,8 +2174,7 @@
   AllocateT
   StoreLocal           r2
   Push                 r2
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   StoreContextVar      0, 1
   Push                 r0
@@ -2253,51 +2218,48 @@
   StoreContextVar      0, 8
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#30
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#30
   PopLocal             r3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#31
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#32
   StoreContextVar      0, 3
   Push                 r0
   Push                 r0
   LoadContextVar       0, 8
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#34
   StoreContextVar      0, 4
   Push                 r0
   LoadContextVar       0, 1
   Push                 r0
   LoadContextVar       0, 8
-  DynamicCall          2, CP#33
+  DynamicCall          2, CP#37
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  InterfaceCall        1, CP#34
+  InterfaceCall        1, CP#38
   ReturnTOS
 }
 ConstantPool {
   [0] = Class dart:async::_AsyncAwaitCompleter
-  [1] = TypeArgumentsForInstanceAllocation dart:async::_AsyncAwaitCompleter [dart:core::int]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:async::_AsyncAwaitCompleter::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::int >
+  [2] = DirectCall 'dart:async::_AsyncAwaitCompleter:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
   [4] = ClosureFunction 0
-  [5] = Null
+  [5] = ObjectRef null
   [6] = InstanceField dart:core::_Closure::_context (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = StaticICData target 'dart:async::_awaitHelper', arg-desc CP#8
-  [10] = ArgDesc num-args 2, num-type-args 0, names []
-  [11] = InterfaceCall target-name '==', arg-desc CP#10
-  [12] = Reserved
-  [13] = ArgDesc num-args 3, num-type-args 0, names []
-  [14] = StaticICData target 'dart:core::_AssertionError::_throwNew', arg-desc CP#13
-  [15] = StaticICData target 'dart:async::_completeOnAsyncReturn', arg-desc CP#10
+  [8] = DirectCall 'dart:async::_awaitHelper', ArgDesc num-args 4, num-type-args 0, names []
+  [9] = Reserved
+  [10] = InterfaceCall 'dart:core::num::==', ArgDesc num-args 2, num-type-args 0, names []
+  [11] = Reserved
+  [12] = DirectCall 'dart:core::_AssertionError::_throwNew', ArgDesc num-args 3, num-type-args 0, names []
+  [13] = Reserved
+  [14] = DirectCall 'dart:async::_completeOnAsyncReturn', ArgDesc num-args 2, num-type-args 0, names []
+  [15] = Reserved
   [16] = Type dynamic
-  [17] = InterfaceCall target-name 'completeError', arg-desc CP#13
+  [17] = InterfaceCall 'dart:async::Completer::completeError', ArgDesc num-args 3, num-type-args 0, names []
   [18] = Reserved
   [19] = EndClosureFunctionScope
   [20] = Class dart:core::_Closure
@@ -2310,14 +2272,18 @@
   [27] = Reserved
   [28] = InstanceField dart:core::_Closure::_function (field)
   [29] = Reserved
-  [30] = StaticICData target 'dart:async::_asyncStackTraceHelper', arg-desc CP#2
-  [31] = StaticICData target 'dart:async::_asyncThenWrapperHelper', arg-desc CP#2
-  [32] = StaticICData target 'dart:async::_asyncErrorWrapperHelper', arg-desc CP#2
-  [33] = ICData dynamic target-name 'start', arg-desc CP#10
-  [34] = InterfaceCall get target-name 'get:future', arg-desc CP#2
+  [30] = DirectCall 'dart:async::_asyncStackTraceHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [31] = Reserved
+  [32] = DirectCall 'dart:async::_asyncThenWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
+  [33] = Reserved
+  [34] = DirectCall 'dart:async::_asyncErrorWrapperHelper', ArgDesc num-args 1, num-type-args 0, names []
   [35] = Reserved
+  [36] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [37] = ICData dynamic target-name 'start', arg-desc CP#36
+  [38] = InterfaceCall 'dart:async::Completer::get:future', ArgDesc num-args 1, num-type-args 0, names []
+  [39] = Reserved
 }
-Closure #lib::testAssert:::async_op ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
+Closure #lib::testAssert::':async_op' ([ dynamic :result, dynamic :exception, dynamic :stack_trace ]) -> dynamic
 ClosureBytecode {
   EntryOptional        1, 3, 0
   LoadConstant         r1, CP#5
@@ -2352,8 +2318,7 @@
   LoadContextVar       0, 4
   Push                 r4
   LoadContextVar       0, 8
-  PushConstant         CP#9
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r8
   PushNull
   ReturnTOS
@@ -2367,14 +2332,13 @@
   JumpIfNoAsserts      L2
   Push                 r1
   PushInt              42
-  InterfaceCall        2, CP#11
+  InterfaceCall        2, CP#10
   AssertBoolean        0
   JumpIfTrue           L2
   PushInt              0
   PushInt              0
   PushNull
-  PushConstant         CP#14
-  IndirectStaticCall   3, CP#13
+  DirectCall           3, CP#12
   Drop1
 L2:
   Push                 r4
@@ -2386,8 +2350,7 @@
   LoadContextVar       0, 1
   Push                 r4
   LoadContextVar       0, 2
-  PushConstant         CP#15
-  IndirectStaticCall   2, CP#10
+  DirectCall           2, CP#14
   Drop1
   PushNull
   ReturnTOS
diff --git a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
index ed981f0..31b1d4a 100644
--- a/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
+++ b/pkg/vm/testcases/bytecode/bootstrapping.dart.expect
@@ -11,15 +11,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::_ScheduleImmediate
     : super core::Object::•()
@@ -32,15 +31,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor _() → self::_NamespaceImpl
     : super core::Object::•()
@@ -91,22 +89,20 @@
   Allocate             CP#0
   StoreLocal           r1
   Push                 r1
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Push                 FP[-5]
-  PushConstant         CP#4
-  IndirectStaticCall   2, CP#3
+  DirectCall           2, CP#3
   StoreStaticTOS       CP#5
   PushNull
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::_NamespaceImpl
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target '#lib::_NamespaceImpl::_ (constructor)', arg-desc CP#1
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = StaticICData target '#lib::_NamespaceImpl::_create', arg-desc CP#3
+  [1] = DirectCall '#lib::_NamespaceImpl::_ (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
+  [3] = DirectCall '#lib::_NamespaceImpl::_create', ArgDesc num-args 2, num-type-args 0, names []
+  [4] = Reserved
   [5] = StaticField #lib::_NamespaceImpl::_cachedNamespace (field)
 }
 ]  static method _setupNamespace(dynamic namespace) → void {
@@ -123,13 +119,10 @@
   Allocate             CP#1
   StoreLocal           r1
   Push                 r1
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
-  PushConstant         CP#5
-  IndirectStaticCall   0, CP#4
-  PushConstant         CP#7
-  IndirectStaticCall   2, CP#6
+  DirectCall           0, CP#4
+  DirectCall           2, CP#6
   StoreStaticTOS       CP#0
 L1:
   PushConstant         CP#0
@@ -139,12 +132,12 @@
 ConstantPool {
   [0] = StaticField #lib::_NamespaceImpl::_cachedNamespace (field)
   [1] = Class #lib::_NamespaceImpl
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target '#lib::_NamespaceImpl::_ (constructor)', arg-desc CP#2
-  [4] = ArgDesc num-args 0, num-type-args 0, names []
-  [5] = StaticICData target '#lib::_NamespaceImpl::_getDefault', arg-desc CP#4
-  [6] = ArgDesc num-args 2, num-type-args 0, names []
-  [7] = StaticICData target '#lib::_NamespaceImpl::_create', arg-desc CP#6
+  [2] = DirectCall '#lib::_NamespaceImpl::_ (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
+  [4] = DirectCall '#lib::_NamespaceImpl::_getDefault', ArgDesc num-args 0, num-type-args 0, names []
+  [5] = Reserved
+  [6] = DirectCall '#lib::_NamespaceImpl::_create', ArgDesc num-args 2, num-type-args 0, names []
+  [7] = Reserved
 }
 ]  static get _namespace() → self::_NamespaceImpl {
     if(self::_NamespaceImpl::_cachedNamespace.{core::Object::==}(null)) {
@@ -156,17 +149,15 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#1
-  IndirectStaticCall   0, CP#0
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           0, CP#0
+  DirectCall           1, CP#2
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 0, num-type-args 0, names []
-  [1] = StaticICData target '#lib::_NamespaceImpl::get:_namespace', arg-desc CP#0
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target '#lib::_NamespaceImpl::_getPointer', arg-desc CP#2
+  [0] = DirectCall '#lib::_NamespaceImpl::get:_namespace', ArgDesc num-args 0, num-type-args 0, names []
+  [1] = Reserved
+  [2] = DirectCall '#lib::_NamespaceImpl::_getPointer', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  static get _namespacePointer() → core::int
     return self::_NamespaceImpl::_getPointer(self::_NamespaceImpl::_namespace);
@@ -177,15 +168,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::_Namespace
     : super core::Object::•()
@@ -195,15 +185,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::_NamespaceImpl::_setupNamespace', arg-desc CP#0
+  [0] = DirectCall '#lib::_NamespaceImpl::_setupNamespace', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  static method _setupNamespace(dynamic namespace) → void {
     self::_NamespaceImpl::_setupNamespace(namespace);
@@ -212,13 +201,12 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#1
-  IndirectStaticCall   0, CP#0
+  DirectCall           0, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 0, num-type-args 0, names []
-  [1] = StaticICData target '#lib::_NamespaceImpl::get:_namespace', arg-desc CP#0
+  [0] = DirectCall '#lib::_NamespaceImpl::get:_namespace', ArgDesc num-args 0, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  static get _namespace() → self::_Namespace
     return self::_NamespaceImpl::_namespace;
@@ -226,13 +214,12 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#1
-  IndirectStaticCall   0, CP#0
+  DirectCall           0, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 0, num-type-args 0, names []
-  [1] = StaticICData target '#lib::_NamespaceImpl::get:_namespacePointer', arg-desc CP#0
+  [0] = DirectCall '#lib::_NamespaceImpl::get:_namespacePointer', ArgDesc num-args 0, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  static get _namespacePointer() → core::int
     return self::_NamespaceImpl::_namespacePointer;
@@ -254,15 +241,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::VMLibraryHooks
     : super core::Object::•()
@@ -318,7 +304,7 @@
 ConstantPool {
   [0] = StaticField #lib::VMLibraryHooks::_cachedScript (field)
   [1] = StaticField #lib::VMLibraryHooks::_computeScriptUri (field)
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
+  [2] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
   [3] = ICData dynamic target-name 'call', arg-desc CP#2
 }
 ]  static get platformScript() → dynamic {
@@ -334,15 +320,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::Stdin
     : super core::Object::•()
@@ -354,15 +339,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::_StdIOUtils
     : super core::Object::•()
@@ -402,18 +386,17 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#0
+  InterfaceCall        1, CP#0
+  DirectCall           1, CP#2
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall target-name 'toString', arg-desc CP#0
-  [2] = Reserved
-  [3] = StaticICData target '#lib::_printString', arg-desc CP#0
+  [0] = InterfaceCall 'dart:core::Object::toString', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = DirectCall '#lib::_printString', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method _print(dynamic arg) → void {
   self::_printString(arg.{core::Object::toString}());
@@ -426,7 +409,7 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = TearOff #lib::_print
+  [0] = ObjectRef const tear-off #lib::_print
 }
 ]static method _getPrintClosure() → dynamic
   return self::_print;
@@ -475,13 +458,13 @@
   PushConstant         CP#0
   PushStatic           CP#0
   PushConstant         CP#1
-  InterfaceCall        2, CP#3
+  InterfaceCall        2, CP#2
   AssertBoolean        0
   JumpIfTrue           L1
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#5
-  InterfaceCall        2, CP#3
+  PushConstant         CP#4
+  InterfaceCall        2, CP#2
   AssertBoolean        0
   PopLocal             r1
   Jump                 L2
@@ -493,8 +476,8 @@
   JumpIfTrue           L3
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#6
-  InterfaceCall        2, CP#3
+  PushConstant         CP#5
+  InterfaceCall        2, CP#2
   AssertBoolean        0
   PopLocal             r0
   Jump                 L4
@@ -506,34 +489,31 @@
   JumpIfFalse          L5
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#6
   ReturnTOS
 L5:
-  PushConstant         CP#10
-  IndirectStaticCall   0, CP#9
+  DirectCall           0, CP#8
   PushNull
   PushConstant         CP#0
   PushStatic           CP#0
-  PushConstant         CP#11
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#10
   InterfaceCall        2, CP#12
   ReturnTOS
 }
 ConstantPool {
   [0] = StaticField #lib::_rawScript (field)
-  [1] = String 'http:'
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = InterfaceCall target-name 'startsWith', arg-desc CP#2
-  [4] = Reserved
-  [5] = String 'https:'
-  [6] = String 'file:'
-  [7] = ArgDesc num-args 1, num-type-args 0, names []
-  [8] = StaticICData target 'dart:core::Uri::parse', arg-desc CP#7
-  [9] = ArgDesc num-args 0, num-type-args 0, names []
-  [10] = StaticICData target 'dart:core::Uri::get:base', arg-desc CP#9
-  [11] = StaticICData target 'dart:core::_Uri::file (constructor)', arg-desc CP#2
-  [12] = InterfaceCall target-name 'resolveUri', arg-desc CP#2
+  [1] = ObjectRef 'http:'
+  [2] = InterfaceCall 'dart:core::String::startsWith', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
+  [4] = ObjectRef 'https:'
+  [5] = ObjectRef 'file:'
+  [6] = DirectCall 'dart:core::Uri::parse', ArgDesc num-args 1, num-type-args 0, names []
+  [7] = Reserved
+  [8] = DirectCall 'dart:core::Uri::get:base', ArgDesc num-args 0, num-type-args 0, names []
+  [9] = Reserved
+  [10] = DirectCall 'dart:core::_Uri::file (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [11] = Reserved
+  [12] = InterfaceCall 'dart:core::Uri::resolveUri', ArgDesc num-args 2, num-type-args 0, names []
   [13] = Reserved
 }
 ]static method _scriptUri() → core::Uri {
@@ -549,16 +529,15 @@
   Entry                1
   CheckStack           0
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TearOff #lib::_scriptUri
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target '#lib::VMLibraryHooks::set:platformScript', arg-desc CP#1
+  [0] = ObjectRef const tear-off #lib::_scriptUri
+  [1] = DirectCall '#lib::VMLibraryHooks::set:platformScript', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method _setupHooks() → dynamic {
   self::VMLibraryHooks::platformScript = self::_scriptUri;
@@ -573,8 +552,7 @@
   JumpIfFalse          L1
   PushConstant         CP#1
   PushStatic           CP#1
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   StoreLocal           r1
   Push                 r1
   StoreStaticTOS       CP#0
@@ -593,8 +571,8 @@
 ConstantPool {
   [0] = StaticField #lib::_stdin (field)
   [1] = StaticField #lib::_stdinFD (field)
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target '#lib::_StdIOUtils::_getStdioInputStream', arg-desc CP#2
+  [2] = DirectCall '#lib::_StdIOUtils::_getStdioInputStream', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static get stdin() → self::Stdin {
   self::_stdin.{core::Object::==}(null) ?{self::Stdin} self::_stdin = self::_StdIOUtils::_getStdioInputStream(self::_stdinFD) : null;
diff --git a/pkg/vm/testcases/bytecode/closures.dart.expect b/pkg/vm/testcases/bytecode/closures.dart.expect
index cbe6532..6eaeaf0 100644
--- a/pkg/vm/testcases/bytecode/closures.dart.expect
+++ b/pkg/vm/testcases/bytecode/closures.dart.expect
@@ -9,15 +9,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C1
     : super core::Object::•()
@@ -29,15 +28,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C2
     : super core::Object::•()
@@ -49,15 +47,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C3
     : super core::Object::•()
@@ -69,15 +66,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C4
     : super core::Object::•()
@@ -89,15 +85,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C5
     : super core::Object::•()
@@ -109,15 +104,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C6
     : super core::Object::•()
@@ -129,15 +123,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C7
     : super core::Object::•()
@@ -149,15 +142,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C8
     : super core::Object::•()
@@ -169,15 +161,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::A<self::A::T1, self::A::T2>
     : super core::Object::•()
@@ -192,12 +183,12 @@
   Push                 r1
   Push                 FP[-5]
   StoreContextVar      0, 0
-  Allocate             CP#31
+  Allocate             CP#30
   StoreLocal           r4
   Push                 r4
   Push                 FP[-5]
-  LoadTypeArgumentsField CP#15
-  StoreFieldTOS        CP#32
+  LoadTypeArgumentsField CP#14
+  StoreFieldTOS        CP#31
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#6
@@ -206,7 +197,7 @@
   StoreFieldTOS        CP#3
   Push                 r4
   PushConstant         CP#0
-  StoreFieldTOS        CP#34
+  StoreFieldTOS        CP#33
   Push                 r4
   Push                 r1
   StoreFieldTOS        CP#1
@@ -231,48 +222,48 @@
   [5] = EmptyTypeArguments
   [6] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = StaticICData target 'dart:_internal::_prependTypeArguments', arg-desc CP#8
+  [8] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names []
+  [9] = Reserved
   [10] = ClosureFunction 1
-  [11] = StaticICData target 'dart:_internal::_prependTypeArguments', arg-desc CP#8
-  [12] = ClosureFunction 2
-  [13] = TypeArgs [dart:core::Type]
-  [14] = Type #lib::A::TypeParam/0
-  [15] = TypeArgumentsField #lib::A
-  [16] = Type #lib::A::TypeParam/1
-  [17] = Type #lib::A::foo::TypeParam/0
-  [18] = Type #lib::A::foo::TypeParam/1
-  [19] = Type #lib::A::foo::Closure/0::TypeParam/0
-  [20] = Type #lib::A::foo::Closure/0::TypeParam/1
-  [21] = Type #lib::A::foo::Closure/1::TypeParam/0
-  [22] = Type #lib::A::foo::Closure/1::TypeParam/1
-  [23] = ArgDesc num-args 2, num-type-args 0, names []
-  [24] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#23
-  [25] = ArgDesc num-args 1, num-type-args 0, names []
-  [26] = StaticICData target 'dart:core::print', arg-desc CP#25
-  [27] = TypeArgs [#lib::A::TypeParam/0, #lib::A::TypeParam/1, #lib::A::foo::TypeParam/0, #lib::A::foo::TypeParam/1, #lib::A::foo::Closure/0::TypeParam/0, #lib::A::foo::Closure/0::TypeParam/1, #lib::A::foo::Closure/1::TypeParam/0, #lib::A::foo::Closure/1::TypeParam/1]
-  [28] = ArgDesc num-args 0, num-type-args 8, names []
-  [29] = StaticICData target '#lib::callWithArgs', arg-desc CP#28
-  [30] = EndClosureFunctionScope
-  [31] = Class dart:core::_Closure
-  [32] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [33] = Reserved
-  [34] = InstanceField dart:core::_Closure::_function (field)
-  [35] = Reserved
-  [36] = ICData dynamic target-name 'call', arg-desc CP#25
+  [11] = ClosureFunction 2
+  [12] = ObjectRef < dart:core::Type >
+  [13] = Type #lib::A::TypeParam/0
+  [14] = TypeArgumentsField #lib::A
+  [15] = Type #lib::A::TypeParam/1
+  [16] = Type #lib::A::foo::TypeParam/0
+  [17] = Type #lib::A::foo::TypeParam/1
+  [18] = Type #lib::A::foo::Closure/0::TypeParam/0
+  [19] = Type #lib::A::foo::Closure/0::TypeParam/1
+  [20] = Type #lib::A::foo::Closure/1::TypeParam/0
+  [21] = Type #lib::A::foo::Closure/1::TypeParam/1
+  [22] = DirectCall 'dart:core::List::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [23] = Reserved
+  [24] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [25] = Reserved
+  [26] = ObjectRef < #lib::A::TypeParam/0, #lib::A::TypeParam/1, #lib::A::foo::TypeParam/0, #lib::A::foo::TypeParam/1, #lib::A::foo::Closure/0::TypeParam/0, #lib::A::foo::Closure/0::TypeParam/1, #lib::A::foo::Closure/1::TypeParam/0, #lib::A::foo::Closure/1::TypeParam/1 >
+  [27] = DirectCall '#lib::callWithArgs', ArgDesc num-args 0, num-type-args 8, names []
+  [28] = Reserved
+  [29] = EndClosureFunctionScope
+  [30] = Class dart:core::_Closure
+  [31] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [32] = Reserved
+  [33] = InstanceField dart:core::_Closure::_function (field)
+  [34] = Reserved
+  [35] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [36] = ICData dynamic target-name 'call', arg-desc CP#35
   [37] = EndClosureFunctionScope
-  [38] = TypeArgs [#lib::C7, #lib::C8]
-  [39] = ArgDesc num-args 1, num-type-args 2, names []
+  [38] = ObjectRef < #lib::C7, #lib::C8 >
+  [39] = ObjectRef ArgDesc num-args 1, num-type-args 2, names []
   [40] = ICData dynamic target-name 'call', arg-desc CP#39
-  [41] = TypeArgs [dart:core::List < #lib::C7 >, dart:core::List < #lib::C8 >]
+  [41] = ObjectRef < dart:core::List < #lib::C7 >, dart:core::List < #lib::C8 > >
   [42] = ICData dynamic target-name 'call', arg-desc CP#39
   [43] = EndClosureFunctionScope
-  [44] = TypeArgs [#lib::C5, #lib::C6]
+  [44] = ObjectRef < #lib::C5, #lib::C6 >
   [45] = ICData dynamic target-name 'call', arg-desc CP#39
-  [46] = TypeArgs [dart:core::List < #lib::C5 >, dart:core::List < #lib::C6 >]
+  [46] = ObjectRef < dart:core::List < #lib::C5 >, dart:core::List < #lib::C6 > >
   [47] = ICData dynamic target-name 'call', arg-desc CP#39
 }
-Closure #lib::A::foo::nested1 <dart:core::Object T5, dart:core::Object T6> () -> void
+Closure #lib::A::foo::'nested1' <dart:core::Object T5, dart:core::Object T6> () -> void
 ClosureBytecode {
   EntryFixed           1, 5
   CheckStack           0
@@ -294,16 +285,15 @@
   LoadFieldTOS         CP#6
   PushInt              2
   PushInt              4
-  PushConstant         CP#9
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r0
-  Allocate             CP#31
+  Allocate             CP#30
   StoreLocal           r4
   Push                 r4
   Push                 r1
   LoadContextVar       0, 0
-  LoadTypeArgumentsField CP#15
-  StoreFieldTOS        CP#32
+  LoadTypeArgumentsField CP#14
+  StoreFieldTOS        CP#31
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#6
@@ -312,7 +302,7 @@
   StoreFieldTOS        CP#3
   Push                 r4
   PushConstant         CP#10
-  StoreFieldTOS        CP#34
+  StoreFieldTOS        CP#33
   Push                 r4
   Push                 r1
   StoreFieldTOS        CP#1
@@ -330,7 +320,7 @@
 
 }
 
-Closure #lib::A::foo::Closure/0::nested2 <dart:core::Object T7, dart:core::Object T8> () -> void
+Closure #lib::A::foo::Closure/0::'nested2' <dart:core::Object T7, dart:core::Object T8> () -> void
 ClosureBytecode {
   EntryFixed           1, 5
   CheckStack           0
@@ -352,16 +342,15 @@
   LoadFieldTOS         CP#6
   PushInt              4
   PushInt              6
-  PushConstant         CP#11
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r0
-  Allocate             CP#31
+  Allocate             CP#30
   StoreLocal           r4
   Push                 r4
   Push                 r1
   LoadContextVar       0, 0
-  LoadTypeArgumentsField CP#15
-  StoreFieldTOS        CP#32
+  LoadTypeArgumentsField CP#14
+  StoreFieldTOS        CP#31
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#6
@@ -369,8 +358,8 @@
   PushConstant         CP#5
   StoreFieldTOS        CP#3
   Push                 r4
-  PushConstant         CP#12
-  StoreFieldTOS        CP#34
+  PushConstant         CP#11
+  StoreFieldTOS        CP#33
   Push                 r4
   Push                 r1
   StoreFieldTOS        CP#1
@@ -383,7 +372,7 @@
 
 }
 
-Closure #lib::A::foo::Closure/1::<anonymous closure> () -> dart:core::Null
+Closure #lib::A::foo::Closure/1::'<anonymous closure>' () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 4
   CheckStack           0
@@ -393,7 +382,7 @@
   Push                 FP[-5]
   LoadFieldTOS         CP#6
   PopLocal             r0
-  PushConstant         CP#13
+  PushConstant         CP#12
   StoreLocal           r3
   Push                 r3
   PushInt              8
@@ -403,66 +392,63 @@
   PushInt              0
   Push                 r1
   LoadContextVar       0, 0
-  LoadTypeArgumentsField CP#15
+  LoadTypeArgumentsField CP#14
   PushNull
-  InstantiateType      CP#14
+  InstantiateType      CP#13
   StoreIndexedTOS
   Push                 r3
   PushInt              1
   Push                 r1
   LoadContextVar       0, 0
-  LoadTypeArgumentsField CP#15
+  LoadTypeArgumentsField CP#14
   PushNull
-  InstantiateType      CP#16
+  InstantiateType      CP#15
   StoreIndexedTOS
   Push                 r3
   PushInt              2
   PushNull
   Push                 r0
-  InstantiateType      CP#17
+  InstantiateType      CP#16
   StoreIndexedTOS
   Push                 r3
   PushInt              3
   PushNull
   Push                 r0
-  InstantiateType      CP#18
+  InstantiateType      CP#17
   StoreIndexedTOS
   Push                 r3
   PushInt              4
   PushNull
   Push                 r0
-  InstantiateType      CP#19
+  InstantiateType      CP#18
   StoreIndexedTOS
   Push                 r3
   PushInt              5
   PushNull
   Push                 r0
-  InstantiateType      CP#20
+  InstantiateType      CP#19
   StoreIndexedTOS
   Push                 r3
   PushInt              6
   PushNull
   Push                 r0
-  InstantiateType      CP#21
+  InstantiateType      CP#20
   StoreIndexedTOS
   Push                 r3
   PushInt              7
   PushNull
   Push                 r0
-  InstantiateType      CP#22
+  InstantiateType      CP#21
   StoreIndexedTOS
-  PushConstant         CP#24
-  IndirectStaticCall   2, CP#23
-  PushConstant         CP#26
-  IndirectStaticCall   1, CP#25
+  DirectCall           2, CP#22
+  DirectCall           1, CP#24
   Drop1
   Push                 r1
   LoadContextVar       0, 0
-  LoadTypeArgumentsField CP#15
+  LoadTypeArgumentsField CP#14
   Push                 r0
-  InstantiateTypeArgumentsTOS 0, CP#27
-  PushConstant         CP#29
-  IndirectStaticCall   1, CP#28
+  InstantiateTypeArgumentsTOS 0, CP#26
+  DirectCall           1, CP#27
   Drop1
   PushNull
   ReturnTOS
@@ -491,16 +477,15 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 Nullable fields: [#lib::B::foo (field)]}
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::B
     : super core::Object::•()
@@ -522,69 +507,66 @@
   Push                 r0
   PushInt              3
   StoreContextVar      0, 2
-  Allocate             CP#11
+  Allocate             CP#10
   StoreLocal           r4
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#13
   Push                 r4
-  PushConstant         CP#16
-  StoreFieldTOS        CP#17
+  PushConstant         CP#15
+  StoreFieldTOS        CP#16
   Push                 r4
   PushConstant         CP#0
-  StoreFieldTOS        CP#19
+  StoreFieldTOS        CP#18
   Push                 r4
   Push                 r0
   StoreFieldTOS        CP#1
   PopLocal             r3
   Push                 r3
   PushInt              10
-  DynamicCall          2, CP#25
+  DynamicCall          2, CP#26
   Drop1
   Push                 r3
   PushInt              11
-  DynamicCall          2, CP#26
+  DynamicCall          2, CP#27
   Drop1
   Push                 r2
-  PushConstant         CP#27
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#22
   Drop1
   Push                 r0
   LoadContextVar       0, 2
-  PushConstant         CP#28
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#22
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  PushConstant         CP#29
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#22
   Drop1
   Push                 r0
   PushInt              42
   StoreContextVar      0, 3
-  Allocate             CP#11
+  Allocate             CP#10
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#13
   Push                 r3
-  PushConstant         CP#16
-  StoreFieldTOS        CP#17
+  PushConstant         CP#15
+  StoreFieldTOS        CP#16
   Push                 r3
-  PushConstant         CP#30
-  StoreFieldTOS        CP#19
+  PushConstant         CP#28
+  StoreFieldTOS        CP#18
   Push                 r3
   Push                 r0
   StoreFieldTOS        CP#1
   PopLocal             r2
   Push                 r2
-  DynamicCall          1, CP#34
+  DynamicCall          1, CP#32
   Drop1
   PushNull
   ReturnTOS
@@ -594,39 +576,37 @@
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
   [3] = Type dart:core::int
-  [4] = String 'y'
+  [4] = ObjectRef 'y'
   [5] = SubtypeTestCache
   [6] = ClosureFunction 1
-  [7] = ArgDesc num-args 1, num-type-args 0, names []
-  [8] = InterfaceCall get target-name 'get:foo', arg-desc CP#7
-  [9] = Reserved
-  [10] = EndClosureFunctionScope
-  [11] = Class dart:core::_Closure
-  [12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [13] = Reserved
-  [14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [15] = Reserved
-  [16] = EmptyTypeArguments
-  [17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [18] = Reserved
-  [19] = InstanceField dart:core::_Closure::_function (field)
-  [20] = Reserved
-  [21] = ICData dynamic target-name 'call', arg-desc CP#7
-  [22] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [23] = EndClosureFunctionScope
-  [24] = ArgDesc num-args 2, num-type-args 0, names []
-  [25] = ICData dynamic target-name 'call', arg-desc CP#24
-  [26] = ICData dynamic target-name 'call', arg-desc CP#24
-  [27] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [28] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [29] = StaticICData target 'dart:core::print', arg-desc CP#7
-  [30] = ClosureFunction 2
-  [31] = InterfaceCall set target-name 'set:foo', arg-desc CP#24
-  [32] = Reserved
-  [33] = EndClosureFunctionScope
-  [34] = ICData dynamic target-name 'call', arg-desc CP#7
+  [7] = InterfaceCall '#lib::B::get:foo', ArgDesc num-args 1, num-type-args 0, names []
+  [8] = Reserved
+  [9] = EndClosureFunctionScope
+  [10] = Class dart:core::_Closure
+  [11] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [12] = Reserved
+  [13] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [14] = Reserved
+  [15] = EmptyTypeArguments
+  [16] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [17] = Reserved
+  [18] = InstanceField dart:core::_Closure::_function (field)
+  [19] = Reserved
+  [20] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [21] = ICData dynamic target-name 'call', arg-desc CP#20
+  [22] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [23] = Reserved
+  [24] = EndClosureFunctionScope
+  [25] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [26] = ICData dynamic target-name 'call', arg-desc CP#25
+  [27] = ICData dynamic target-name 'call', arg-desc CP#25
+  [28] = ClosureFunction 2
+  [29] = InterfaceCall '#lib::B::set:foo', ArgDesc num-args 2, num-type-args 0, names []
+  [30] = Reserved
+  [31] = EndClosureFunctionScope
+  [32] = ICData dynamic target-name 'call', arg-desc CP#20
 }
-Closure #lib::B::topLevel::<anonymous closure> (dart:core::int y) -> dart:core::Null
+Closure #lib::B::topLevel::'<anonymous closure>' (dart:core::int y) -> dart:core::Null
 ClosureBytecode {
   EntryFixed           2, 4
   CheckStack           0
@@ -665,20 +645,20 @@
   Push                 r0
   PushInt              4
   StoreContextVar      1, 1
-  Allocate             CP#11
+  Allocate             CP#10
   StoreLocal           r2
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r2
   PushNull
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#13
   Push                 r2
-  PushConstant         CP#16
-  StoreFieldTOS        CP#17
+  PushConstant         CP#15
+  StoreFieldTOS        CP#16
   Push                 r2
   PushConstant         CP#6
-  StoreFieldTOS        CP#19
+  StoreFieldTOS        CP#18
   Push                 r2
   Push                 r0
   StoreFieldTOS        CP#1
@@ -688,8 +668,7 @@
   Drop1
   Push                 r0
   LoadContextVar       1, 1
-  PushConstant         CP#22
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#22
   Drop1
 L1:
   PushNull
@@ -697,7 +676,7 @@
 
 }
 
-Closure #lib::B::topLevel::Closure/0::closure2 () -> void
+Closure #lib::B::topLevel::Closure/0::'closure2' () -> void
 ClosureBytecode {
   EntryFixed           1, 3
   CheckStack           0
@@ -716,7 +695,7 @@
   Push                 r0
   LoadContextParent
   LoadContextVar       0, 0
-  InterfaceCall        1, CP#8
+  InterfaceCall        1, CP#7
   Push                 r0
   LoadContextVar       1, 0
   AddInt
@@ -726,7 +705,7 @@
 
 }
 
-Closure #lib::B::topLevel::<anonymous closure> () -> dart:core::Null
+Closure #lib::B::topLevel::'<anonymous closure>' () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 3
   CheckStack           0
@@ -737,7 +716,7 @@
   LoadContextVar       0, 0
   Push                 r0
   LoadContextVar       0, 3
-  InterfaceCall        2, CP#31
+  InterfaceCall        2, CP#29
   Drop1
   PushNull
   ReturnTOS
@@ -783,15 +762,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C
     : super core::Object::•()
@@ -811,8 +789,7 @@
   PushInt              0
   CreateArrayTOS
   StoreLocal           r3
-  PushConstant         CP#2
-  IndirectStaticCall   2, CP#1
+  DirectCall           2, CP#1
   PopLocal             r2
   PushConstant         CP#0
   StoreLocal           r3
@@ -820,8 +797,7 @@
   PushInt              0
   CreateArrayTOS
   StoreLocal           r3
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#1
+  DirectCall           2, CP#1
   PopLocal             r4
   AllocateContext      1, 1
   StoreLocal           r1
@@ -840,44 +816,44 @@
   CompareIntLt
   JumpIfFalse          L1
   Push                 r2
-  Allocate             CP#8
+  Allocate             CP#7
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#9
+  StoreFieldTOS        CP#8
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#11
+  StoreFieldTOS        CP#10
   Push                 r3
-  PushConstant         CP#13
-  StoreFieldTOS        CP#14
+  PushConstant         CP#12
+  StoreFieldTOS        CP#13
   Push                 r3
-  PushConstant         CP#4
-  StoreFieldTOS        CP#16
+  PushConstant         CP#3
+  StoreFieldTOS        CP#15
   Push                 r3
   Push                 r0
-  StoreFieldTOS        CP#5
-  InterfaceCall        2, CP#18
+  StoreFieldTOS        CP#4
+  InterfaceCall        2, CP#17
   Drop1
   Push                 r4
-  Allocate             CP#8
+  Allocate             CP#7
   StoreLocal           r3
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#9
+  StoreFieldTOS        CP#8
   Push                 r3
   PushNull
-  StoreFieldTOS        CP#11
+  StoreFieldTOS        CP#10
   Push                 r3
-  PushConstant         CP#13
-  StoreFieldTOS        CP#14
+  PushConstant         CP#12
+  StoreFieldTOS        CP#13
   Push                 r3
-  PushConstant         CP#20
-  StoreFieldTOS        CP#16
+  PushConstant         CP#19
+  StoreFieldTOS        CP#15
   Push                 r3
   Push                 r0
-  StoreFieldTOS        CP#5
-  InterfaceCall        2, CP#18
+  StoreFieldTOS        CP#4
+  InterfaceCall        2, CP#17
   Drop1
   Push                 r0
   CloneContext         1, 1
@@ -903,38 +879,37 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::Function]
-  [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
-  [3] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
-  [4] = ClosureFunction 0
-  [5] = InstanceField dart:core::_Closure::_context (field)
-  [6] = Reserved
-  [7] = EndClosureFunctionScope
-  [8] = Class dart:core::_Closure
-  [9] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [10] = Reserved
-  [11] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [12] = Reserved
-  [13] = EmptyTypeArguments
-  [14] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [15] = Reserved
-  [16] = InstanceField dart:core::_Closure::_function (field)
-  [17] = Reserved
-  [18] = InterfaceCall target-name 'add', arg-desc CP#1
-  [19] = Reserved
-  [20] = ClosureFunction 1
-  [21] = Type dart:core::int
-  [22] = String 'ii'
-  [23] = SubtypeTestCache
-  [24] = EndClosureFunctionScope
+  [0] = ObjectRef < dart:core::Function >
+  [1] = DirectCall 'dart:core::List::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ClosureFunction 0
+  [4] = InstanceField dart:core::_Closure::_context (field)
+  [5] = Reserved
+  [6] = EndClosureFunctionScope
+  [7] = Class dart:core::_Closure
+  [8] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [9] = Reserved
+  [10] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [11] = Reserved
+  [12] = EmptyTypeArguments
+  [13] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [14] = Reserved
+  [15] = InstanceField dart:core::_Closure::_function (field)
+  [16] = Reserved
+  [17] = InterfaceCall 'dart:core::List::add', ArgDesc num-args 2, num-type-args 0, names []
+  [18] = Reserved
+  [19] = ClosureFunction 1
+  [20] = Type dart:core::int
+  [21] = ObjectRef 'ii'
+  [22] = SubtypeTestCache
+  [23] = EndClosureFunctionScope
 }
-Closure #lib::C::testForLoop::<anonymous closure> () -> dart:core::int
+Closure #lib::C::testForLoop::'<anonymous closure>' () -> dart:core::int
 ClosureBytecode {
   EntryFixed           1, 2
   CheckStack           0
   Push                 FP[-5]
-  LoadFieldTOS         CP#5
+  LoadFieldTOS         CP#4
   PopLocal             r0
   Push                 r0
   LoadContextVar       1, 0
@@ -946,19 +921,19 @@
 
 }
 
-Closure #lib::C::testForLoop::<anonymous closure> (dart:core::int ii) -> dart:core::Null
+Closure #lib::C::testForLoop::'<anonymous closure>' (dart:core::int ii) -> dart:core::Null
 ClosureBytecode {
   EntryFixed           2, 3
   CheckStack           0
   Push                 FP[-6]
-  LoadFieldTOS         CP#5
+  LoadFieldTOS         CP#4
   PopLocal             r0
   Push                 FP[-5]
+  PushConstant         CP#20
+  PushNull
+  PushNull
   PushConstant         CP#21
-  PushNull
-  PushNull
-  PushConstant         CP#22
-  AssertAssignable     1, CP#23
+  AssertAssignable     1, CP#22
   Drop1
   Push                 r0
   Push                 FP[-5]
@@ -987,44 +962,43 @@
   Entry                5
   CheckStack           0
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InterfaceCall        1, CP#3
+  InterfaceCall        1, CP#2
   JumpIfFalse          L1
   AllocateContext      0, 1
   PopLocal             r0
   Push                 r0
   Push                 r2
-  InterfaceCall        1, CP#5
+  InterfaceCall        1, CP#4
   StoreContextVar      0, 0
-  Allocate             CP#11
+  Allocate             CP#10
   StoreLocal           r4
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r4
   PushNull
-  StoreFieldTOS        CP#14
+  StoreFieldTOS        CP#13
   Push                 r4
-  PushConstant         CP#16
-  StoreFieldTOS        CP#17
+  PushConstant         CP#15
+  StoreFieldTOS        CP#16
   Push                 r4
-  PushConstant         CP#7
-  StoreFieldTOS        CP#19
+  PushConstant         CP#6
+  StoreFieldTOS        CP#18
   Push                 r4
   Push                 r0
-  StoreFieldTOS        CP#8
+  StoreFieldTOS        CP#7
   PopLocal             r3
   Push                 r3
   DynamicCall          1, CP#21
   Drop1
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#22
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#22
   Drop1
   Push                 r0
   LoadContextParent
@@ -1035,36 +1009,37 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
-  [2] = Reserved
-  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
-  [4] = Reserved
-  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
-  [6] = Reserved
-  [7] = ClosureFunction 0
-  [8] = InstanceField dart:core::_Closure::_context (field)
-  [9] = Reserved
-  [10] = EndClosureFunctionScope
-  [11] = Class dart:core::_Closure
-  [12] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [13] = Reserved
-  [14] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [15] = Reserved
-  [16] = EmptyTypeArguments
-  [17] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [18] = Reserved
-  [19] = InstanceField dart:core::_Closure::_function (field)
-  [20] = Reserved
-  [21] = ICData dynamic target-name 'call', arg-desc CP#0
-  [22] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [0] = InterfaceCall 'dart:core::Iterable::get:iterator', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::Iterator::moveNext', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
+  [4] = InterfaceCall 'dart:core::Iterator::get:current', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
+  [6] = ClosureFunction 0
+  [7] = InstanceField dart:core::_Closure::_context (field)
+  [8] = Reserved
+  [9] = EndClosureFunctionScope
+  [10] = Class dart:core::_Closure
+  [11] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [12] = Reserved
+  [13] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [14] = Reserved
+  [15] = EmptyTypeArguments
+  [16] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [17] = Reserved
+  [18] = InstanceField dart:core::_Closure::_function (field)
+  [19] = Reserved
+  [20] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [21] = ICData dynamic target-name 'call', arg-desc CP#20
+  [22] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [23] = Reserved
 }
-Closure #lib::C::testForInLoop::<anonymous closure> () -> dart:core::Null
+Closure #lib::C::testForInLoop::'<anonymous closure>' () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 3
   CheckStack           0
   Push                 FP[-5]
-  LoadFieldTOS         CP#8
+  LoadFieldTOS         CP#7
   PopLocal             r0
   Push                 r0
   Push                 r0
@@ -1092,15 +1067,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::D<self::D::T>
     : super core::Object::•()
@@ -1145,7 +1119,7 @@
 ConstantPool {
   [0] = Type #lib::D::TypeParam/0
   [1] = TypeArgumentsField #lib::D
-  [2] = String 't'
+  [2] = ObjectRef 't'
   [3] = SubtypeTestCache
   [4] = ClosureFunction 0
   [5] = InstanceField dart:core::_Closure::_context (field)
@@ -1162,7 +1136,7 @@
   [16] = InstanceField dart:core::_Closure::_function (field)
   [17] = Reserved
 }
-Closure #lib::D::foo::<anonymous closure> () -> #lib::D::TypeParam/0
+Closure #lib::D::foo::'<anonymous closure>' () -> #lib::D::TypeParam/0
 ClosureBytecode {
   EntryFixed           1, 2
   CheckStack           0
@@ -1223,11 +1197,11 @@
   [13] = Reserved
   [14] = InstanceField dart:core::_Closure::_function (field)
   [15] = Reserved
-  [16] = ArgDesc num-args 1, num-type-args 0, names []
+  [16] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
   [17] = ICData dynamic target-name 'call', arg-desc CP#16
   [18] = EndClosureFunctionScope
 }
-Closure #lib::D::bar::<anonymous closure> () -> dart:core::Null
+Closure #lib::D::bar::'<anonymous closure>' () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 4
   CheckStack           0
@@ -1262,7 +1236,7 @@
 
 }
 
-Closure #lib::D::bar::Closure/0::inner () -> dart:core::Null
+Closure #lib::D::bar::Closure/0::'inner' () -> dart:core::Null
 ClosureBytecode {
   EntryFixed           1, 2
   CheckStack           0
@@ -1320,7 +1294,7 @@
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
   [3] = Type dart:core::int
-  [4] = String 'y'
+  [4] = ObjectRef 'y'
   [5] = SubtypeTestCache
   [6] = EndClosureFunctionScope
   [7] = Class dart:core::_Closure
@@ -1333,10 +1307,10 @@
   [14] = Reserved
   [15] = InstanceField dart:core::_Closure::_function (field)
   [16] = Reserved
-  [17] = ArgDesc num-args 2, num-type-args 0, names []
+  [17] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
   [18] = ICData dynamic target-name 'call', arg-desc CP#17
 }
-Closure #lib::simpleClosure::<anonymous closure> (dart:core::int y) -> dart:core::Null
+Closure #lib::simpleClosure::'<anonymous closure>' (dart:core::int y) -> dart:core::Null
 ClosureBytecode {
   EntryFixed           2, 3
   CheckStack           0
@@ -1427,16 +1401,14 @@
   Push                 r0
   InstantiateType      CP#8
   StoreIndexedTOS
-  PushConstant         CP#10
-  IndirectStaticCall   2, CP#9
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#11
+  DirectCall           2, CP#9
+  DirectCall           1, CP#11
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::Type]
+  [0] = ObjectRef < dart:core::Type >
   [1] = Type #lib::callWithArgs::TypeParam/0
   [2] = Type #lib::callWithArgs::TypeParam/1
   [3] = Type #lib::callWithArgs::TypeParam/2
@@ -1445,10 +1417,10 @@
   [6] = Type #lib::callWithArgs::TypeParam/5
   [7] = Type #lib::callWithArgs::TypeParam/6
   [8] = Type #lib::callWithArgs::TypeParam/7
-  [9] = ArgDesc num-args 2, num-type-args 0, names []
-  [10] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#9
-  [11] = ArgDesc num-args 1, num-type-args 0, names []
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#11
+  [9] = DirectCall 'dart:core::List::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [10] = Reserved
+  [11] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [12] = Reserved
 }
 ]static method callWithArgs<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic, T3 extends core::Object = dynamic, T4 extends core::Object = dynamic, T5 extends core::Object = dynamic, T6 extends core::Object = dynamic, T7 extends core::Object = dynamic, T8 extends core::Object = dynamic>() → void {
   core::print(<core::Type>[self::callWithArgs::T1, self::callWithArgs::T2, self::callWithArgs::T3, self::callWithArgs::T4, self::callWithArgs::T5, self::callWithArgs::T6, self::callWithArgs::T7, self::callWithArgs::T8]);
@@ -1463,49 +1435,43 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
-  InterfaceCall        2, CP#6
+  InterfaceCall        2, CP#5
   Drop1
-  PushConstant         CP#8
+  PushConstant         CP#7
   PushConstant         CP#2
   PushConstant         CP#1
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
-  InterfaceCall        2, CP#6
+  InterfaceCall        2, CP#5
   Drop1
+  PushConstant         CP#7
   PushConstant         CP#8
-  PushConstant         CP#10
   PushConstant         CP#1
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
-  InterfaceCall        2, CP#6
+  InterfaceCall        2, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [#lib::C3, #lib::C4]
+  [0] = ObjectRef < #lib::C3, #lib::C4 >
   [1] = Class #lib::A
-  [2] = TypeArgumentsForInstanceAllocation #lib::A [#lib::C1, #lib::C2]
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
-  [5] = ArgDesc num-args 1, num-type-args 2, names []
-  [6] = InterfaceCall target-name 'foo', arg-desc CP#5
-  [7] = Reserved
-  [8] = TypeArgs [dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 >]
-  [9] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
-  [10] = TypeArgumentsForInstanceAllocation #lib::A [dart:core::List < #lib::C1 >, dart:core::List < #lib::C2 >]
-  [11] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
+  [2] = ObjectRef < #lib::C1, #lib::C2 >
+  [3] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = InterfaceCall '#lib::A::foo', ArgDesc num-args 1, num-type-args 2, names []
+  [6] = Reserved
+  [7] = ObjectRef < dart:core::List < #lib::C3 >, dart:core::List < #lib::C4 > >
+  [8] = ObjectRef < dart:core::List < #lib::C1 >, dart:core::List < #lib::C2 > >
 }
 ]static method callA() → void {
   new self::A::•<self::C1, self::C2>().{self::A::foo}<self::C3, self::C4>();
@@ -1538,8 +1504,7 @@
   StoreLocal           r3
   PushConstant         CP#19
   StoreLocal           r6
-  PushConstant         CP#21
-  IndirectStaticCall   2, CP#20
+  DirectCall           2, CP#20
   Drop1
   Allocate             CP#14
   StoreLocal           r5
@@ -1575,10 +1540,10 @@
   [5] = EmptyTypeArguments
   [6] = InstanceField dart:core::_Closure::_function_type_arguments (field)
   [7] = Reserved
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = StaticICData target 'dart:_internal::_prependTypeArguments', arg-desc CP#8
+  [8] = DirectCall 'dart:_internal::_prependTypeArguments', ArgDesc num-args 4, num-type-args 0, names []
+  [9] = Reserved
   [10] = Type #lib::testPartialInstantiation::Closure/0::TypeParam/0
-  [11] = String 't'
+  [11] = ObjectRef 't'
   [12] = SubtypeTestCache
   [13] = EndClosureFunctionScope
   [14] = Class dart:core::_Closure
@@ -1586,11 +1551,11 @@
   [16] = Reserved
   [17] = InstanceField dart:core::_Closure::_function (field)
   [18] = Reserved
-  [19] = TypeArgs [dart:core::int]
-  [20] = ArgDesc num-args 2, num-type-args 0, names []
-  [21] = StaticICData target 'dart:_internal::_boundsCheckForPartialInstantiation', arg-desc CP#20
+  [19] = ObjectRef < dart:core::int >
+  [20] = DirectCall 'dart:_internal::_boundsCheckForPartialInstantiation', ArgDesc num-args 2, num-type-args 0, names []
+  [21] = Reserved
 }
-Closure #lib::testPartialInstantiation::foo <dart:core::Object T> (#lib::testPartialInstantiation::Closure/0::TypeParam/0 t) -> void
+Closure #lib::testPartialInstantiation::'foo' <dart:core::Object T> (#lib::testPartialInstantiation::Closure/0::TypeParam/0 t) -> void
 ClosureBytecode {
   EntryFixed           2, 3
   CheckStack           0
@@ -1612,8 +1577,7 @@
   LoadFieldTOS         CP#6
   PushInt              0
   PushInt              1
-  PushConstant         CP#9
-  IndirectStaticCall   4, CP#8
+  DirectCall           4, CP#8
   PopLocal             r0
   Push                 FP[-5]
   PushConstant         CP#10
diff --git a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
index b9e2d09..131cb14 100644
--- a/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
+++ b/pkg/vm/testcases/bytecode/deferred_lib.dart.expect
@@ -9,18 +9,16 @@
   Entry                1
   CheckStack           0
   PushNull
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   PopLocal             r0
-  PushConstant         CP#3
-  IndirectStaticCall   0, CP#2
+  DirectCall           0, CP#2
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:async::Future::value (constructor)', arg-desc CP#0
-  [2] = ArgDesc num-args 0, num-type-args 0, names []
-  [3] = StaticICData target '#pkg/vm/testcases/bytecode/hello.dart::main', arg-desc CP#2
+  [0] = DirectCall 'dart:async::Future::value (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = DirectCall '#pkg/vm/testcases/bytecode/hello.dart::main', ArgDesc num-args 0, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method callDeferred() → dynamic
   return let final dynamic #t1 = CheckLibraryIsLoaded(lib) in hel::main();
@@ -29,13 +27,12 @@
   Entry                0
   CheckStack           0
   PushNull
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:async::Future::value (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:async::Future::value (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]static method testLoadLibrary() → dynamic
   return LoadLibrary(lib);
diff --git a/pkg/vm/testcases/bytecode/field_initializers.dart.expect b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
index 695f1a9..f5f3808 100644
--- a/pkg/vm/testcases/bytecode/field_initializers.dart.expect
+++ b/pkg/vm/testcases/bytecode/field_initializers.dart.expect
@@ -25,8 +25,7 @@
   PushInt              44
   StoreFieldTOS        CP#2
   Push                 FP[-6]
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#6
+  DirectCall           1, CP#6
   Drop1
   PushNull
   ReturnTOS
@@ -39,8 +38,8 @@
   [3] = Reserved
   [4] = InstanceField #lib::A::foo4 (field)
   [5] = Reserved
-  [6] = ArgDesc num-args 1, num-type-args 0, names []
-  [7] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#6
+  [6] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [7] = Reserved
 }
 ]  constructor •(core::int foo4) → self::A
     : self::A::foo1 = null, self::A::foo4 = foo4, self::A::foo5 = 44, super core::Object::•()
@@ -64,8 +63,7 @@
   AddInt
   StoreFieldTOS        CP#2
   Push                 FP[-7]
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#6
+  DirectCall           1, CP#6
   Drop1
   PushNull
   ReturnTOS
@@ -78,8 +76,8 @@
   [3] = Reserved
   [4] = InstanceField #lib::A::foo1 (field)
   [5] = Reserved
-  [6] = ArgDesc num-args 1, num-type-args 0, names []
-  [7] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#6
+  [6] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [7] = Reserved
 }
 ]  constructor constr2(core::int x, core::int y) → self::A
     : self::A::foo4 = null, self::A::foo1 = x, self::A::foo5 = y.{core::num::+}(1), super core::Object::•()
@@ -90,15 +88,14 @@
   CheckStack           0
   Push                 FP[-5]
   PushInt              45
-  PushConstant         CP#1
-  IndirectStaticCall   2, CP#0
+  DirectCall           2, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor redirecting1() → self::A
     : this self::A::•(45)
@@ -112,15 +109,14 @@
   Push                 FP[-6]
   Push                 FP[-5]
   MulInt
-  PushConstant         CP#1
-  IndirectStaticCall   3, CP#0
+  DirectCall           3, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 3, num-type-args 0, names []
-  [1] = StaticICData target '#lib::A::constr2 (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::A::constr2 (constructor)', ArgDesc num-args 3, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor redirecting2(core::int a, core::int b, core::int c) → self::A
     : this self::A::constr2(a, b.{core::num::*}(c))
@@ -139,8 +135,7 @@
   StoreFieldTOS        CP#0
   Push                 FP[-5]
   PushInt              49
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
   Drop1
   PushNull
   ReturnTOS
@@ -148,8 +143,8 @@
 ConstantPool {
   [0] = InstanceField #lib::B::foo6 (field)
   [1] = Reserved
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#2
+  [2] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  constructor •() → self::B
     : super self::A::•(49)
@@ -168,8 +163,7 @@
   Push                 FP[-6]
   Push                 FP[-5]
   PushInt              51
-  PushConstant         CP#3
-  IndirectStaticCall   4, CP#2
+  DirectCall           4, CP#2
   Drop1
   PushNull
   ReturnTOS
@@ -177,8 +171,8 @@
 ConstantPool {
   [0] = InstanceField #lib::B::foo6 (field)
   [1] = Reserved
-  [2] = ArgDesc num-args 4, num-type-args 0, names []
-  [3] = StaticICData target '#lib::A::redirecting2 (constructor)', arg-desc CP#2
+  [2] = DirectCall '#lib::A::redirecting2 (constructor)', ArgDesc num-args 4, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  constructor c2(core::int i, core::int j) → self::B
     : self::B::foo6 = 50, super self::A::redirecting2(i, j, 51)
diff --git a/pkg/vm/testcases/bytecode/hello.dart.expect b/pkg/vm/testcases/bytecode/hello.dart.expect
index 0c5c9de..bcddfbb 100644
--- a/pkg/vm/testcases/bytecode/hello.dart.expect
+++ b/pkg/vm/testcases/bytecode/hello.dart.expect
@@ -7,16 +7,15 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'Hello, Dart Bytecode!'
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef 'Hello, Dart Bytecode!'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method main() → dynamic {
   core::print("Hello, Dart Bytecode!");
diff --git a/pkg/vm/testcases/bytecode/instance_creation.dart.expect b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
index 1407a9e..7c6bf14 100644
--- a/pkg/vm/testcases/bytecode/instance_creation.dart.expect
+++ b/pkg/vm/testcases/bytecode/instance_creation.dart.expect
@@ -11,8 +11,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   PushInt              4
@@ -40,25 +39,25 @@
   PushNull
   InstantiateType      CP#6
   StoreIndexedTOS
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#0
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
   Drop1
   PushNull
   ReturnTOS
 }
 Nullable fields: [#lib::Base::t1 (field), #lib::Base::t2 (field)]}
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
-  [2] = String 'Base: '
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = ObjectRef 'Base: '
   [3] = Type #lib::Base::TypeParam/0
   [4] = TypeArgumentsField #lib::Base
-  [5] = String ', '
+  [5] = ObjectRef ', '
   [6] = Type #lib::Base::TypeParam/1
-  [7] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [7] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [8] = Reserved
+  [9] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [10] = Reserved
 }
 ]  constructor •() → self::Base<self::Base::T1, self::Base::T2>
     : super core::Object::•() {
@@ -71,15 +70,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-6]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor •(core::String s) → self::A
     : super self::Base::•()
@@ -91,8 +89,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   PushInt              2
@@ -109,22 +106,22 @@
   PushNull
   InstantiateType      CP#3
   StoreIndexedTOS
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#0
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#5
+  DirectCall           1, CP#7
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
-  [2] = String 'B: '
+  [0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = ObjectRef 'B: '
   [3] = Type #lib::B::TypeParam/0
   [4] = TypeArgumentsField #lib::B
-  [5] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [5] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
+  [7] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [8] = Reserved
 }
 ]  constructor •() → self::B<self::B::T>
     : super self::Base::•() {
@@ -137,8 +134,7 @@
   Entry                1
   CheckStack           0
   Push                 FP[-6]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   PushInt              2
@@ -152,20 +148,20 @@
   PushInt              1
   Push                 FP[-5]
   StoreIndexedTOS
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#0
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#3
+  DirectCall           1, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
-  [2] = String 'C: '
-  [3] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#0
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = ObjectRef 'C: '
+  [3] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
 }
 ]  constructor •(core::String s) → self::C
     : super core::Object::•() {
@@ -178,15 +174,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::E<self::E::K, self::E::V>
     : super core::Object::•()
@@ -197,14 +192,13 @@
   CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   ReturnTOS
 }
 ConstantPool {
   [0] = TypeArgumentsField #lib::E
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::Map::'' (constructor)', arg-desc CP#1
+  [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]  method test_reuse1() → dynamic
     return core::Map::•<self::E::K, self::E::V>();
@@ -215,15 +209,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::E::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::E:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::F<self::F::K, self::F::V>
     : super self::E::•()
@@ -234,14 +227,13 @@
   CheckStack           0
   Push                 FP[-5]
   LoadTypeArgumentsField CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   ReturnTOS
 }
 ConstantPool {
   [0] = TypeArgumentsField #lib::F
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::Map::'' (constructor)', arg-desc CP#1
+  [1] = DirectCall 'dart:core::Map:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]  method test_reuse2() → dynamic
     return core::Map::•<core::String, core::List<self::F::V>>();
@@ -252,15 +244,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor •() → self::G<self::G::K, self::G::V>
     : super core::Object::•()
@@ -276,16 +267,15 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::H
-  [1] = TypeArgumentsForInstanceAllocation #lib::H [dart:core::String, #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target '#lib::H::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1, dart:core::String, #lib::G::test_factory (constructor)::TypeParam/0, #lib::G::test_factory (constructor)::TypeParam/1 >
+  [2] = DirectCall '#lib::H:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  static factory test_factory<K extends core::Object = dynamic, V extends core::Object = dynamic>() → self::G<self::G::test_factory::K, self::G::test_factory::V>
     return new self::H::•<core::String, self::G::test_factory::K, self::G::test_factory::V>();
@@ -296,15 +286,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::G::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::G:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::H<self::H::P1, self::H::P2, self::H::P3>
     : super self::G::•()
@@ -316,15 +305,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-6]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  constructor •(dynamic param) → self::I
     : super core::Object::•()
@@ -340,17 +328,16 @@
   StoreLocal           r2
   Push                 r2
   Push                 r1
-  PushConstant         CP#4
-  IndirectStaticCall   2, CP#3
+  DirectCall           2, CP#3
   Drop1
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'param'
-  [1] = Null
+  [0] = ObjectRef 'param'
+  [1] = ObjectRef null
   [2] = Class #lib::I
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = StaticICData target '#lib::I::'' (constructor)', arg-desc CP#3
+  [3] = DirectCall '#lib::I:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [4] = Reserved
 }
 ]  static factory test_factory2({dynamic param = null}) → self::I
     return new self::I::•(param);
@@ -380,15 +367,14 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::TestTypeArgReuse
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target '#lib::TestTypeArgReuse::'' (constructor)', arg-desc CP#1
+  [1] = DirectCall '#lib::TestTypeArgReuse:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]  static factory •<A extends core::Object = dynamic, B extends core::Object = dynamic>() → self::K<self::K::•::A, self::K::•::B>
     return new self::TestTypeArgReuse::•<self::K::•::A, self::K::•::B>();
@@ -399,15 +385,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::Base:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::TestTypeArgReuse<self::TestTypeArgReuse::P, self::TestTypeArgReuse::Q>
     : super self::Base::•()
@@ -421,16 +406,15 @@
   StoreLocal           r0
   Push                 r0
   PushConstant         CP#1
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
   Drop1
   ReturnTOS
 }
 ConstantPool {
   [0] = Class #lib::C
-  [1] = String 'hello'
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = StaticICData target '#lib::C::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef 'hello'
+  [2] = DirectCall '#lib::C:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method foo1() → dynamic
   return new self::C::•("hello");
@@ -444,8 +428,7 @@
   StoreLocal           r0
   Push                 r0
   PushConstant         CP#2
-  PushConstant         CP#4
-  IndirectStaticCall   2, CP#3
+  DirectCall           2, CP#3
   Drop1
   Drop1
   PushConstant         CP#6
@@ -453,8 +436,7 @@
   AllocateT
   StoreLocal           r0
   Push                 r0
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#7
+  DirectCall           1, CP#7
   Drop1
   Drop1
   PushNull
@@ -462,14 +444,14 @@
 }
 ConstantPool {
   [0] = Class #lib::A
-  [1] = TypeArgumentsForInstanceAllocation #lib::A []
-  [2] = String 'hi'
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#3
+  [1] = ObjectRef < dart:core::int, dart:core::String >
+  [2] = ObjectRef 'hi'
+  [3] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [4] = Reserved
   [5] = Class #lib::B
-  [6] = TypeArgumentsForInstanceAllocation #lib::B [dart:core::int]
-  [7] = ArgDesc num-args 1, num-type-args 0, names []
-  [8] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#7
+  [6] = ObjectRef < dart:core::List < dart:core::int >, dart:core::String, dart:core::int >
+  [7] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [8] = Reserved
 }
 ]static method foo2() → void {
   new self::A::•("hi");
@@ -487,8 +469,7 @@
   AllocateT
   StoreLocal           r1
   Push                 r1
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   Drop1
   PushNull
@@ -496,9 +477,9 @@
 }
 ConstantPool {
   [0] = Class #lib::B
-  [1] = TypeArgumentsForInstanceAllocation #lib::B [dart:core::List < #lib::foo3::TypeParam/0 >]
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#2
+  [1] = ObjectRef < dart:core::List < dart:core::List < #lib::foo3::TypeParam/0 > >, dart:core::String, dart:core::List < #lib::foo3::TypeParam/0 > >
+  [2] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method foo3<T extends core::Object = dynamic>() → void {
   new self::B::•<core::List<self::foo3::T>>();
@@ -508,16 +489,15 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgumentsForInstanceAllocation #lib::G [dart:core::int, dart:core::List < dart:core::String >]
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target '#lib::G::test_factory (constructor)', arg-desc CP#1
+  [0] = ObjectRef < dart:core::int, dart:core::List < dart:core::String > >
+  [1] = DirectCall '#lib::G::test_factory (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method foo4() → void {
   self::G::test_factory<core::int, core::List<core::String>>();
@@ -527,22 +507,20 @@
   Entry                0
   CheckStack           0
   PushNull
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   PushInt              42
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::I::test_factory2 (constructor)', arg-desc CP#0
-  [2] = ArgDesc num-args 2, num-type-args 0, names [param]
-  [3] = StaticICData target '#lib::I::test_factory2 (constructor)', arg-desc CP#2
+  [0] = DirectCall '#lib::I::test_factory2 (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = DirectCall '#lib::I::test_factory2 (constructor)', ArgDesc num-args 2, num-type-args 0, names ['param']
+  [3] = Reserved
 }
 ]static method foo5() → void {
   self::I::test_factory2();
@@ -554,14 +532,13 @@
   CheckStack           0
   PushConstant         CP#0
   PushInt              0
-  PushConstant         CP#2
-  IndirectStaticCall   2, CP#1
+  DirectCall           2, CP#1
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgumentsForInstanceAllocation dart:core::_GrowableList [dart:core::String]
-  [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::_GrowableList::'' (constructor)', arg-desc CP#1
+  [0] = ObjectRef < dart:core::String >
+  [1] = DirectCall 'dart:core::_GrowableList:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method foo6() → dynamic
   return core::_GrowableList::•<core::String>(0);
@@ -571,14 +548,13 @@
   CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
-  PushConstant         CP#2
-  IndirectStaticCall   2, CP#1
+  DirectCall           2, CP#1
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgumentsForInstanceAllocation dart:core::_List [dart:core::int]
-  [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::_List::'' (constructor)', arg-desc CP#1
+  [0] = ObjectRef < dart:core::int >
+  [1] = DirectCall 'dart:core::_List:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method foo7(core::int n) → dynamic
   return core::_List::•<core::int>(n);
@@ -586,26 +562,24 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#1
-  IndirectStaticCall   0, CP#0
+  DirectCall           0, CP#0
   Drop1
-  PushConstant         CP#2
-  IndirectStaticCall   0, CP#0
+  DirectCall           0, CP#2
   Drop1
-  PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#4
+  DirectCall           1, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 0, num-type-args 0, names []
-  [1] = StaticICData target '#lib::foo1', arg-desc CP#0
-  [2] = StaticICData target '#lib::foo2', arg-desc CP#0
-  [3] = TypeArgs [dart:core::String]
-  [4] = ArgDesc num-args 0, num-type-args 1, names []
-  [5] = StaticICData target '#lib::foo3', arg-desc CP#4
+  [0] = DirectCall '#lib::foo1', ArgDesc num-args 0, num-type-args 0, names []
+  [1] = Reserved
+  [2] = DirectCall '#lib::foo2', ArgDesc num-args 0, num-type-args 0, names []
+  [3] = Reserved
+  [4] = ObjectRef < dart:core::String >
+  [5] = DirectCall '#lib::foo3', ArgDesc num-args 0, num-type-args 1, names []
+  [6] = Reserved
 }
 ]static method main() → dynamic {
   self::foo1();
diff --git a/pkg/vm/testcases/bytecode/literals.dart.expect b/pkg/vm/testcases/bytecode/literals.dart.expect
index 4649642..bef20c6 100644
--- a/pkg/vm/testcases/bytecode/literals.dart.expect
+++ b/pkg/vm/testcases/bytecode/literals.dart.expect
@@ -10,80 +10,55 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#13
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 0
-  [2] = String 'A.elem1'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
-  [4] = Int 1
-  [5] = String 'A.elem2'
-  [6] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#4, #lib::A::_name (field): CP#5}
-  [7] = Int 2
-  [8] = String 'A.elem3'
-  [9] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#7, #lib::A::_name (field): CP#8}
-  [10] = Int 3
-  [11] = String 'A.elem4'
-  [12] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#10, #lib::A::_name (field): CP#11}
-  [13] = List type-arg #lib::A, entries CP# [3, 6, 9, 12]
+  [0] = ObjectRef const <#lib::A> [const #lib::A {#lib::A::index (field): const 0, #lib::A::_name (field): 'A.elem1'}, const #lib::A {#lib::A::index (field): const 1, #lib::A::_name (field): 'A.elem2'}, const #lib::A {#lib::A::index (field): const 2, #lib::A::_name (field): 'A.elem3'}, const #lib::A {#lib::A::index (field): const 3, #lib::A::_name (field): 'A.elem4'}]
 }
 ]  static const field core::List<self::A> values = const <self::A>[self::A::elem1, self::A::elem2, self::A::elem3, self::A::elem4];
 [@vm.bytecode=
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 0
-  [2] = String 'A.elem1'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 0, #lib::A::_name (field): 'A.elem1'}
 }
 ]  static const field self::A elem1 = const self::A::•(0, "A.elem1");
 [@vm.bytecode=
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 1
-  [2] = String 'A.elem2'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 1, #lib::A::_name (field): 'A.elem2'}
 }
 ]  static const field self::A elem2 = const self::A::•(1, "A.elem2");
 [@vm.bytecode=
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 2
-  [2] = String 'A.elem3'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 2, #lib::A::_name (field): 'A.elem3'}
 }
 ]  static const field self::A elem3 = const self::A::•(2, "A.elem3");
 [@vm.bytecode=
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 3
-  [2] = String 'A.elem4'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 3, #lib::A::_name (field): 'A.elem4'}
 }
 ]  static const field self::A elem4 = const self::A::•(3, "A.elem4");
 [@vm.bytecode=
@@ -97,8 +72,7 @@
   Push                 FP[-5]
   StoreFieldTOS        CP#2
   Push                 FP[-7]
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#4
   Drop1
   PushNull
   ReturnTOS
@@ -108,8 +82,8 @@
   [1] = Reserved
   [2] = InstanceField #lib::A::_name (field)
   [3] = Reserved
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#4
+  [4] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
 }
 ]  const constructor •(core::int index, core::String _name) → self::A
     : self::A::index = index, self::A::_name = _name, super core::Object::•()
@@ -119,13 +93,12 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::A::get:_name', arg-desc CP#0
+  [0] = DirectCall '#lib::A::get:_name', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  method toString() → core::String
     return this.{=self::A::_name};
@@ -140,8 +113,7 @@
   Push                 FP[-5]
   StoreFieldTOS        CP#0
   Push                 FP[-6]
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#2
+  DirectCall           1, CP#2
   Drop1
   PushNull
   ReturnTOS
@@ -149,8 +121,8 @@
 ConstantPool {
   [0] = InstanceField #lib::B::i (field)
   [1] = Reserved
-  [2] = ArgDesc num-args 1, num-type-args 0, names []
-  [3] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#2
+  [2] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  const constructor •(core::int i) → self::B
     : self::B::i = i, super core::Object::•()
@@ -171,8 +143,7 @@
   Push                 FP[-5]
   PushInt              5
   MulInt
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
   Drop1
   PushNull
   ReturnTOS
@@ -180,8 +151,8 @@
 ConstantPool {
   [0] = InstanceField #lib::C::j (field)
   [1] = Reserved
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#2
+  [2] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]  const constructor •(core::int a, core::int b, core::int c) → self::C
     : self::C::j = a.{core::num::+}(b), super self::B::•(c.{core::num::*}(5))
@@ -203,20 +174,19 @@
   Push                 r2
   StoreFieldTOS        CP#3
   Push                 r0
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
+  [0] = ObjectRef null
   [1] = InstanceField #lib::D::x (field)
   [2] = Reserved
   [3] = InstanceField #lib::D::y (field)
   [4] = Reserved
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#5
+  [5] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
 }
 ]  const constructor •(dynamic x, [dynamic y = null]) → self::D
     : self::D::x = x, self::D::y = y, super core::Object::•()
@@ -228,15 +198,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  const constructor •() → self::E<self::E::T>
     : super core::Object::•()
@@ -248,15 +217,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::E::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::E:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  const constructor •() → self::F<self::F::P, self::F::Q>
     : super self::E::•()
@@ -266,14 +234,11 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 2
-  [2] = String 'A.elem3'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 2, #lib::A::_name (field): 'A.elem3'}
 }
 ]static const field self::A c1 = self::A::elem3;
 static const field core::String c2 = "hello!";
@@ -291,28 +256,22 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 3
-  [2] = Int 15
-  [3] = Instance #lib::C type-args CP#0 {#lib::C::j (field): CP#1, #lib::B::i (field): CP#2}
+  [0] = ObjectRef const #lib::C {#lib::C::j (field): const 3, #lib::B::i (field): const 15}
 }
 ]static const field self::C c4 = const self::C::•(1, 2, 3);
 [@vm.bytecode=
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 4
-  [2] = Instance #lib::B type-args CP#0 {#lib::B::i (field): CP#1}
-  [3] = Instance #lib::D type-args CP#0 {#lib::D::x (field): CP#2, #lib::D::y (field): CP#0}
+  [0] = ObjectRef const #lib::D {#lib::D::x (field): const #lib::B {#lib::B::i (field): const 4}, #lib::D::y (field): null}
 }
 ]static const field self::D c5 = const self::D::•(const self::B::•(4));
 static field core::double fieldWithDoubleLiteralInitializer = 1.0;
@@ -320,47 +279,31 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#0
+  DirectCall           1, CP#1
   Drop1
-  PushConstant         CP#6
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#3
+  DirectCall           1, CP#1
   Drop1
   PushInt              6
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#1
   Drop1
-  PushConstant         CP#11
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#4
+  DirectCall           1, CP#1
   Drop1
-  PushConstant         CP#15
-  PushConstant         CP#16
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#5
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = Null
-  [1] = Int 2
-  [2] = String 'A.elem3'
-  [3] = Instance #lib::A type-args CP#0 {#lib::A::index (field): CP#1, #lib::A::_name (field): CP#2}
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [6] = String 'hello!'
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [9] = Int 3
-  [10] = Int 15
-  [11] = Instance #lib::C type-args CP#0 {#lib::C::j (field): CP#9, #lib::B::i (field): CP#10}
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [13] = Int 4
-  [14] = Instance #lib::B type-args CP#0 {#lib::B::i (field): CP#13}
-  [15] = Instance #lib::D type-args CP#0 {#lib::D::x (field): CP#14, #lib::D::y (field): CP#0}
-  [16] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [0] = ObjectRef const #lib::A {#lib::A::index (field): const 2, #lib::A::_name (field): 'A.elem3'}
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ObjectRef 'hello!'
+  [4] = ObjectRef const #lib::C {#lib::C::j (field): const 3, #lib::B::i (field): const 15}
+  [5] = ObjectRef const #lib::D {#lib::D::x (field): const #lib::B {#lib::B::i (field): const 4}, #lib::D::y (field): null}
 }
 ]static method test_constants1() → void {
   core::print(self::c1);
@@ -374,66 +317,34 @@
   Entry                0
   CheckStack           0
   PushInt              42
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushConstant         CP#2
+  DirectCall           1, CP#0
+  Drop1
   PushConstant         CP#3
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
-  PushConstant         CP#7
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#0
+  PushConstant         CP#4
+  DirectCall           1, CP#0
   Drop1
-  PushConstant         CP#11
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#0
+  PushConstant         CP#5
+  DirectCall           1, CP#0
   Drop1
-  PushConstant         CP#20
-  PushConstant         CP#21
-  IndirectStaticCall   1, CP#0
-  Drop1
-  PushConstant         CP#31
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#0
+  PushConstant         CP#6
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::print', arg-desc CP#0
-  [2] = String 'foo'
-  [3] = StaticICData target 'dart:core::print', arg-desc CP#0
-  [4] = Null
-  [5] = Int 1
-  [6] = String 'A.elem2'
-  [7] = Instance #lib::A type-args CP#4 {#lib::A::index (field): CP#5, #lib::A::_name (field): CP#6}
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#0
-  [9] = Int 42
-  [10] = Type dart:core::int
-  [11] = List type-arg dart:core::Object, entries CP# [9, 2, 10]
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#0
-  [13] = TypeArgumentsForInstanceAllocation dart:core::_ImmutableMap [dart:core::String, #lib::A]
-  [14] = String 'E2'
-  [15] = String 'E4'
-  [16] = Int 3
-  [17] = String 'A.elem4'
-  [18] = Instance #lib::A type-args CP#4 {#lib::A::index (field): CP#16, #lib::A::_name (field): CP#17}
-  [19] = List type-arg dynamic, entries CP# [14, 7, 15, 18]
-  [20] = Instance dart:core::_ImmutableMap type-args CP#13 {dart:core::_ImmutableMap::_kvPairs (field): CP#19}
-  [21] = StaticICData target 'dart:core::print', arg-desc CP#0
-  [22] = Int 9
-  [23] = Int 30
-  [24] = Instance #lib::C type-args CP#4 {#lib::C::j (field): CP#22, #lib::B::i (field): CP#23}
-  [25] = TypeArgumentsForInstanceAllocation dart:core::_ImmutableMap [dart:core::String, dart:core::Object]
-  [26] = String 'bar'
-  [27] = Int 6
-  [28] = Instance #lib::B type-args CP#4 {#lib::B::i (field): CP#27}
-  [29] = List type-arg dynamic, entries CP# [2, 9, 26, 28]
-  [30] = Instance dart:core::_ImmutableMap type-args CP#25 {dart:core::_ImmutableMap::_kvPairs (field): CP#29}
-  [31] = Instance #lib::D type-args CP#4 {#lib::D::x (field): CP#24, #lib::D::y (field): CP#30}
-  [32] = StaticICData target 'dart:core::print', arg-desc CP#0
+  [0] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = ObjectRef 'foo'
+  [3] = ObjectRef const #lib::A {#lib::A::index (field): const 1, #lib::A::_name (field): 'A.elem2'}
+  [4] = ObjectRef const <dart:core::Object> [const 42, 'foo', dart:core::int]
+  [5] = ObjectRef const dart:core::_ImmutableMap < dart:core::String, #lib::A > {dart:core::_ImmutableMap::_kvPairs (field): const <dynamic> ['E2', const #lib::A {#lib::A::index (field): const 1, #lib::A::_name (field): 'A.elem2'}, 'E4', const #lib::A {#lib::A::index (field): const 3, #lib::A::_name (field): 'A.elem4'}]}
+  [6] = ObjectRef const #lib::D {#lib::D::x (field): const #lib::C {#lib::C::j (field): const 9, #lib::B::i (field): const 30}, #lib::D::y (field): const dart:core::_ImmutableMap < dart:core::String, dart:core::Object > {dart:core::_ImmutableMap::_kvPairs (field): const <dynamic> ['foo', const 42, 'bar', const #lib::B {#lib::B::i (field): const 6}]}}
 }
 ]static method test_constants2() → void {
   core::print(42);
@@ -465,10 +376,8 @@
   PushInt              2
   PushInt              3
   StoreIndexedTOS
-  PushConstant         CP#2
-  IndirectStaticCall   2, CP#1
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#3
+  DirectCall           2, CP#1
+  DirectCall           1, CP#3
   Drop1
   PushConstant         CP#5
   StoreLocal           r0
@@ -489,27 +398,23 @@
   PushInt              2
   PushConstant         CP#9
   StoreIndexedTOS
-  PushConstant         CP#10
-  IndirectStaticCall   2, CP#1
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#3
+  DirectCall           2, CP#1
+  DirectCall           1, CP#3
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::int]
-  [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [5] = TypeArgs [dart:core::String]
-  [6] = String 'a'
-  [7] = InterfaceCall target-name 'toString', arg-desc CP#3
+  [0] = ObjectRef < dart:core::int >
+  [1] = DirectCall 'dart:core::List::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Reserved
+  [3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = ObjectRef < dart:core::String >
+  [6] = ObjectRef 'a'
+  [7] = InterfaceCall 'dart:core::int::toString', ArgDesc num-args 1, num-type-args 0, names []
   [8] = Reserved
-  [9] = String 'b'
-  [10] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#1
-  [11] = StaticICData target 'dart:core::print', arg-desc CP#3
+  [9] = ObjectRef 'b'
 }
 ]static method test_list_literal(core::int a) → void {
   core::print(<core::int>[1, a, 3]);
@@ -541,10 +446,8 @@
   PushInt              3
   PushInt              2
   StoreIndexedTOS
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  DirectCall           2, CP#2
+  DirectCall           1, CP#4
   Drop1
   PushConstant         CP#6
   PushConstant         CP#1
@@ -568,23 +471,19 @@
   PushInt              3
   PushInt              3
   StoreIndexedTOS
-  PushConstant         CP#10
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
+  DirectCall           1, CP#4
+  Drop1
+  PushNull
+  Push                 r0
+  InstantiateTypeArgumentsTOS 0, CP#10
   PushConstant         CP#11
-  IndirectStaticCall   1, CP#4
+  DirectCall           2, CP#2
+  DirectCall           1, CP#4
   Drop1
   PushNull
   Push                 r0
   InstantiateTypeArgumentsTOS 0, CP#12
-  PushConstant         CP#13
-  PushConstant         CP#14
-  IndirectStaticCall   2, CP#2
-  PushConstant         CP#15
-  IndirectStaticCall   1, CP#4
-  Drop1
-  PushNull
-  Push                 r0
-  InstantiateTypeArgumentsTOS 0, CP#16
   PushConstant         CP#1
   PushInt              2
   CreateArrayTOS
@@ -597,34 +496,26 @@
   PushInt              1
   PushInt              4
   StoreIndexedTOS
-  PushConstant         CP#17
-  IndirectStaticCall   2, CP#2
-  PushConstant         CP#18
-  IndirectStaticCall   1, CP#4
+  DirectCall           2, CP#2
+  DirectCall           1, CP#4
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::int, dart:core::int]
-  [1] = TypeArgs [dynamic]
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [6] = TypeArgs [dart:core::String, dart:core::int]
-  [7] = String 'foo'
-  [8] = InterfaceCall target-name 'toString', arg-desc CP#4
+  [0] = ObjectRef < dart:core::int, dart:core::int >
+  [1] = ObjectRef < dynamic >
+  [2] = DirectCall 'dart:core::Map::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
+  [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
+  [6] = ObjectRef < dart:core::String, dart:core::int >
+  [7] = ObjectRef 'foo'
+  [8] = InterfaceCall 'dart:core::int::toString', ArgDesc num-args 1, num-type-args 0, names []
   [9] = Reserved
-  [10] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [11] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [12] = TypeArgs [dart:core::String, #lib::test_map_literal::TypeParam/0]
-  [13] = List type-arg dynamic, entries CP# []
-  [14] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [15] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [16] = TypeArgs [#lib::test_map_literal::TypeParam/0, dart:core::int]
-  [17] = StaticICData target 'dart:core::Map::_fromLiteral (constructor)', arg-desc CP#2
-  [18] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [10] = ObjectRef < dart:core::String, #lib::test_map_literal::TypeParam/0 >
+  [11] = ObjectRef const <dynamic> []
+  [12] = ObjectRef < #lib::test_map_literal::TypeParam/0, dart:core::int >
 }
 ]static method test_map_literal<T extends core::Object = dynamic>(core::int a, core::int b, self::test_map_literal::T c) → void {
   core::print(<core::int, core::int>{1: a, b: 2});
@@ -637,22 +528,19 @@
   Entry                0
   CheckStack           0
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushConstant         CP#3
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = Symbol test_symbol
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [3] = Symbol _private_symbol
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef const 'test_symbol'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ObjectRef const '_private_symbol'
 }
 ]static method test_symbol() → void {
   core::print(#test_symbol);
@@ -664,24 +552,21 @@
   CheckStack           0
   CheckFunctionTypeArgs 1, r0
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   Push                 r0
   InstantiateType      CP#3
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
   [0] = Type dart:core::String
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
   [3] = Type #lib::test_type_literal::TypeParam/0
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#1
 }
 ]static method test_type_literal<T extends core::Object = dynamic>() → void {
   core::print(core::String);
@@ -691,12 +576,11 @@
 Bytecode {
   Entry                0
   CheckStack           0
-  PushConstant         CP#1
+  PushConstant         CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgumentsForInstanceAllocation #lib::F [dart:core::int, dart:core::String]
-  [1] = Instance #lib::F type-args CP#0 {}
+  [0] = ObjectRef const #lib::F < dart:core::Map < dart:core::int, dart:core::String >, dart:core::int, dart:core::String > {}
 }
 ]static method testGenericConstInstance() → dynamic
   return const self::F::•<core::int, core::String>();
diff --git a/pkg/vm/testcases/bytecode/loops.dart.expect b/pkg/vm/testcases/bytecode/loops.dart.expect
index 4fbdb3b..0c91ab3 100644
--- a/pkg/vm/testcases/bytecode/loops.dart.expect
+++ b/pkg/vm/testcases/bytecode/loops.dart.expect
@@ -14,13 +14,13 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#4
+  InterfaceCall        2, CP#2
   AddInt
   PopLocal             r0
   Push                 r1
@@ -34,12 +34,10 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
-  [2] = Reserved
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = InterfaceCall target-name '[]', arg-desc CP#3
-  [5] = Reserved
+  [0] = InterfaceCall 'dart:core::List::get:length', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method test_for(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -64,7 +62,7 @@
   JumpIfFalse          L1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   CompareIntGe
   JumpIfFalse          L2
   Jump                 L1
@@ -72,7 +70,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#4
+  InterfaceCall        2, CP#2
   AddInt
   PopLocal             r0
   Push                 r1
@@ -86,12 +84,10 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
-  [2] = Reserved
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = InterfaceCall target-name '[]', arg-desc CP#3
-  [5] = Reserved
+  [0] = InterfaceCall 'dart:core::List::get:length', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method test_for_break(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -117,7 +113,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   CompareIntLt
   JumpIfFalse          L1
   Push                 r1
@@ -129,7 +125,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#4
+  InterfaceCall        2, CP#2
   AddInt
   PopLocal             r0
 L3:
@@ -144,12 +140,10 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
-  [2] = Reserved
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = InterfaceCall target-name '[]', arg-desc CP#3
-  [5] = Reserved
+  [0] = InterfaceCall 'dart:core::List::get:length', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method test_for_continue(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -175,7 +169,7 @@
   CheckStack           1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   CompareIntLt
   JumpIfFalse          L1
   Push                 r0
@@ -188,7 +182,7 @@
   StoreLocal           r1
   PopLocal             r3
   Push                 r2
-  InterfaceCall        2, CP#4
+  InterfaceCall        2, CP#2
   AddInt
   PopLocal             r0
   Jump                 L2
@@ -197,12 +191,10 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:length', arg-desc CP#0
-  [2] = Reserved
-  [3] = ArgDesc num-args 2, num-type-args 0, names []
-  [4] = InterfaceCall target-name '[]', arg-desc CP#3
-  [5] = Reserved
+  [0] = InterfaceCall 'dart:core::List::get:length', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method test_while(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -225,7 +217,7 @@
   Push                 r0
   Push                 FP[-5]
   Push                 r1
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   AddInt
   PopLocal             r0
   Push                 r1
@@ -234,19 +226,17 @@
   PopLocal             r1
   Push                 r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#4
+  InterfaceCall        1, CP#2
   CompareIntLt
   JumpIfTrue           L1
   Push                 r0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = InterfaceCall target-name '[]', arg-desc CP#0
-  [2] = Reserved
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = InterfaceCall get target-name 'get:length', arg-desc CP#3
-  [5] = Reserved
+  [0] = InterfaceCall 'dart:core::List::[]', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::List::get:length', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
 }
 ]static method test_do_while(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -265,15 +255,15 @@
   PushInt              0
   PopLocal             r0
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   PopLocal             r1
 L2:
   CheckStack           1
   Push                 r1
-  InterfaceCall        1, CP#3
+  InterfaceCall        1, CP#2
   JumpIfFalse          L1
   Push                 r1
-  InterfaceCall        1, CP#5
+  InterfaceCall        1, CP#4
   PopLocal             r2
   Push                 r0
   Push                 r2
@@ -285,13 +275,12 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
-  [2] = Reserved
-  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
-  [4] = Reserved
-  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
-  [6] = Reserved
+  [0] = InterfaceCall 'dart:core::Iterable::get:iterator', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::Iterator::moveNext', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
+  [4] = InterfaceCall 'dart:core::Iterator::get:current', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
 }
 ]static method test_for_in(core::List<core::int> list) → core::int {
   core::int sum = 0;
@@ -309,15 +298,15 @@
   PushInt              42
   PopLocal             r1
   Push                 FP[-5]
-  InterfaceCall        1, CP#1
+  InterfaceCall        1, CP#0
   PopLocal             r2
 L2:
   CheckStack           1
   Push                 r2
-  InterfaceCall        1, CP#3
+  InterfaceCall        1, CP#2
   JumpIfFalse          L1
   Push                 r2
-  InterfaceCall        1, CP#5
+  InterfaceCall        1, CP#4
   PopLocal             r3
   Push                 r3
   PopLocal             r1
@@ -331,13 +320,12 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = InterfaceCall get target-name 'get:iterator', arg-desc CP#0
-  [2] = Reserved
-  [3] = InterfaceCall target-name 'moveNext', arg-desc CP#0
-  [4] = Reserved
-  [5] = InterfaceCall get target-name 'get:current', arg-desc CP#0
-  [6] = Reserved
+  [0] = InterfaceCall 'dart:core::Iterable::get:iterator', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
+  [2] = InterfaceCall 'dart:core::Iterator::moveNext', ArgDesc num-args 1, num-type-args 0, names []
+  [3] = Reserved
+  [4] = InterfaceCall 'dart:core::Iterator::get:current', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
 }
 ]static method test_for_in_with_outer_var(core::List<core::int> list) → core::int {
   core::int sum = 0;
diff --git a/pkg/vm/testcases/bytecode/optional_params.dart.expect b/pkg/vm/testcases/bytecode/optional_params.dart.expect
index d715039..0920f3c 100644
--- a/pkg/vm/testcases/bytecode/optional_params.dart.expect
+++ b/pkg/vm/testcases/bytecode/optional_params.dart.expect
@@ -21,10 +21,8 @@
   PushInt              1
   Push                 r0
   StoreIndexedTOS
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
+  DirectCall           1, CP#5
   Drop1
   PushNull
   PushInt              2
@@ -32,16 +30,14 @@
   StoreLocal           r3
   Push                 r3
   PushInt              0
-  PushConstant         CP#6
+  PushConstant         CP#7
   StoreIndexedTOS
   Push                 r3
   PushInt              1
   Push                 r1
   StoreIndexedTOS
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#3
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
+  DirectCall           1, CP#5
   Drop1
   PushNull
   PushInt              2
@@ -49,33 +45,28 @@
   StoreLocal           r3
   Push                 r3
   PushInt              0
-  PushConstant         CP#9
+  PushConstant         CP#8
   StoreIndexedTOS
   Push                 r3
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#3
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
+  DirectCall           1, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'default_a'
-  [1] = String 'default_b'
-  [2] = String 'x = '
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#3
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [6] = String 'a = '
-  [7] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#3
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [9] = String 'b = '
-  [10] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#3
-  [11] = StaticICData target 'dart:core::print', arg-desc CP#3
+  [0] = ObjectRef 'default_a'
+  [1] = ObjectRef 'default_b'
+  [2] = ObjectRef 'x = '
+  [3] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
+  [7] = ObjectRef 'a = '
+  [8] = ObjectRef 'b = '
 }
 ]static method foo1(dynamic x, [dynamic a = "default_a", dynamic b = "default_b"]) → void {
   core::print("x = ${x}");
@@ -88,9 +79,9 @@
   LoadConstant         r2, CP#0
   LoadConstant         r2, CP#1
   LoadConstant         r3, CP#2
-  LoadConstant         r3, CP#4
+  LoadConstant         r3, CP#3
+  LoadConstant         r4, CP#4
   LoadConstant         r4, CP#5
-  LoadConstant         r4, CP#6
   Frame                1
   CheckStack           0
   PushNull
@@ -99,16 +90,14 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#7
+  PushConstant         CP#6
   StoreIndexedTOS
   Push                 r5
   PushInt              1
   Push                 r0
   StoreIndexedTOS
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#8
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
   Drop1
   PushNull
   PushInt              2
@@ -122,10 +111,38 @@
   PushInt              1
   Push                 r1
   StoreIndexedTOS
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
+  Drop1
+  PushNull
+  PushInt              2
+  CreateArrayTOS
+  StoreLocal           r5
+  Push                 r5
+  PushInt              0
   PushConstant         CP#12
-  IndirectStaticCall   1, CP#8
+  StoreIndexedTOS
+  Push                 r5
+  PushInt              1
+  Push                 r2
+  StoreIndexedTOS
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
+  Drop1
+  PushNull
+  PushInt              2
+  CreateArrayTOS
+  StoreLocal           r5
+  Push                 r5
+  PushInt              0
   PushConstant         CP#13
-  IndirectStaticCall   1, CP#8
+  StoreIndexedTOS
+  Push                 r5
+  PushInt              1
+  Push                 r3
+  StoreIndexedTOS
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
   Drop1
   PushNull
   PushInt              2
@@ -137,74 +154,30 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              1
-  Push                 r2
-  StoreIndexedTOS
-  PushConstant         CP#15
-  IndirectStaticCall   1, CP#8
-  PushConstant         CP#16
-  IndirectStaticCall   1, CP#8
-  Drop1
-  PushNull
-  PushInt              2
-  CreateArrayTOS
-  StoreLocal           r5
-  Push                 r5
-  PushInt              0
-  PushConstant         CP#17
-  StoreIndexedTOS
-  Push                 r5
-  PushInt              1
-  Push                 r3
-  StoreIndexedTOS
-  PushConstant         CP#18
-  IndirectStaticCall   1, CP#8
-  PushConstant         CP#19
-  IndirectStaticCall   1, CP#8
-  Drop1
-  PushNull
-  PushInt              2
-  CreateArrayTOS
-  StoreLocal           r5
-  Push                 r5
-  PushInt              0
-  PushConstant         CP#20
-  StoreIndexedTOS
-  Push                 r5
-  PushInt              1
   Push                 r4
   StoreIndexedTOS
-  PushConstant         CP#21
-  IndirectStaticCall   1, CP#8
-  PushConstant         CP#22
-  IndirectStaticCall   1, CP#8
+  DirectCall           1, CP#7
+  DirectCall           1, CP#9
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'a'
-  [1] = Int 42
-  [2] = String 'b'
-  [3] = String 'default_b'
-  [4] = List type-arg dart:core::String, entries CP# [3]
-  [5] = String 'c'
-  [6] = String 'default_c'
-  [7] = String 'y = '
-  [8] = ArgDesc num-args 1, num-type-args 0, names []
-  [9] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#8
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#8
-  [11] = String 'z = '
-  [12] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#8
-  [13] = StaticICData target 'dart:core::print', arg-desc CP#8
-  [14] = String 'a = '
-  [15] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#8
-  [16] = StaticICData target 'dart:core::print', arg-desc CP#8
-  [17] = String 'b = '
-  [18] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#8
-  [19] = StaticICData target 'dart:core::print', arg-desc CP#8
-  [20] = String 'c = '
-  [21] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#8
-  [22] = StaticICData target 'dart:core::print', arg-desc CP#8
+  [0] = ObjectRef 'a'
+  [1] = ObjectRef const 42
+  [2] = ObjectRef 'b'
+  [3] = ObjectRef const <dart:core::String> ['default_b']
+  [4] = ObjectRef 'c'
+  [5] = ObjectRef 'default_c'
+  [6] = ObjectRef 'y = '
+  [7] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [8] = Reserved
+  [9] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [10] = Reserved
+  [11] = ObjectRef 'z = '
+  [12] = ObjectRef 'a = '
+  [13] = ObjectRef 'b = '
+  [14] = ObjectRef 'c = '
 }
 ]static method foo2(dynamic y, dynamic z, {dynamic c = "default_c", dynamic a = 42, dynamic b = const <core::String>["default_b"]}) → void {
   core::print("y = ${y}");
@@ -226,30 +199,25 @@
   PushNull
   Push                 r4
   InstantiateType      CP#4
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#5
   Drop1
   Push                 r1
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#5
   Drop1
   Push                 r3
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#5
+  DirectCall           1, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'a'
-  [1] = Bool false
-  [2] = String 'b'
-  [3] = Null
+  [0] = ObjectRef 'a'
+  [1] = ObjectRef const false
+  [2] = ObjectRef 'b'
+  [3] = ObjectRef null
   [4] = Type #lib::foo3::TypeParam/0
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#5
+  [5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
 }
 ]static method foo3<P extends core::Object = dynamic, Q extends core::Object = dynamic>(dynamic z, dynamic y, {core::bool a = false, core::Map<self::foo3::P, self::foo3::Q> b = null}) → void {
   core::print(self::foo3::P);
@@ -262,27 +230,25 @@
   CheckStack           0
   PushConstant         CP#0
   PushConstant         CP#1
-  PushConstant         CP#3
-  IndirectStaticCall   2, CP#2
+  DirectCall           2, CP#2
   Drop1
   PushConstant         CP#4
   PushConstant         CP#5
   PushConstant         CP#1
-  PushConstant         CP#7
-  IndirectStaticCall   3, CP#6
+  DirectCall           3, CP#6
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = String 'fixed_x'
-  [1] = String 'concrete_a'
-  [2] = ArgDesc num-args 2, num-type-args 0, names []
-  [3] = StaticICData target '#lib::foo1', arg-desc CP#2
-  [4] = String 'fixed_y'
-  [5] = String 'fixed_z'
-  [6] = ArgDesc num-args 3, num-type-args 0, names [a]
-  [7] = StaticICData target '#lib::foo2', arg-desc CP#6
+  [0] = ObjectRef 'fixed_x'
+  [1] = ObjectRef 'concrete_a'
+  [2] = DirectCall '#lib::foo1', ArgDesc num-args 2, num-type-args 0, names []
+  [3] = Reserved
+  [4] = ObjectRef 'fixed_y'
+  [5] = ObjectRef 'fixed_z'
+  [6] = DirectCall '#lib::foo2', ArgDesc num-args 3, num-type-args 0, names ['a']
+  [7] = Reserved
 }
 ]static method main() → dynamic {
   self::foo1("fixed_x", "concrete_a");
diff --git a/pkg/vm/testcases/bytecode/super_calls.dart.expect b/pkg/vm/testcases/bytecode/super_calls.dart.expect
index 346cd8a..4fa0a47 100644
--- a/pkg/vm/testcases/bytecode/super_calls.dart.expect
+++ b/pkg/vm/testcases/bytecode/super_calls.dart.expect
@@ -8,15 +8,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::Base1
     : super core::Object::•()
@@ -60,15 +59,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base1::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::Base1:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::A
     : super self::Base1::•()
@@ -81,15 +79,14 @@
   Push                 FP[-6]
   PushConstant         CP#1
   PushInt              2
-  PushConstant         CP#3
-  IndirectStaticCall   4, CP#2
+  DirectCall           4, CP#2
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::String]
-  [1] = String 'a1'
-  [2] = ArgDesc num-args 3, num-type-args 1, names []
-  [3] = StaticICData target '#lib::Base1::foo', arg-desc CP#2
+  [0] = ObjectRef < dart:core::String >
+  [1] = ObjectRef 'a1'
+  [2] = DirectCall '#lib::Base1::foo', ArgDesc num-args 3, num-type-args 1, names []
+  [3] = Reserved
 }
 ]  method testSuperCall(core::int x) → dynamic
     return super.{self::Base1::foo}<core::String>("a1", 2);
@@ -98,13 +95,12 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base1::get:foo', arg-desc CP#0
+  [0] = DirectCall '#lib::Base1::get:foo', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  method testSuperTearOff() → dynamic
     return super.{self::Base1::foo};
@@ -113,13 +109,12 @@
   Entry                1
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base1::get:bar', arg-desc CP#0
+  [0] = DirectCall '#lib::Base1::get:bar', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  method testSuperGet() → dynamic
     return super.{self::Base1::bar};
@@ -129,18 +124,17 @@
   CheckStack           0
   PushConstant         CP#0
   Push                 FP[-5]
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   PushConstant         CP#3
   DynamicCall          3, CP#5
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::int]
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target '#lib::Base1::get:bar', arg-desc CP#1
-  [3] = String 'param'
-  [4] = ArgDesc num-args 2, num-type-args 1, names []
+  [0] = ObjectRef < dart:core::int >
+  [1] = DirectCall '#lib::Base1::get:bar', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ObjectRef 'param'
+  [4] = ObjectRef ArgDesc num-args 2, num-type-args 1, names []
   [5] = ICData dynamic target-name 'call', arg-desc CP#4
 }
 ]  method testSuperCallViaGetter() → dynamic
@@ -151,15 +145,14 @@
   CheckStack           0
   Push                 FP[-5]
   PushInt              3
-  PushConstant         CP#1
-  IndirectStaticCall   2, CP#0
+  DirectCall           2, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base1::set:bazz', arg-desc CP#0
+  [0] = DirectCall '#lib::Base1::set:bazz', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  method testSuperSet() → dynamic {
     super.{self::Base1::bazz} = 3;
@@ -171,15 +164,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::Base2
     : super core::Object::•()
@@ -194,15 +186,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::Base2::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::Base2:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::B
     : super self::Base2::•()
@@ -239,23 +230,21 @@
   PushInt              5
   StoreIndexedTOS
   PushTrue
-  PushConstant         CP#7
-  IndirectStaticCall   4, CP#6
-  PushConstant         CP#9
-  IndirectStaticCall   2, CP#8
+  DirectCall           4, CP#6
+  DirectCall           2, CP#8
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 4, num-type-args 1, names []
-  [1] = String 'foo'
-  [2] = TypeArgs [dynamic]
-  [3] = TypeArgs [dart:core::double]
-  [4] = String 'a1'
-  [5] = Double 3.14
-  [6] = ArgDesc num-args 4, num-type-args 0, names []
-  [7] = StaticICData target 'dart:core::_InvocationMirror::_allocateInvocationMirror', arg-desc CP#6
-  [8] = ArgDesc num-args 2, num-type-args 0, names []
-  [9] = StaticICData target 'dart:core::Object::noSuchMethod', arg-desc CP#8
+  [0] = ObjectRef ArgDesc num-args 4, num-type-args 1, names []
+  [1] = ObjectRef 'foo'
+  [2] = ObjectRef < dynamic >
+  [3] = ObjectRef < dart:core::double >
+  [4] = ObjectRef 'a1'
+  [5] = ObjectRef const 3.14
+  [6] = DirectCall 'dart:core::_InvocationMirror::_allocateInvocationMirror', ArgDesc num-args 4, num-type-args 0, names []
+  [7] = Reserved
+  [8] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
+  [9] = Reserved
 }
 ]  method testSuperCall(core::int x) → dynamic
     return super.{self::Base2::foo}<core::double>("a1", 3.14, 5);
@@ -275,20 +264,18 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  PushConstant         CP#4
-  IndirectStaticCall   4, CP#3
-  PushConstant         CP#6
-  IndirectStaticCall   2, CP#5
+  DirectCall           4, CP#3
+  DirectCall           2, CP#5
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = String 'foo'
-  [2] = TypeArgs [dynamic]
-  [3] = ArgDesc num-args 4, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::_InvocationMirror::_allocateInvocationMirror', arg-desc CP#3
-  [5] = ArgDesc num-args 2, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::Object::noSuchMethod', arg-desc CP#5
+  [0] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [1] = ObjectRef 'foo'
+  [2] = ObjectRef < dynamic >
+  [3] = DirectCall 'dart:core::_InvocationMirror::_allocateInvocationMirror', ArgDesc num-args 4, num-type-args 0, names []
+  [4] = Reserved
+  [5] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
+  [6] = Reserved
 }
 ]  method testSuperTearOff() → dynamic
     return super.{self::Base2::foo};
@@ -308,20 +295,18 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  PushConstant         CP#4
-  IndirectStaticCall   4, CP#3
-  PushConstant         CP#6
-  IndirectStaticCall   2, CP#5
+  DirectCall           4, CP#3
+  DirectCall           2, CP#5
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = String 'bar'
-  [2] = TypeArgs [dynamic]
-  [3] = ArgDesc num-args 4, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::_InvocationMirror::_allocateInvocationMirror', arg-desc CP#3
-  [5] = ArgDesc num-args 2, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::Object::noSuchMethod', arg-desc CP#5
+  [0] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [1] = ObjectRef 'bar'
+  [2] = ObjectRef < dynamic >
+  [3] = DirectCall 'dart:core::_InvocationMirror::_allocateInvocationMirror', ArgDesc num-args 4, num-type-args 0, names []
+  [4] = Reserved
+  [5] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
+  [6] = Reserved
 }
 ]  method testSuperGet() → dynamic
     return super.{self::Base2::bar};
@@ -342,25 +327,23 @@
   Push                 FP[-5]
   StoreIndexedTOS
   PushTrue
-  PushConstant         CP#5
-  IndirectStaticCall   4, CP#4
-  PushConstant         CP#7
-  IndirectStaticCall   2, CP#6
+  DirectCall           4, CP#4
+  DirectCall           2, CP#6
   PushConstant         CP#8
   DynamicCall          3, CP#10
   ReturnTOS
 }
 ConstantPool {
-  [0] = TypeArgs [dart:core::int]
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = String 'bar'
-  [3] = TypeArgs [dynamic]
-  [4] = ArgDesc num-args 4, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::_InvocationMirror::_allocateInvocationMirror', arg-desc CP#4
-  [6] = ArgDesc num-args 2, num-type-args 0, names []
-  [7] = StaticICData target 'dart:core::Object::noSuchMethod', arg-desc CP#6
-  [8] = String 'param'
-  [9] = ArgDesc num-args 2, num-type-args 1, names []
+  [0] = ObjectRef < dart:core::int >
+  [1] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [2] = ObjectRef 'bar'
+  [3] = ObjectRef < dynamic >
+  [4] = DirectCall 'dart:core::_InvocationMirror::_allocateInvocationMirror', ArgDesc num-args 4, num-type-args 0, names []
+  [5] = Reserved
+  [6] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
+  [7] = Reserved
+  [8] = ObjectRef 'param'
+  [9] = ObjectRef ArgDesc num-args 2, num-type-args 1, names []
   [10] = ICData dynamic target-name 'call', arg-desc CP#9
 }
 ]  method testSuperCallViaGetter() → dynamic
@@ -385,21 +368,20 @@
   PushInt              3
   StoreIndexedTOS
   PushTrue
-  PushConstant         CP#4
-  IndirectStaticCall   4, CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   2, CP#0
+  DirectCall           4, CP#3
+  DirectCall           2, CP#5
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = String 'bazz'
-  [2] = TypeArgs [dynamic]
-  [3] = ArgDesc num-args 4, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::_InvocationMirror::_allocateInvocationMirror', arg-desc CP#3
-  [5] = StaticICData target 'dart:core::Object::noSuchMethod', arg-desc CP#0
+  [0] = ObjectRef ArgDesc num-args 2, num-type-args 0, names []
+  [1] = ObjectRef 'bazz'
+  [2] = ObjectRef < dynamic >
+  [3] = DirectCall 'dart:core::_InvocationMirror::_allocateInvocationMirror', ArgDesc num-args 4, num-type-args 0, names []
+  [4] = Reserved
+  [5] = DirectCall 'dart:core::Object::noSuchMethod', ArgDesc num-args 2, num-type-args 0, names []
+  [6] = Reserved
 }
 ]  method testSuperSet() → dynamic {
     super.{self::Base2::bazz} = 3;
diff --git a/pkg/vm/testcases/bytecode/switch.dart.expect b/pkg/vm/testcases/bytecode/switch.dart.expect
index 93301c3..d66c358 100644
--- a/pkg/vm/testcases/bytecode/switch.dart.expect
+++ b/pkg/vm/testcases/bytecode/switch.dart.expect
@@ -12,15 +12,15 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L3
   Jump                 L4
 L1:
@@ -40,9 +40,8 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = InterfaceCall target-name '==', arg-desc CP#0
-  [2] = Reserved
+  [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
 }
 ]static method foo1(core::int x) → core::int {
   core::int y;
@@ -79,27 +78,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -118,9 +117,8 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = InterfaceCall target-name '==', arg-desc CP#0
-  [2] = Reserved
+  [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
 }
 ]static method foo2(core::int x) → core::int {
   core::int y;
@@ -160,27 +158,27 @@
   PopLocal             r1
   Push                 r1
   PushInt              1
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              2
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              3
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r1
   PushInt              4
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Push                 r1
   PushInt              5
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Push                 r1
   PushInt              6
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Jump                 L3
 L1:
@@ -199,9 +197,8 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = InterfaceCall target-name '==', arg-desc CP#0
-  [2] = Reserved
+  [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
 }
 ]static method foo3(core::int x) → core::int {
   core::int y;
diff --git a/pkg/vm/testcases/bytecode/try_blocks.dart.expect b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
index e946fb1..384bd81 100644
--- a/pkg/vm/testcases/bytecode/try_blocks.dart.expect
+++ b/pkg/vm/testcases/bytecode/try_blocks.dart.expect
@@ -8,8 +8,7 @@
   CheckStack           0
 Try #0 start:
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -31,10 +30,8 @@
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#1
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#5
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L1:
@@ -42,16 +39,16 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 7, handler 7, types [CP#3]
+  try-index 0, outer -1, start 2, end 6, handler 6, types [CP#3]
 }
 ConstantPool {
-  [0] = String 'danger!'
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef 'danger!'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
   [3] = Type dynamic
-  [4] = String 'caught '
-  [5] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [4] = ObjectRef 'caught '
+  [5] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
 }
 ]static method testTryCatch1() → dynamic {
   try {
@@ -67,8 +64,7 @@
   CheckStack           0
 Try #0 start:
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 Try #0 end:
@@ -78,17 +74,16 @@
   MoveSpecial          stackTrace, r1
   Push                 r0
   PushConstant         CP#3
-  InterfaceCall        2, CP#5
+  InterfaceCall        2, CP#4
   JumpIfFalse          L2
-  PushConstant         CP#7
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#1
+  PushConstant         CP#6
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L2:
   Push                 r0
-  PushConstant         CP#9
-  InterfaceCall        2, CP#5
+  PushConstant         CP#7
+  InterfaceCall        2, CP#4
   JumpIfFalse          L3
   Push                 r0
   PopLocal             r2
@@ -98,22 +93,20 @@
   StoreLocal           r3
   Push                 r3
   PushInt              0
-  PushConstant         CP#10
+  PushConstant         CP#8
   StoreIndexedTOS
   Push                 r3
   PushInt              1
   Push                 r2
   StoreIndexedTOS
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#1
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#9
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L3:
   Push                 r0
-  PushConstant         CP#13
-  InterfaceCall        2, CP#5
+  PushConstant         CP#11
+  InterfaceCall        2, CP#4
   JumpIfFalse          L4
   Push                 r0
   PopLocal             r2
@@ -125,7 +118,7 @@
   StoreLocal           r4
   Push                 r4
   PushInt              0
-  PushConstant         CP#14
+  PushConstant         CP#12
   StoreIndexedTOS
   Push                 r4
   PushInt              1
@@ -133,16 +126,14 @@
   StoreIndexedTOS
   Push                 r4
   PushInt              2
-  PushConstant         CP#15
+  PushConstant         CP#13
   StoreIndexedTOS
   Push                 r4
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  PushConstant         CP#16
-  IndirectStaticCall   1, CP#1
-  PushConstant         CP#17
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#9
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L4:
@@ -156,7 +147,7 @@
   StoreLocal           r4
   Push                 r4
   PushInt              0
-  PushConstant         CP#19
+  PushConstant         CP#15
   StoreIndexedTOS
   Push                 r4
   PushInt              1
@@ -164,16 +155,14 @@
   StoreIndexedTOS
   Push                 r4
   PushInt              2
-  PushConstant         CP#15
+  PushConstant         CP#13
   StoreIndexedTOS
   Push                 r4
   PushInt              3
   Push                 r3
   StoreIndexedTOS
-  PushConstant         CP#20
-  IndirectStaticCall   1, CP#1
-  PushConstant         CP#21
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#9
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L1:
@@ -181,31 +170,25 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 7, handler 7, needs-stack-trace, types [CP#3, CP#9, CP#13, CP#18]
+  try-index 0, outer -1, start 2, end 6, handler 6, needs-stack-trace, types [CP#3, CP#7, CP#11, CP#14]
 }
 ConstantPool {
-  [0] = String 'danger!'
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef 'danger!'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
   [3] = Type dart:core::TypeError
-  [4] = ArgDesc num-args 2, num-type-args 0, names []
-  [5] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#4
-  [6] = Reserved
-  [7] = String 'caught type error'
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [9] = Type dart:core::AssertionError
-  [10] = String 'caught assertion error '
-  [11] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [13] = Type dart:core::Error
-  [14] = String 'caught error '
-  [15] = String ' '
-  [16] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [17] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [18] = Type dynamic
-  [19] = String 'caught something '
-  [20] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#1
-  [21] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [4] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+  [5] = Reserved
+  [6] = ObjectRef 'caught type error'
+  [7] = Type dart:core::AssertionError
+  [8] = ObjectRef 'caught assertion error '
+  [9] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [10] = Reserved
+  [11] = Type dart:core::Error
+  [12] = ObjectRef 'caught error '
+  [13] = ObjectRef ' '
+  [14] = Type dynamic
+  [15] = ObjectRef 'caught something '
 }
 ]static method testTryCatch2() → dynamic {
   try {
@@ -239,20 +222,20 @@
   Push                 r0
   PushInt              2
   StoreContextVar      0, 1
-  Allocate             CP#9
+  Allocate             CP#8
   StoreLocal           r5
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#10
+  StoreFieldTOS        CP#9
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r5
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
+  PushConstant         CP#13
+  StoreFieldTOS        CP#14
   Push                 r5
   PushConstant         CP#0
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#16
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -262,8 +245,7 @@
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  PushConstant         CP#20
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#4
   Drop1
   Jump                 L1
 Try #0 end:
@@ -284,7 +266,7 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#21
+  PushConstant         CP#20
   StoreIndexedTOS
   Push                 r5
   PushInt              1
@@ -292,32 +274,30 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              2
-  PushConstant         CP#22
+  PushConstant         CP#21
   StoreIndexedTOS
   Push                 r5
   PushInt              3
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  PushConstant         CP#23
-  IndirectStaticCall   1, CP#4
-  PushConstant         CP#24
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#22
+  DirectCall           1, CP#4
   Drop1
-  Allocate             CP#9
+  Allocate             CP#8
   StoreLocal           r5
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#10
+  StoreFieldTOS        CP#9
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#12
+  StoreFieldTOS        CP#11
   Push                 r5
-  PushConstant         CP#14
-  StoreFieldTOS        CP#15
+  PushConstant         CP#13
+  StoreFieldTOS        CP#14
   Push                 r5
-  PushConstant         CP#25
-  StoreFieldTOS        CP#17
+  PushConstant         CP#24
+  StoreFieldTOS        CP#16
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -332,48 +312,43 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 9, end 39, handler 39, needs-stack-trace, types [CP#6]
+  try-index 0, outer -1, start 9, end 38, handler 38, needs-stack-trace, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
-  [3] = String 'danger foo'
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [3] = ObjectRef 'danger foo'
+  [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
   [6] = Type dynamic
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [8] = EndClosureFunctionScope
-  [9] = Class dart:core::_Closure
-  [10] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [11] = Reserved
-  [12] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [13] = Reserved
-  [14] = EmptyTypeArguments
-  [15] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [16] = Reserved
-  [17] = InstanceField dart:core::_Closure::_function (field)
-  [18] = Reserved
-  [19] = ICData dynamic target-name 'call', arg-desc CP#4
-  [20] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [21] = String 'caught '
-  [22] = String ' '
-  [23] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
-  [24] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [25] = ClosureFunction 1
-  [26] = String 'danger bar'
-  [27] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [28] = Type dart:core::Error
-  [29] = ArgDesc num-args 2, num-type-args 0, names []
-  [30] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#29
-  [31] = Reserved
-  [32] = String 'error '
-  [33] = String ', captured stack trace: '
-  [34] = StaticICData target 'dart:core::_StringBase::_interpolate', arg-desc CP#4
-  [35] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [36] = EndClosureFunctionScope
+  [7] = EndClosureFunctionScope
+  [8] = Class dart:core::_Closure
+  [9] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [10] = Reserved
+  [11] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [12] = Reserved
+  [13] = EmptyTypeArguments
+  [14] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [15] = Reserved
+  [16] = InstanceField dart:core::_Closure::_function (field)
+  [17] = Reserved
+  [18] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [19] = ICData dynamic target-name 'call', arg-desc CP#18
+  [20] = ObjectRef 'caught '
+  [21] = ObjectRef ' '
+  [22] = DirectCall 'dart:core::_StringBase::_interpolate', ArgDesc num-args 1, num-type-args 0, names []
+  [23] = Reserved
+  [24] = ClosureFunction 1
+  [25] = ObjectRef 'danger bar'
+  [26] = Type dart:core::Error
+  [27] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+  [28] = Reserved
+  [29] = ObjectRef 'error '
+  [30] = ObjectRef ', captured stack trace: '
+  [31] = EndClosureFunctionScope
 }
-Closure #lib::testTryCatch3::foo () -> void
+Closure #lib::testTryCatch3::'foo' () -> void
 ClosureBytecode {
   EntryFixed           1, 6
   CheckStack           0
@@ -384,8 +359,7 @@
   PopLocal             r2
 Try #0 start:
   PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#4
   Drop1
   Jump                 L1
 Try #0 end:
@@ -399,8 +373,7 @@
   PopLocal             r4
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#4
   Drop1
   Push                 r0
   PushInt              3
@@ -412,7 +385,7 @@
 
 }
 
-Closure #lib::testTryCatch3::bar () -> void
+Closure #lib::testTryCatch3::'bar' () -> void
 ClosureBytecode {
   EntryFixed           1, 6
   CheckStack           0
@@ -422,9 +395,8 @@
   Push                 r0
   PopLocal             r2
 Try #0 start:
-  PushConstant         CP#26
-  PushConstant         CP#27
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#25
+  DirectCall           1, CP#4
   Drop1
   Jump                 L1
 Try #0 end:
@@ -435,8 +407,8 @@
   MoveSpecial          exception, r2
   MoveSpecial          stackTrace, r3
   Push                 r2
-  PushConstant         CP#28
-  InterfaceCall        2, CP#30
+  PushConstant         CP#26
+  InterfaceCall        2, CP#27
   JumpIfFalse          L2
   Push                 r2
   PopLocal             r4
@@ -446,7 +418,7 @@
   StoreLocal           r5
   Push                 r5
   PushInt              0
-  PushConstant         CP#32
+  PushConstant         CP#29
   StoreIndexedTOS
   Push                 r5
   PushInt              1
@@ -454,17 +426,15 @@
   StoreIndexedTOS
   Push                 r5
   PushInt              2
-  PushConstant         CP#33
+  PushConstant         CP#30
   StoreIndexedTOS
   Push                 r5
   PushInt              3
   Push                 r0
   LoadContextVar       0, 2
   StoreIndexedTOS
-  PushConstant         CP#34
-  IndirectStaticCall   1, CP#4
-  PushConstant         CP#35
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#22
+  DirectCall           1, CP#4
   Drop1
   Jump                 L1
 L2:
@@ -512,8 +482,7 @@
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 Try #1 end:
@@ -525,8 +494,7 @@
   PopLocal             r4
 Try #2 start:
   PushConstant         CP#4
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Push                 FP[-5]
   AssertBoolean        0
@@ -543,9 +511,8 @@
   MoveSpecial          stackTrace, r6
   Push                 r5
   PopLocal             r7
-  PushConstant         CP#6
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#1
+  PushConstant         CP#5
+  DirectCall           1, CP#1
   Drop1
   Jump                 L3
 L3:
@@ -561,13 +528,11 @@
   PopLocal             r2
   Push                 r1
   PopLocal             r3
-  PushConstant         CP#8
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#1
+  PushConstant         CP#6
+  DirectCall           1, CP#1
   Drop1
   Push                 r3
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L4
 L4:
@@ -575,22 +540,18 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 35, handler 35, needs-stack-trace, types [CP#3]
-  try-index 1, outer 0, start 2, end 7, handler 7, needs-stack-trace, types [CP#3]
-  try-index 2, outer 0, start 12, end 23, handler 23, types [CP#3]
+  try-index 0, outer -1, start 2, end 32, handler 32, needs-stack-trace, types [CP#3]
+  try-index 1, outer 0, start 2, end 6, handler 6, needs-stack-trace, types [CP#3]
+  try-index 2, outer 0, start 11, end 21, handler 21, types [CP#3]
 }
 ConstantPool {
-  [0] = String 'try 1 > try 2'
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef 'try 1 > try 2'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
   [3] = Type dynamic
-  [4] = String 'try 1 > catch 2 > try 3'
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [6] = String 'try 1 > catch 2 > catch 3'
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [8] = String 'catch 1'
-  [9] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [4] = ObjectRef 'try 1 > catch 2 > try 3'
+  [5] = ObjectRef 'try 1 > catch 2 > catch 3'
+  [6] = ObjectRef 'catch 1'
 }
 ]static method testRethrow(core::bool cond) → dynamic {
   try {
@@ -640,22 +601,19 @@
   MoveSpecial          exception, r1
   MoveSpecial          stackTrace, r2
   Push                 r0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Push                 r1
   Push                 r2
   Throw                1
 L3:
   Push                 r0
-  PushConstant         CP#3
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L4:
   Push                 r0
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Push                 r0
   PushInt              1
@@ -672,10 +630,8 @@
 }
 ConstantPool {
   [0] = Type dynamic
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [3] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
 }
 ]static method testTryFinally1() → dynamic {
   #L1:
@@ -704,20 +660,19 @@
   PopLocal             r2
   Push                 r2
   PushInt              1
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L1
   Push                 r2
   PushInt              2
-  InterfaceCall        2, CP#1
+  InterfaceCall        2, CP#0
   JumpIfTrue           L2
   Jump                 L3
 L1:
   Push                 r0
   PopLocal             r3
 Try #0 start:
-  PushConstant         CP#3
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#2
+  DirectCall           1, CP#3
   Drop1
   Push                 r0
   PushInt              3
@@ -725,30 +680,29 @@
   Push                 r0
   PopLocal             r5
 Try #1 start:
-  PushConstant         CP#6
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#5
+  DirectCall           1, CP#3
   Drop1
-  Allocate             CP#14
+  Allocate             CP#10
   StoreLocal           r8
   Push                 r8
   PushNull
-  StoreFieldTOS        CP#15
+  StoreFieldTOS        CP#11
   Push                 r8
   PushNull
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#13
   Push                 r8
-  PushConstant         CP#19
-  StoreFieldTOS        CP#20
+  PushConstant         CP#15
+  StoreFieldTOS        CP#16
   Push                 r8
-  PushConstant         CP#8
-  StoreFieldTOS        CP#22
+  PushConstant         CP#6
+  StoreFieldTOS        CP#18
   Push                 r8
   Push                 r0
-  StoreFieldTOS        CP#9
+  StoreFieldTOS        CP#7
   PopLocal             r7
   Push                 r7
-  DynamicCall          1, CP#24
+  DynamicCall          1, CP#21
   Drop1
   Jump                 L4
 Try #1 end:
@@ -758,9 +712,8 @@
   PopLocal             r0
   MoveSpecial          exception, r5
   MoveSpecial          stackTrace, r6
-  PushConstant         CP#26
-  PushConstant         CP#27
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#23
+  DirectCall           1, CP#3
   Drop1
   Push                 r5
   Push                 r6
@@ -768,9 +721,8 @@
 L4:
   Push                 r5
   PopLocal             r0
-  PushConstant         CP#26
-  PushConstant         CP#28
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#23
+  DirectCall           1, CP#3
   Drop1
   Jump                 L5
 Try #0 end:
@@ -780,9 +732,8 @@
   PopLocal             r0
   MoveSpecial          exception, r3
   MoveSpecial          stackTrace, r4
-  PushConstant         CP#31
-  PushConstant         CP#32
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#25
+  DirectCall           1, CP#3
   Drop1
   Push                 r3
   Push                 r4
@@ -790,15 +741,13 @@
 L5:
   Push                 r3
   PopLocal             r0
-  PushConstant         CP#31
-  PushConstant         CP#33
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#25
+  DirectCall           1, CP#3
   Drop1
   Jump                 L2
 L2:
-  PushConstant         CP#34
-  PushConstant         CP#35
-  IndirectStaticCall   1, CP#4
+  PushConstant         CP#26
+  DirectCall           1, CP#3
   Drop1
   Jump                 L3
 L3:
@@ -806,63 +755,52 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 21, end 75, handler 75, needs-stack-trace, types [CP#25]
-  try-index 1, outer 0, start 30, end 56, handler 56, needs-stack-trace, types [CP#25]
+  try-index 0, outer -1, start 21, end 71, handler 71, needs-stack-trace, types [CP#22]
+  try-index 1, outer 0, start 29, end 54, handler 54, needs-stack-trace, types [CP#22]
 }
 ConstantPool {
-  [0] = ArgDesc num-args 2, num-type-args 0, names []
-  [1] = InterfaceCall target-name '==', arg-desc CP#0
-  [2] = Reserved
-  [3] = String 'before try 1'
-  [4] = ArgDesc num-args 1, num-type-args 0, names []
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [6] = String 'try'
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [8] = ClosureFunction 0
-  [9] = InstanceField dart:core::_Closure::_context (field)
-  [10] = Reserved
-  [11] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [13] = EndClosureFunctionScope
-  [14] = Class dart:core::_Closure
-  [15] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
-  [16] = Reserved
-  [17] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [18] = Reserved
-  [19] = EmptyTypeArguments
-  [20] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [21] = Reserved
-  [22] = InstanceField dart:core::_Closure::_function (field)
-  [23] = Reserved
-  [24] = ICData dynamic target-name 'call', arg-desc CP#4
-  [25] = Type dynamic
-  [26] = String 'finally 1'
-  [27] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [28] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [29] = String 'after try 1'
-  [30] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [31] = String 'finally 2'
-  [32] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [33] = StaticICData target 'dart:core::print', arg-desc CP#4
-  [34] = String 'case 2'
-  [35] = StaticICData target 'dart:core::print', arg-desc CP#4
+  [0] = InterfaceCall 'dart:core::Object::==', ArgDesc num-args 2, num-type-args 0, names []
+  [1] = Reserved
+  [2] = ObjectRef 'before try 1'
+  [3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = ObjectRef 'try'
+  [6] = ClosureFunction 0
+  [7] = InstanceField dart:core::_Closure::_context (field)
+  [8] = Reserved
+  [9] = EndClosureFunctionScope
+  [10] = Class dart:core::_Closure
+  [11] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [12] = Reserved
+  [13] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [14] = Reserved
+  [15] = EmptyTypeArguments
+  [16] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [17] = Reserved
+  [18] = InstanceField dart:core::_Closure::_function (field)
+  [19] = Reserved
+  [20] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [21] = ICData dynamic target-name 'call', arg-desc CP#20
+  [22] = Type dynamic
+  [23] = ObjectRef 'finally 1'
+  [24] = ObjectRef 'after try 1'
+  [25] = ObjectRef 'finally 2'
+  [26] = ObjectRef 'case 2'
 }
-Closure #lib::testTryFinally2::foo () -> void
+Closure #lib::testTryFinally2::'foo' () -> void
 ClosureBytecode {
   EntryFixed           1, 2
   CheckStack           0
   Push                 FP[-5]
-  LoadFieldTOS         CP#9
+  LoadFieldTOS         CP#7
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#3
   Drop1
   Push                 r0
   LoadContextVar       0, 1
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#4
+  DirectCall           1, CP#3
   Drop1
   PushNull
   ReturnTOS
@@ -918,20 +856,20 @@
   Push                 r0
   PopLocal             r3
 Try #0 start:
-  Allocate             CP#16
+  Allocate             CP#9
   StoreLocal           r5
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#17
+  StoreFieldTOS        CP#10
   Push                 r5
   PushNull
-  StoreFieldTOS        CP#19
+  StoreFieldTOS        CP#12
   Push                 r5
-  PushConstant         CP#21
-  StoreFieldTOS        CP#22
+  PushConstant         CP#14
+  StoreFieldTOS        CP#15
   Push                 r5
   PushConstant         CP#0
-  StoreFieldTOS        CP#24
+  StoreFieldTOS        CP#17
   Push                 r5
   Push                 r0
   StoreFieldTOS        CP#1
@@ -946,11 +884,10 @@
   MoveSpecial          stackTrace, r4
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#26
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Push                 r2
-  DynamicCall          1, CP#27
+  DynamicCall          1, CP#20
   Drop1
   Push                 r3
   Push                 r4
@@ -960,11 +897,10 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#28
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Push                 r2
-  DynamicCall          1, CP#29
+  DynamicCall          1, CP#21
   Drop1
   Push                 r0
   LoadContextParent
@@ -973,41 +909,33 @@
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 11, end 30, handler 30, needs-stack-trace, types [CP#7]
+  try-index 0, outer -1, start 11, end 30, handler 30, needs-stack-trace, types [CP#6]
 }
 ConstantPool {
   [0] = ClosureFunction 0
   [1] = InstanceField dart:core::_Closure::_context (field)
   [2] = Reserved
-  [3] = ArgDesc num-args 1, num-type-args 0, names []
-  [4] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [5] = String 'try 1'
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [7] = Type dynamic
-  [8] = String 'try 2'
-  [9] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [11] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [13] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [14] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [15] = EndClosureFunctionScope
-  [16] = Class dart:core::_Closure
-  [17] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [3] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [4] = Reserved
+  [5] = ObjectRef 'try 1'
+  [6] = Type dynamic
+  [7] = ObjectRef 'try 2'
+  [8] = EndClosureFunctionScope
+  [9] = Class dart:core::_Closure
+  [10] = InstanceField dart:core::_Closure::_instantiator_type_arguments (field)
+  [11] = Reserved
+  [12] = InstanceField dart:core::_Closure::_function_type_arguments (field)
+  [13] = Reserved
+  [14] = EmptyTypeArguments
+  [15] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
+  [16] = Reserved
+  [17] = InstanceField dart:core::_Closure::_function (field)
   [18] = Reserved
-  [19] = InstanceField dart:core::_Closure::_function_type_arguments (field)
-  [20] = Reserved
-  [21] = EmptyTypeArguments
-  [22] = InstanceField dart:core::_Closure::_delayed_type_arguments (field)
-  [23] = Reserved
-  [24] = InstanceField dart:core::_Closure::_function (field)
-  [25] = Reserved
-  [26] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [27] = ICData dynamic target-name 'call', arg-desc CP#3
-  [28] = StaticICData target 'dart:core::print', arg-desc CP#3
-  [29] = ICData dynamic target-name 'call', arg-desc CP#3
+  [19] = ObjectRef ArgDesc num-args 1, num-type-args 0, names []
+  [20] = ICData dynamic target-name 'call', arg-desc CP#19
+  [21] = ICData dynamic target-name 'call', arg-desc CP#19
 }
-Closure #lib::testTryFinally3::<anonymous closure> () -> dart:core::int
+Closure #lib::testTryFinally3::'<anonymous closure>' () -> dart:core::int
 ClosureBytecode {
   EntryFixed           1, 6
   CheckStack           0
@@ -1016,15 +944,13 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#4
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Push                 r0
   PopLocal             r2
 Try #0 start:
   PushConstant         CP#5
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Jump                 L1
 Try #0 end:
@@ -1037,9 +963,8 @@
   Push                 r0
   PopLocal             r4
 Try #1 start:
-  PushConstant         CP#8
-  PushConstant         CP#9
-  IndirectStaticCall   1, CP#3
+  PushConstant         CP#7
+  DirectCall           1, CP#3
   Drop1
   Jump                 L2
 Try #1 end:
@@ -1051,8 +976,7 @@
   MoveSpecial          stackTrace, r5
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Push                 r4
   Push                 r5
@@ -1062,8 +986,7 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#11
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   PushInt              43
   ReturnTOS
@@ -1073,9 +996,8 @@
   Push                 r0
   PopLocal             r4
 Try #2 start:
-  PushConstant         CP#8
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#3
+  PushConstant         CP#7
+  DirectCall           1, CP#3
   Drop1
   Jump                 L3
 Try #2 end:
@@ -1087,8 +1009,7 @@
   MoveSpecial          stackTrace, r5
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#13
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   Push                 r4
   Push                 r5
@@ -1098,8 +1019,7 @@
   PopLocal             r0
   Push                 r0
   LoadContextVar       0, 0
-  PushConstant         CP#14
-  IndirectStaticCall   1, CP#3
+  DirectCall           1, CP#3
   Drop1
   PushInt              43
   ReturnTOS
@@ -1138,8 +1058,7 @@
 Try #0 start:
 Try #1 start:
   PushConstant         CP#0
-  PushConstant         CP#2
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 Try #1 end:
@@ -1150,8 +1069,7 @@
   Push                 r2
   PopLocal             r4
   PushConstant         CP#4
-  PushConstant         CP#5
-  IndirectStaticCall   1, CP#1
+  DirectCall           1, CP#1
   Drop1
   Jump                 L1
 L1:
@@ -1161,35 +1079,30 @@
   SetFrame             5
   MoveSpecial          exception, r0
   MoveSpecial          stackTrace, r1
-  PushConstant         CP#6
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#1
+  PushConstant         CP#5
+  DirectCall           1, CP#1
   Drop1
   Push                 r0
   Push                 r1
   Throw                1
 L2:
-  PushConstant         CP#6
-  PushConstant         CP#8
-  IndirectStaticCall   1, CP#1
+  PushConstant         CP#5
+  DirectCall           1, CP#1
   Drop1
   PushNull
   ReturnTOS
 }
 ExceptionsTable {
-  try-index 0, outer -1, start 2, end 18, handler 18, needs-stack-trace, types [CP#3]
-  try-index 1, outer 0, start 2, end 7, handler 7, types [CP#3]
+  try-index 0, outer -1, start 2, end 16, handler 16, needs-stack-trace, types [CP#3]
+  try-index 1, outer 0, start 2, end 6, handler 6, types [CP#3]
 }
 ConstantPool {
-  [0] = String 'try'
-  [1] = ArgDesc num-args 1, num-type-args 0, names []
-  [2] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [0] = ObjectRef 'try'
+  [1] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [2] = Reserved
   [3] = Type dynamic
-  [4] = String 'catch'
-  [5] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [6] = String 'finally'
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#1
-  [8] = StaticICData target 'dart:core::print', arg-desc CP#1
+  [4] = ObjectRef 'catch'
+  [5] = ObjectRef 'finally'
 }
 ]static method testTryCatchFinally() → dynamic {
   try
diff --git a/pkg/vm/testcases/bytecode/type_ops.dart.expect b/pkg/vm/testcases/bytecode/type_ops.dart.expect
index 04a4e32..6da40f3 100644
--- a/pkg/vm/testcases/bytecode/type_ops.dart.expect
+++ b/pkg/vm/testcases/bytecode/type_ops.dart.expect
@@ -8,15 +8,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target 'dart:core::Object::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall 'dart:core::Object:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::A<self::A::T>
     : super core::Object::•()
@@ -28,15 +27,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::A::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::A:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::B
     : super self::A::•()
@@ -48,15 +46,14 @@
   Entry                0
   CheckStack           0
   Push                 FP[-5]
-  PushConstant         CP#1
-  IndirectStaticCall   1, CP#0
+  DirectCall           1, CP#0
   Drop1
   PushNull
   ReturnTOS
 }
 ConstantPool {
-  [0] = ArgDesc num-args 1, num-type-args 0, names []
-  [1] = StaticICData target '#lib::B::'' (constructor)', arg-desc CP#0
+  [0] = DirectCall '#lib::B:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [1] = Reserved
 }
 ]  synthetic constructor •() → self::C<self::C::T1, self::C::T2, self::C::T3>
     : super self::B::•()
@@ -78,8 +75,7 @@
   AssertAssignable     0, CP#3
   StoreFieldTOS        CP#4
   Push                 FP[-6]
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#6
+  DirectCall           1, CP#6
   Drop1
   PushNull
   ReturnTOS
@@ -87,12 +83,12 @@
 ConstantPool {
   [0] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
   [1] = TypeArgumentsField #lib::D
-  [2] = String ''
+  [2] = ObjectRef ''
   [3] = SubtypeTestCache
   [4] = InstanceField #lib::D::foo (field)
   [5] = Reserved
-  [6] = ArgDesc num-args 1, num-type-args 0, names []
-  [7] = StaticICData target '#lib::C::'' (constructor)', arg-desc CP#6
+  [6] = DirectCall '#lib::C:: (constructor)', ArgDesc num-args 1, num-type-args 0, names []
+  [7] = Reserved
 }
 ]  constructor •(dynamic tt) → self::D<self::D::P, self::D::Q>
     : self::D::foo = tt as{TypeError} core::Map<self::D::P, self::D::Q>, super self::C::•()
@@ -106,34 +102,32 @@
   LoadTypeArgumentsField CP#0
   PushNull
   PushConstant         CP#1
-  InterfaceCall        4, CP#3
+  InterfaceCall        4, CP#2
   JumpIfFalse          L1
-  PushConstant         CP#5
-  PushConstant         CP#7
-  IndirectStaticCall   1, CP#6
+  PushConstant         CP#4
+  DirectCall           1, CP#5
   Drop1
 L1:
   Push                 FP[-5]
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
   PushNull
-  PushConstant         CP#8
-  InterfaceCall        4, CP#3
+  PushConstant         CP#7
+  InterfaceCall        4, CP#2
   JumpIfFalse          L2
-  PushConstant         CP#9
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#6
+  PushConstant         CP#8
+  DirectCall           1, CP#5
   Drop1
 L2:
   Push                 FP[-6]
   Push                 FP[-5]
-  PushConstant         CP#11
+  PushConstant         CP#9
   Push                 FP[-6]
   LoadTypeArgumentsField CP#0
   PushNull
-  PushConstant         CP#12
-  AssertAssignable     0, CP#13
-  InterfaceCall        2, CP#15
+  PushConstant         CP#10
+  AssertAssignable     0, CP#11
+  InterfaceCall        2, CP#12
   Drop1
   PushNull
   ReturnTOS
@@ -141,21 +135,18 @@
 ConstantPool {
   [0] = TypeArgumentsField #lib::D
   [1] = Type #lib::A < #lib::D::TypeParam/0 >
-  [2] = ArgDesc num-args 4, num-type-args 0, names []
-  [3] = InterfaceCall target-name '_instanceOf', arg-desc CP#2
-  [4] = Reserved
-  [5] = String '21'
-  [6] = ArgDesc num-args 1, num-type-args 0, names []
-  [7] = StaticICData target 'dart:core::print', arg-desc CP#6
-  [8] = Type #lib::C < dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
-  [9] = String '22'
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#6
-  [11] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
-  [12] = String ''
-  [13] = SubtypeTestCache
-  [14] = ArgDesc num-args 2, num-type-args 0, names []
-  [15] = InterfaceCall set target-name 'set:foo', arg-desc CP#14
-  [16] = Reserved
+  [2] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
+  [3] = Reserved
+  [4] = ObjectRef '21'
+  [5] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [6] = Reserved
+  [7] = Type #lib::C < dart:core::String, dynamic, #lib::D::TypeParam/1, dart:core::List < #lib::D::TypeParam/0 > >
+  [8] = ObjectRef '22'
+  [9] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
+  [10] = ObjectRef ''
+  [11] = SubtypeTestCache
+  [12] = InterfaceCall '#lib::D::set:foo', ArgDesc num-args 2, num-type-args 0, names []
+  [13] = Reserved
 }
 ]  method foo2(dynamic y) → dynamic {
     if(y is self::A<self::D::P>) {
@@ -175,52 +166,48 @@
   PushNull
   Push                 r0
   PushConstant         CP#0
-  InterfaceCall        4, CP#2
+  InterfaceCall        4, CP#1
   JumpIfFalse          L1
-  PushConstant         CP#4
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  PushConstant         CP#3
+  DirectCall           1, CP#4
   Drop1
 L1:
   Push                 FP[-5]
   Push                 FP[-6]
-  LoadTypeArgumentsField CP#7
+  LoadTypeArgumentsField CP#6
   Push                 r0
-  PushConstant         CP#8
-  InterfaceCall        4, CP#2
+  PushConstant         CP#7
+  InterfaceCall        4, CP#1
   JumpIfFalse          L2
-  PushConstant         CP#9
-  PushConstant         CP#10
-  IndirectStaticCall   1, CP#5
+  PushConstant         CP#8
+  DirectCall           1, CP#4
   Drop1
 L2:
   Push                 FP[-5]
-  PushConstant         CP#11
+  PushConstant         CP#9
   Push                 FP[-6]
-  LoadTypeArgumentsField CP#7
+  LoadTypeArgumentsField CP#6
   Push                 r0
-  PushConstant         CP#12
-  AssertAssignable     0, CP#13
-  InterfaceCall        1, CP#14
+  PushConstant         CP#10
+  AssertAssignable     0, CP#11
+  InterfaceCall        1, CP#12
   ReturnTOS
 }
 ConstantPool {
   [0] = Type #lib::A < #lib::D::foo3::TypeParam/0 >
-  [1] = ArgDesc num-args 4, num-type-args 0, names []
-  [2] = InterfaceCall target-name '_instanceOf', arg-desc CP#1
-  [3] = Reserved
-  [4] = String '31'
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [7] = TypeArgumentsField #lib::D
-  [8] = Type #lib::C < dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
-  [9] = String '32'
-  [10] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [11] = Type dart:core::Map < #lib::D::foo3::TypeParam/1, #lib::D::TypeParam/1 >
-  [12] = String ' in type cast'
-  [13] = SubtypeTestCache
-  [14] = InterfaceCall get target-name 'get:values', arg-desc CP#5
-  [15] = Reserved
+  [1] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ObjectRef '31'
+  [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
+  [6] = TypeArgumentsField #lib::D
+  [7] = Type #lib::C < dart:core::String, dart:core::Map < #lib::D::foo3::TypeParam/0, #lib::D::TypeParam/0 >, dart:core::List < #lib::D::foo3::TypeParam/1 >, #lib::D::TypeParam/1 >
+  [8] = ObjectRef '32'
+  [9] = Type dart:core::Map < #lib::D::foo3::TypeParam/1, #lib::D::TypeParam/1 >
+  [10] = ObjectRef ' in type cast'
+  [11] = SubtypeTestCache
+  [12] = InterfaceCall 'dart:core::Map::get:values', ArgDesc num-args 1, num-type-args 0, names []
+  [13] = Reserved
 }
 ]  method foo3<T1 extends core::Object = dynamic, T2 extends core::Object = dynamic>(dynamic z) → dynamic {
     if(z is self::A<self::D::foo3::T1>) {
@@ -254,8 +241,7 @@
   PushConstant         CP#3
   AssertAssignable     0, CP#4
   StoreIndexedTOS
-  PushConstant         CP#6
-  IndirectStaticCall   2, CP#5
+  DirectCall           2, CP#5
   PopLocal             r0
   Push                 FP[-5]
   PushConstant         CP#2
@@ -268,12 +254,12 @@
 }
 ConstantPool {
   [0] = TypeArgumentsField #lib::D
-  [1] = TypeArgs [dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >]
+  [1] = ObjectRef < dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 > >
   [2] = Type dart:core::Map < #lib::D::TypeParam/0, #lib::D::TypeParam/1 >
-  [3] = String ''
+  [3] = ObjectRef ''
   [4] = SubtypeTestCache
-  [5] = ArgDesc num-args 2, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::List::_fromLiteral (constructor)', arg-desc CP#5
+  [5] = DirectCall 'dart:core::List::_fromLiteral (constructor)', ArgDesc num-args 2, num-type-args 0, names []
+  [6] = Reserved
   [7] = SubtypeTestCache
 }
 ]  method foo4(dynamic w) → core::Map<self::D::P, self::D::Q> {
@@ -317,10 +303,10 @@
 }
 ConstantPool {
   [0] = TypeArgumentsField #lib::E
-  [1] = TypeArgs [#lib::E::TypeParam/0, dart:core::List < #lib::E::TypeParam/0 >]
+  [1] = ObjectRef < #lib::E::TypeParam/0, dart:core::List < #lib::E::TypeParam/0 > >
   [2] = Type #lib::E::foo6::TypeParam/0
   [3] = Type #lib::E::TypeParam/0
-  [4] = String 'T'
+  [4] = ObjectRef 'T'
 }
 ]  method foo6<generic-covariant-impl T extends self::E::P = self::E::P, U extends core::List<self::E::foo6::T> = core::List<self::E::P>>(core::Map<self::E::foo6::T, self::E::foo6::U> map) → void {}
 }
@@ -331,49 +317,44 @@
   CheckStack           0
   Push                 FP[-5]
   PushConstant         CP#0
-  InterfaceCall        2, CP#2
+  InterfaceCall        2, CP#1
   JumpIfFalse          L1
-  PushConstant         CP#4
-  PushConstant         CP#6
-  IndirectStaticCall   1, CP#5
+  PushConstant         CP#3
+  DirectCall           1, CP#4
   Drop1
 L1:
   Push                 FP[-5]
   PushNull
   PushNull
-  PushConstant         CP#7
-  InterfaceCall        4, CP#9
+  PushConstant         CP#6
+  InterfaceCall        4, CP#7
   JumpIfFalse          L2
-  PushConstant         CP#11
-  PushConstant         CP#12
-  IndirectStaticCall   1, CP#5
+  PushConstant         CP#9
+  DirectCall           1, CP#4
   Drop1
 L2:
   Push                 FP[-5]
-  PushConstant         CP#13
+  PushConstant         CP#10
   PushNull
   PushNull
-  PushConstant         CP#14
-  AssertAssignable     0, CP#15
+  PushConstant         CP#11
+  AssertAssignable     0, CP#12
   ReturnTOS
 }
 ConstantPool {
   [0] = Type #lib::B
-  [1] = ArgDesc num-args 2, num-type-args 0, names []
-  [2] = InterfaceCall target-name '_simpleInstanceOf', arg-desc CP#1
-  [3] = Reserved
-  [4] = String '11'
-  [5] = ArgDesc num-args 1, num-type-args 0, names []
-  [6] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [7] = Type #lib::C < dart:core::int, dart:core::Object, dynamic >
-  [8] = ArgDesc num-args 4, num-type-args 0, names []
-  [9] = InterfaceCall target-name '_instanceOf', arg-desc CP#8
-  [10] = Reserved
-  [11] = String '12'
-  [12] = StaticICData target 'dart:core::print', arg-desc CP#5
-  [13] = Type #lib::A < dart:core::int >
-  [14] = String ' in type cast'
-  [15] = SubtypeTestCache
+  [1] = InterfaceCall 'dart:core::Object::_simpleInstanceOf', ArgDesc num-args 2, num-type-args 0, names []
+  [2] = Reserved
+  [3] = ObjectRef '11'
+  [4] = DirectCall 'dart:core::print', ArgDesc num-args 1, num-type-args 0, names []
+  [5] = Reserved
+  [6] = Type #lib::C < dart:core::String, dart:core::int, dart:core::Object, dynamic >
+  [7] = InterfaceCall 'dart:core::Object::_instanceOf', ArgDesc num-args 4, num-type-args 0, names []
+  [8] = Reserved
+  [9] = ObjectRef '12'
+  [10] = Type #lib::A < dart:core::int >
+  [11] = ObjectRef ' in type cast'
+  [12] = SubtypeTestCache
 }
 ]static method foo1(dynamic x) → dynamic {
   if(x is self::B) {
@@ -399,8 +380,8 @@
   ReturnTOS
 }
 ConstantPool {
-  [0] = Type dart:core::List < dart:core::Iterable < dynamic > >
-  [1] = String ''
+  [0] = Type dart:core::List < dart:core::Iterable null >
+  [1] = ObjectRef ''
   [2] = SubtypeTestCache
   [3] = StaticField #lib::globalVar (field)
 }
diff --git a/runtime/bin/BUILD.gn b/runtime/bin/BUILD.gn
index ec64042..41a4b0a 100644
--- a/runtime/bin/BUILD.gn
+++ b/runtime/bin/BUILD.gn
@@ -1004,6 +1004,50 @@
   }
 }
 
+shared_library("ffi_test_dynamic_library") {
+  deps = [
+    ":dart",
+  ]
+  sources = [
+    "ffi_test_dynamic_library.cc",
+  ]
+  include_dirs = [ ".." ]
+  defines = [
+    # The only effect of DART_SHARED_LIB is to export the Dart API.
+    "DART_SHARED_LIB",
+  ]
+  if (is_linux || is_android) {
+    cflags = [ "-fPIC" ]
+  }
+  if (is_win) {
+    libs = [ "dart.lib" ]
+    abs_root_out_dir = rebase_path(root_out_dir)
+    ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
+  }
+}
+
+shared_library("ffi_test_functions") {
+  deps = [
+    ":dart",
+  ]
+  sources = [
+    "ffi_test_functions.cc",
+  ]
+  include_dirs = [ ".." ]
+  defines = [
+    # The only effect of DART_SHARED_LIB is to export the Dart API.
+    "DART_SHARED_LIB",
+  ]
+  if (is_linux || is_android) {
+    cflags = [ "-fPIC" ]
+  }
+  if (is_win) {
+    libs = [ "dart.lib" ]
+    abs_root_out_dir = rebase_path(root_out_dir)
+    ldflags = [ "/LIBPATH:$abs_root_out_dir" ]
+  }
+}
+
 shared_library("sample_extension") {
   deps = [
     ":dart",
diff --git a/runtime/bin/ffi_test_dynamic_library.cc b/runtime/bin/ffi_test_dynamic_library.cc
new file mode 100644
index 0000000..c925300
--- /dev/null
+++ b/runtime/bin/ffi_test_dynamic_library.cc
@@ -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.
+
+#include "include/dart_api.h"
+
+DART_EXPORT int return42() {
+  return 42;
+}
+
+DART_EXPORT double timesFour(double d) {
+  return d * 4.0;
+}
diff --git a/runtime/bin/ffi_test_functions.cc b/runtime/bin/ffi_test_functions.cc
new file mode 100644
index 0000000..0248829
--- /dev/null
+++ b/runtime/bin/ffi_test_functions.cc
@@ -0,0 +1,368 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// This file contains test functions for the dart:ffi test cases.
+
+#include <stddef.h>
+#include <iostream>
+
+#include "include/dart_api.h"
+
+namespace dart {
+
+// Sums two ints and adds 42.
+// Simple function to test trampolines.
+// Also used for testing argument exception on passing null instead of a Dart
+// int.
+DART_EXPORT int32_t SumPlus42(int32_t a, int32_t b) {
+  std::cout << "SumPlus42(" << a << ", " << b << ")\n";
+  int32_t retval = 42 + a + b;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Performs some computation on various sized signed ints.
+// Used for testing value ranges for signed ints.
+DART_EXPORT int64_t IntComputation(int8_t a, int16_t b, int32_t c, int64_t d) {
+  std::cout << "IntComputation(" << static_cast<int>(a) << ", " << b << ", "
+            << c << ", " << d << ")\n";
+  int64_t retval = d - c + b - a;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Performs some computation on various sized unsigned ints.
+// Used for testing value ranges for unsigned ints.
+DART_EXPORT int64_t UintComputation(uint8_t a,
+                                    uint16_t b,
+                                    uint32_t c,
+                                    uint64_t d) {
+  std::cout << "UintComputation(" << static_cast<int>(a) << ", " << b << ", "
+            << c << ", " << d << ")\n";
+  uint64_t retval = d - c + b - a;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Multiplies pointer sized int by three.
+// Used for testing pointer sized parameter and return value.
+DART_EXPORT intptr_t Times3(intptr_t a) {
+  std::cout << "Times3(" << a << ")\n";
+  intptr_t retval = a * 3;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Multiples a double by 1.337.
+// Used for testing double parameter and return value.
+// Also used for testing argument exception on passing null instead of a Dart
+// double.
+DART_EXPORT double Times1_337Double(double a) {
+  std::cout << "Times1_337Double(" << a << ")\n";
+  double retval = a * 1.337;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Multiples a float by 1.337.
+// Used for testing float parameter and return value.
+DART_EXPORT float Times1_337Float(float a) {
+  std::cout << "Times1_337Float(" << a << ")\n";
+  float retval = a * 1.337f;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Sums many ints.
+// Used for testing calling conventions. With so many doubles we are using all
+// normal parameter registers and some stack slots.
+DART_EXPORT intptr_t SumManyInts(intptr_t a,
+                                 intptr_t b,
+                                 intptr_t c,
+                                 intptr_t d,
+                                 intptr_t e,
+                                 intptr_t f,
+                                 intptr_t g,
+                                 intptr_t h,
+                                 intptr_t i,
+                                 intptr_t j) {
+  std::cout << "SumManyInts(" << a << ", " << b << ", " << c << ", " << d
+            << ", " << e << ", " << f << ", " << g << ", " << h << ", " << i
+            << ", " << j << ")\n";
+  intptr_t retval = a + b + c + d + e + f + g + h + i + j;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Sums many doubles.
+// Used for testing calling conventions. With so many doubles we are using all
+// xmm parameter registers and some stack slots.
+DART_EXPORT double SumManyDoubles(double a,
+                                  double b,
+                                  double c,
+                                  double d,
+                                  double e,
+                                  double f,
+                                  double g,
+                                  double h,
+                                  double i,
+                                  double j) {
+  std::cout << "SumManyDoubles(" << a << ", " << b << ", " << c << ", " << d
+            << ", " << e << ", " << f << ", " << g << ", " << h << ", " << i
+            << ", " << j << ")\n";
+  double retval = a + b + c + d + e + f + g + h + i + j;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Sums many numbers.
+// Used for testing calling conventions. With so many parameters we are using
+// both registers and stack slots.
+DART_EXPORT double SumManyNumbers(int a,
+                                  float b,
+                                  int c,
+                                  double d,
+                                  int e,
+                                  float f,
+                                  int g,
+                                  double h,
+                                  int i,
+                                  float j,
+                                  int k,
+                                  double l,
+                                  int m,
+                                  float n,
+                                  int o,
+                                  double p,
+                                  int q,
+                                  float r,
+                                  int s,
+                                  double t) {
+  std::cout << "SumManyNumbers(" << a << ", " << b << ", " << c << ", " << d
+            << ", " << e << ", " << f << ", " << g << ", " << h << ", " << i
+            << ", " << j << ", " << k << ", " << l << ", " << m << ", " << n
+            << ", " << o << ", " << p << ", " << q << ", " << r << ", " << s
+            << ", " << t << ")\n";
+  double retval = a + b + c + d + e + f + g + h + i + j + k + l + m + n + o +
+                  p + q + r + s + t;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Assigns 1337 to the second element and returns the address of that element.
+// Used for testing Pointer parameters and return values.
+DART_EXPORT int64_t* Assign1337Index1(int64_t* a) {
+  std::cout << "Assign1337Index1(" << a << ")\n";
+  std::cout << "val[0] = " << a[0] << "\n";
+  std::cout << "val[1] = " << a[1] << "\n";
+  a[1] = 1337;
+  std::cout << "val[1] = " << a[1] << "\n";
+  int64_t* retval = a + 1;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+struct Coord {
+  double x;
+  double y;
+  Coord* next;
+};
+
+// Transposes Coordinate by (10, 10) and returns next Coordinate.
+// Used for testing struct pointer parameter, struct pointer return value,
+// struct field access, and struct pointer field dereference.
+DART_EXPORT Coord* TransposeCoordinate(Coord* coord) {
+  std::cout << "TransposeCoordinate(" << coord << " {" << coord->x << ", "
+            << coord->y << ", " << coord->next << "})\n";
+  coord->x = coord->x + 10.0;
+  coord->y = coord->y + 10.0;
+  std::cout << "returning " << coord->next << "\n";
+  return coord->next;
+}
+
+// Takes a Coordinate array and returns a Coordinate pointer to the next
+// element.
+// Used for testing struct arrays.
+DART_EXPORT Coord* CoordinateElemAt1(Coord* coord) {
+  std::cout << "CoordinateElemAt1(" << coord << ")\n";
+  std::cout << "sizeof(Coord): " << sizeof(Coord) << "\n";
+  std::cout << "coord[0] = {" << coord[0].x << ", " << coord[0].y << ", "
+            << coord[0].next << "}\n";
+  std::cout << "coord[1] = {" << coord[1].x << ", " << coord[1].y << ", "
+            << coord[1].next << "}\n";
+  Coord* retval = coord + 1;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+typedef Coord* (*CoordUnOp)(Coord* coord);
+
+// Takes a Coordinate Function(Coordinate) and applies it three times to a
+// Coordinate.
+// Used for testing function pointers with structs.
+DART_EXPORT Coord* CoordinateUnOpTrice(CoordUnOp unop, Coord* coord) {
+  std::cout << "CoordinateUnOpTrice(" << unop << ", " << coord << ")\n";
+  Coord* retval = unop(unop(unop(coord)));
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+typedef intptr_t (*IntptrBinOp)(intptr_t a, intptr_t b);
+
+// Returns a closure.
+// Note this closure is not properly marked as DART_EXPORT or extern "C".
+// Used for testing passing a pointer to a closure to Dart.
+// TODO(dacoharkes): is this a supported use case?
+DART_EXPORT IntptrBinOp IntptrAdditionClosure() {
+  std::cout << "IntptrAdditionClosure()\n";
+  IntptrBinOp retval = [](intptr_t a, intptr_t b) { return a + b; };
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Applies an intptr binop function to 42 and 74.
+// Used for testing passing a function pointer to C.
+DART_EXPORT intptr_t ApplyTo42And74(IntptrBinOp binop) {
+  std::cout << "ApplyTo42And74()\n";
+  intptr_t retval = binop(42, 74);
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Returns next element in the array, unless a null pointer is passed.
+// When a null pointer is passed, a null pointer is returned.
+// Used for testing null pointers.
+DART_EXPORT int64_t* NullableInt64ElemAt1(int64_t* a) {
+  std::cout << "NullableInt64ElemAt1(" << a << ")\n";
+  int64_t* retval;
+  if (a) {
+    std::cout << "not null pointer, address: " << a << "\n";
+    retval = a + 1;
+  } else {
+    std::cout << "null pointer, address: " << a << "\n";
+    retval = nullptr;
+  }
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+struct VeryLargeStruct {
+  int8_t a;
+  int16_t b;
+  int32_t c;
+  int64_t d;
+  uint8_t e;
+  uint16_t f;
+  uint32_t g;
+  uint64_t h;
+  intptr_t i;
+  float j;
+  double k;
+  VeryLargeStruct* parent;
+  intptr_t numChildren;
+  VeryLargeStruct* children;
+  int8_t smallLastField;
+};
+
+// Sums the fields of a very large struct, including the first field (a) from
+// the parent and children.
+// Used for testing alignment and padding in structs.
+DART_EXPORT int64_t SumVeryLargeStruct(VeryLargeStruct* vls) {
+  std::cout << "SumVeryLargeStruct(" << vls << ")\n";
+  std::cout << "offsetof(a): " << offsetof(VeryLargeStruct, a) << "\n";
+  std::cout << "offsetof(b): " << offsetof(VeryLargeStruct, b) << "\n";
+  std::cout << "offsetof(c): " << offsetof(VeryLargeStruct, c) << "\n";
+  std::cout << "offsetof(d): " << offsetof(VeryLargeStruct, d) << "\n";
+  std::cout << "offsetof(e): " << offsetof(VeryLargeStruct, e) << "\n";
+  std::cout << "offsetof(f): " << offsetof(VeryLargeStruct, f) << "\n";
+  std::cout << "offsetof(g): " << offsetof(VeryLargeStruct, g) << "\n";
+  std::cout << "offsetof(h): " << offsetof(VeryLargeStruct, h) << "\n";
+  std::cout << "offsetof(i): " << offsetof(VeryLargeStruct, i) << "\n";
+  std::cout << "offsetof(j): " << offsetof(VeryLargeStruct, j) << "\n";
+  std::cout << "offsetof(k): " << offsetof(VeryLargeStruct, k) << "\n";
+  std::cout << "offsetof(parent): " << offsetof(VeryLargeStruct, parent)
+            << "\n";
+  std::cout << "offsetof(numChildren): "
+            << offsetof(VeryLargeStruct, numChildren) << "\n";
+  std::cout << "offsetof(children): " << offsetof(VeryLargeStruct, children)
+            << "\n";
+  std::cout << "offsetof(smallLastField): "
+            << offsetof(VeryLargeStruct, smallLastField) << "\n";
+  std::cout << "sizeof(VeryLargeStruct): " << sizeof(VeryLargeStruct) << "\n";
+
+  std::cout << "vls->a: " << static_cast<int>(vls->a) << "\n";
+  std::cout << "vls->b: " << vls->b << "\n";
+  std::cout << "vls->c: " << vls->c << "\n";
+  std::cout << "vls->d: " << vls->d << "\n";
+  std::cout << "vls->e: " << static_cast<int>(vls->e) << "\n";
+  std::cout << "vls->f: " << vls->f << "\n";
+  std::cout << "vls->g: " << vls->g << "\n";
+  std::cout << "vls->h: " << vls->h << "\n";
+  std::cout << "vls->i: " << vls->i << "\n";
+  std::cout << "vls->j: " << vls->j << "\n";
+  std::cout << "vls->k: " << vls->k << "\n";
+  std::cout << "vls->parent: " << vls->parent << "\n";
+  std::cout << "vls->numChildren: " << vls->numChildren << "\n";
+  std::cout << "vls->children: " << vls->children << "\n";
+  std::cout << "vls->smallLastField: " << static_cast<int>(vls->smallLastField)
+            << "\n";
+
+  int64_t retval = 0;
+  retval += 0x0L + vls->a;
+  retval += vls->b;
+  retval += vls->c;
+  retval += vls->d;
+  retval += vls->e;
+  retval += vls->f;
+  retval += vls->g;
+  retval += vls->h;
+  retval += vls->i;
+  retval += vls->j;
+  retval += vls->k;
+  retval += vls->smallLastField;
+  std::cout << retval << "\n";
+  if (vls->parent) {
+    std::cout << "has parent\n";
+    retval += vls->parent->a;
+  }
+  std::cout << "has " << vls->numChildren << " children\n";
+  for (int i = 0; i < vls->numChildren; i++) {
+    retval += vls->children[i].a;
+  }
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Sums numbers of various sizes.
+// Used for testing truncation and sign extension of non 64 bit parameters.
+DART_EXPORT int64_t SumSmallNumbers(int8_t a,
+                                    int16_t b,
+                                    int32_t c,
+                                    uint8_t d,
+                                    uint16_t e,
+                                    uint32_t f) {
+  std::cout << "SumSmallNumbers(" << static_cast<int>(a) << ", " << b << ", "
+            << c << ", " << static_cast<int>(d) << ", " << e << ", " << f
+            << ")\n";
+  int64_t retval = 0;
+  retval += a;
+  retval += b;
+  retval += c;
+  retval += d;
+  retval += e;
+  retval += f;
+  std::cout << "returning " << retval << "\n";
+  return retval;
+}
+
+// Checks whether the float is between 1336.0f and 1338.0f.
+// Used for testing rounding of Dart Doubles to floats in Pointer.store().
+DART_EXPORT uint8_t IsRoughly1337(float* a) {
+  std::cout << "IsRoughly1337(" << a[0] << ")\n";
+  uint8_t retval = (1336.0f < a[0] && a[0] < 1338.0f) ? 1 : 0;
+  std::cout << "returning " << static_cast<int>(retval) << "\n";
+  return retval;
+}
+
+}  // namespace dart
diff --git a/runtime/bin/gen_snapshot.cc b/runtime/bin/gen_snapshot.cc
index 3cb0462..c0656b7 100644
--- a/runtime/bin/gen_snapshot.cc
+++ b/runtime/bin/gen_snapshot.cc
@@ -71,7 +71,6 @@
 enum SnapshotKind {
   kCore,
   kCoreJIT,
-  kCoreJITAll,
   kApp,
   kAppJIT,
   kAppAOTBlobs,
@@ -99,7 +98,6 @@
     // clang-format off
     "core",
     "core-jit",
-    "core-jit-all",
     "app",
     "app-jit",
     "app-aot-blobs",
@@ -132,6 +130,8 @@
   V(save_obfuscation_map, obfuscation_map_filename)
 
 #define BOOL_OPTIONS_LIST(V)                                                   \
+  V(read_all_bytecode, read_all_bytecode)                                      \
+  V(compile_all, compile_all)                                                  \
   V(obfuscate, obfuscate)                                                      \
   V(verbose, verbose)                                                          \
   V(version, version)                                                          \
@@ -286,7 +286,6 @@
       }
       break;
     }
-    case kCoreJITAll:
     case kCoreJIT: {
       if ((vm_snapshot_data_filename == NULL) ||
           (vm_snapshot_instructions_filename == NULL) ||
@@ -461,7 +460,6 @@
         WriteDependenciesWithTarget(isolate_snapshot_data_filename);
         // WriteDependenciesWithTarget(isolate_snapshot_instructions_filename);
         break;
-      case kCoreJITAll:
       case kCoreJIT:
         WriteDependenciesWithTarget(vm_snapshot_data_filename);
         // WriteDependenciesWithTarget(vm_snapshot_instructions_filename);
@@ -550,16 +548,20 @@
   dependencies->Clear();
 }
 
-static void LoadBytecode() {
-  if ((Dart_IsVMFlagSet("enable_interpreter") ||
-       Dart_IsVMFlagSet("use_bytecode_compiler")) &&
-      ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+static void MaybeLoadCode() {
+  if (read_all_bytecode &&
+      ((snapshot_kind == kCore) || (snapshot_kind == kCoreJIT) ||
+       (snapshot_kind == kApp) || (snapshot_kind == kAppJIT))) {
     Dart_Handle result = Dart_ReadAllBytecode();
     CHECK_RESULT(result);
   }
-}
 
-static void LoadCompilationTrace() {
+  if (compile_all &&
+      ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
+    Dart_Handle result = Dart_CompileAll();
+    CHECK_RESULT(result);
+  }
+
   if ((load_compilation_trace_filename != NULL) &&
       ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
     uint8_t* buffer = NULL;
@@ -568,6 +570,7 @@
     Dart_Handle result = Dart_LoadCompilationTrace(buffer, size);
     CHECK_RESULT(result);
   }
+
   if ((load_type_feedback_filename != NULL) &&
       ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT))) {
     uint8_t* buffer = NULL;
@@ -578,13 +581,6 @@
   }
 }
 
-static void CompileAll() {
-  if (snapshot_kind == kCoreJITAll) {
-    Dart_Handle result = Dart_CompileAll();
-    CHECK_RESULT(result);
-  }
-}
-
 static void CreateAndWriteCoreSnapshot() {
   ASSERT(snapshot_kind == kCore);
   ASSERT(vm_snapshot_data_filename != NULL);
@@ -645,7 +641,7 @@
 }
 
 static void CreateAndWriteCoreJITSnapshot() {
-  ASSERT((snapshot_kind == kCoreJIT) || (snapshot_kind == kCoreJITAll));
+  ASSERT(snapshot_kind == kCoreJIT);
   ASSERT(vm_snapshot_data_filename != NULL);
   ASSERT(vm_snapshot_instructions_filename != NULL);
   ASSERT(isolate_snapshot_data_filename != NULL);
@@ -909,6 +905,8 @@
       Dart_LoadLibraryFromKernel(kernel_buffer, kernel_buffer_size));
   CHECK_RESULT(result);
 
+  MaybeLoadCode();
+
   switch (snapshot_kind) {
     case kAppAOTBlobs:
     case kAppAOTAssembly: {
@@ -927,21 +925,13 @@
     case kCore:
       CreateAndWriteCoreSnapshot();
       break;
-    case kCoreJITAll:
-      CompileAll();
-      CreateAndWriteCoreJITSnapshot();
-      break;
     case kCoreJIT:
-      LoadBytecode();
-      LoadCompilationTrace();
       CreateAndWriteCoreJITSnapshot();
       break;
     case kApp:
       CreateAndWriteAppSnapshot();
       break;
     case kAppJIT:
-      LoadBytecode();
-      LoadCompilationTrace();
       CreateAndWriteAppJITSnapshot();
       break;
     case kVMAOTAssembly: {
@@ -1019,8 +1009,7 @@
 
   if (IsSnapshottingForPrecompilation()) {
     vm_options.AddArgument("--precompilation");
-  } else if ((snapshot_kind == kCoreJITAll) || (snapshot_kind == kCoreJIT) ||
-             (snapshot_kind == kAppJIT)) {
+  } else if ((snapshot_kind == kCoreJIT) || (snapshot_kind == kAppJIT)) {
     vm_options.AddArgument("--fields_may_be_reset");
 #if !defined(TARGET_ARCH_IA32)
     vm_options.AddArgument("--link_natives_lazily");
diff --git a/runtime/bin/main.cc b/runtime/bin/main.cc
index cb1dd8d..301b3ee 100644
--- a/runtime/bin/main.cc
+++ b/runtime/bin/main.cc
@@ -38,8 +38,6 @@
 #include "platform/hashmap.h"
 #include "platform/text_buffer.h"
 
-#include "vm/flags.h"
-
 extern "C" {
 extern const uint8_t kDartVmSnapshotData[];
 extern const uint8_t kDartVmSnapshotInstructions[];
@@ -228,7 +226,7 @@
   result = DartUtils::PrepareForScriptLoading(false, Options::trace_loading());
   CHECK_RESULT(result);
 
-  if (FLAG_support_service || !kDartPrecompiledRuntime) {
+  if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
     // Set up the load port provided by the service isolate so that we can
     // load scripts.
     result = DartUtils::SetupServiceLoadPort();
@@ -307,7 +305,7 @@
     result = DartUtils::SetupIOLibrary(namespc, script_uri,
                                        Options::exit_disabled());
     CHECK_RESULT(result);
-    if (FLAG_support_service || !kDartPrecompiledRuntime) {
+    if (Dart_IsVMFlagSet("support_service") || !Dart_IsPrecompiledRuntime()) {
       Loader::InitForSnapshot(script_uri);
     }
 #if !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/docs/compiler/optimization_levels.md b/runtime/docs/compiler/optimization_levels.md
new file mode 100644
index 0000000..c86976b
--- /dev/null
+++ b/runtime/docs/compiler/optimization_levels.md
@@ -0,0 +1,63 @@
+# Dart MiniDesign Doc
+
+## Optimization Levels for AOT Dart Compiler
+
+# Introduction
+
+In order to strike the right balance between compile-time, code speed, and code size, most optimizing compilers support several levels of optimizations, typically controlled by an -Ox switch. The usual ones relevant to this design code are:
+
+*   O0: short compilation-time, unoptimized code, small code size; highly debuggable
+*   O2: medium compilation-time, optimized code, reasonable code size
+*   O3: potentially long compilation-time, highly optimized code, possibly larger code size
+*   Os: medium compilation-time, optimized while favoring code size
+
+The O0 level is typically used during development and early testing, when a very fast compilation-time is more desirable than code speed. Also, this code is best for debugging, since unoptimized code has a very straightforward mapping between native instructions and memory locations and source program instructions and variables.
+
+The O2 level is used to generate code for shipping. It strikes a right balance between compile-time and generated code speed and size. Since shipping occurs less frequently than debugging and testing, slightly longer compilation-times are acceptable.
+
+When either code speed or size is favored, respectively, levels O3 or Os are used. For the former, longer compilation-times are acceptable as well.
+
+The Dart compiler conceptually only supports level O0 (the un-optimized code that is used as our deopt "fallback") and level O2 (optimized code). Although the quality of optimization can heavily depend on profile feedback (JIT) and the possibility for speculative execution, both JIT and AOT strike more or less the same balance between generated code speed and size.
+
+# Proposal
+
+Some optimizations are known to benefit mostly code speed (with an unfavorable or unknown impact on code size) or mostly code size (with an unfavorable or unknown impact on code speed). For example, more aggressively inlining (to a certain extent) usually yields faster but more sizable code. Conversely, not aligning code (where allowed) usually yields more compact, but potentially slower running code.
+
+Sometimes performing more expensive analysis, which negatively impacts compile-time, may discover more optimization opportunities in some cases, but remain completely empty handed in other cases. For example, doing an expensive data dependence analysis of loops only pays of if the loop is eventually vectorized or parallelized. Otherwise, all analysis time is wasted.
+
+Note that almost every optimization decision_ is heuristic in nature_; optimizations generally improve a certain aspect of the code, but there are no hard guarantees.
+
+Since Dart conceptually only supports O2, _all_ optimizations must always be chosen to strike a balance between compile-time and generated code speed and size. In order to give users more control over the optimization decision when using the Dart compiler, we propose adding the concept of Os and O3 as additional compilation modes. This could be implemented as an optimization level, for example as:
+
+```
+--optimization_level=
+       0: unoptimized (O0)
+       1: size optimized (Os)
+       2: default optimized (O2)
+       3: speed optimized (O3)
+```
+
+Level 0 corresponds to our current unoptimized path, whereas level 2 corresponds to the default path through our optimization passes. The other two levels alter the default path using the following guidelines.
+
+*   optimization_level=1 (Os)
+    *   Skip O2 optimizations that tend to increase code size, even if doing so may negatively impacts code speed
+    *   Introduce new optimizations that "heuristically" decrease code size, but at high risk of negatively impacting code speed
+*   optimization_level=3 (O3)
+    *   Introduce more detailed analysis or optimizations that "heuristically" increase code speed, but at high risk of negatively impacting compile-time or code size
+
+The guidelines are intentionally worded this way to avoid reckless use of the flag as a substitute for proper heuristics. For example, an optimization aimed at reducing code size with a neutral impact on code speed belongs in O2, not Os. As another example, always inlining without proper heuristics just in the hope to improve speed by blindly giving up size is not something we want in O3. Also, inlining heuristics that overall increase code speed with only minimal code size increase belongs in O2.
+
+The proposal would apply to both the JIT and AOT compiler (to avoid adding yet another dimension through the optimization passes), although initially we may only want to expose the switch externally for the AOT compiler.
+
+Advantages of approach:
+
+*   Allows new optimizations for size or speed that don't fit the current O2 philosophy
+*   Enables removal of existing optimization from O2 that had a disproportionate negative impact on only size
+*   Allows introduction of more expensive analysis that can (but is not guaranteed to) find more opportunities for optimization
+*   Gives more control to users that favor size or speed differently than others
+*   Potentially gives more insights on optimizations that were initially deemed to risky but helped "in the field"; perhaps better heuristics can be found to move these to O2
+
+Disadvantages of the approach:
+
+*   Two additional code paths through compiler, increases the size of all testing matrices (Dart, Flutter, performance, correctness)
+*   Risk of misusing the flag to avoid spending time finding better heuristics
diff --git a/runtime/include/dart_tools_api.h b/runtime/include/dart_tools_api.h
index 49b1f19..402e01d 100644
--- a/runtime/include/dart_tools_api.h
+++ b/runtime/include/dart_tools_api.h
@@ -344,58 +344,6 @@
 DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask);
 
 typedef enum {
-  /** Indicates a new stream is being output */
-  Dart_StreamConsumer_kStart = 0,
-  /** Data for the current stream */
-  Dart_StreamConsumer_kData = 1,
-  /** Indicates stream is finished */
-  Dart_StreamConsumer_kFinish = 2,
-} Dart_StreamConsumer_State;
-
-/**
- * A stream consumer callback function.
- *
- * This function will be called repeatedly until there is no more data in a
- * stream and there are no more streams.
- *
- * \param state Indicates a new stream, data, or a finished stream.
- * \param stream_name A name for this stream. Not guaranteed to be meaningful.
- * \param buffer A pointer to the stream data.
- * \param buffer_length The number of bytes at buffer that should be consumed.
- * \param stream_callback_data The pointer passed in when requesting the stream.
- *
- * At the start of each stream state will be DART_STREAM_CONSUMER_STATE_START
- * and buffer will be NULL.
- *
- * For each chunk of data the state will be DART_STREAM_CONSUMER_STATE_DATA
- * and buffer will not be NULL.
- *
- * At the end of each stream state will be DART_STREAM_CONSUMER_STATE_FINISH
- * and buffer will be NULL.
- */
-typedef void (*Dart_StreamConsumer)(Dart_StreamConsumer_State state,
-                                    const char* stream_name,
-                                    const uint8_t* buffer,
-                                    intptr_t buffer_length,
-                                    void* stream_callback_data);
-
-/**
- * Get the timeline for entire VM (including all isolates).
- *
- * NOTE: The timeline retrieved from this API call may not include the most
- * recent events.
- *
- * \param consumer A Dart_StreamConsumer.
- * \param user_data User data passed into consumer.
- *
- * NOTE: The trace-event format is documented here: https://goo.gl/hDZw5M
- *
- * \return True if a stream was output.
- */
-DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
-                                             void* user_data);
-
-typedef enum {
   Dart_Timeline_Event_Begin,          // Phase = 'B'.
   Dart_Timeline_Event_End,            // Phase = 'E'.
   Dart_Timeline_Event_Instant,        // Phase = 'i'.
@@ -436,31 +384,6 @@
  */
 DART_EXPORT void Dart_SetThreadName(const char* name);
 
-/**
- * Called by the VM to let the embedder know when to start recording into the
- * timeline. Can be called from any thread.
- */
-typedef void (*Dart_EmbedderTimelineStartRecording)();
-
-/**
- * Called by the VM to let the embedder know when to stop recording into the
- * timeline. Can be called from any thread.
- */
-typedef void (*Dart_EmbedderTimelineStopRecording)();
-
-/**
- * Sets the embedder timeline callbacks. These callbacks are used by the VM
- * to notify the embedder of timeline recording state changes.
- *
- * \param start_recording See Dart_EmbedderTimelineStartRecording.
- * \param stop_recording See Dart_EmbedderTimelineStopRecording.
- *
- * NOTE: To avoid races, this should be called before Dart_Initialize.
- */
-DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
-    Dart_EmbedderTimelineStartRecording start_recording,
-    Dart_EmbedderTimelineStopRecording stop_recording);
-
 /*
  * =======
  * Metrics
diff --git a/runtime/lib/convert_patch.dart b/runtime/lib/convert_patch.dart
index 3d99c0d..7342f87 100644
--- a/runtime/lib/convert_patch.dart
+++ b/runtime/lib/convert_patch.dart
@@ -261,7 +261,7 @@
   // TODO(lrn): See if parsing of numbers can be abstracted to something
   // not only working on strings, but also on char-code lists, without lossing
   // performance.
-  int parseInt() => int.parse(getString());
+  num parseNum() => num.parse(getString());
   double parseDouble() => double.parse(getString());
 }
 
@@ -598,13 +598,17 @@
   String getString(int start, int end, int bits);
 
   /**
-   * Parse a slice of the current chunk as an integer.
+   * Parse a slice of the current chunk as a number.
+   *
+   * Since integers have a maximal value, and we don't track the value
+   * in the buffer, a sequence of digits can be either an int or a double.
+   * The `num.parse` function does the right thing.
    *
    * The format is expected to be correct.
    */
-  int parseInt(int start, int end) {
-    const int asciiBits = 0x7f; // Integer literals are ASCII only.
-    return int.parse(getString(start, end, asciiBits));
+  num parseNum(int start, int end) {
+    const int asciiBits = 0x7f; // Number literals are ASCII only.
+    return num.parse(getString(start, end, asciiBits));
   }
 
   /**
@@ -917,7 +921,6 @@
         default:
           if ((state & ALLOW_VALUE_MASK) != 0) fail(position);
           state |= VALUE_READ_BITS;
-          if (char == null) print("$chunk - $position");
           position = parseNumber(char, position);
           break;
       }
@@ -1214,7 +1217,8 @@
       addNumberChunk(buffer, start, end, 0);
     }
     if (state == NUM_DIGIT) {
-      listener.handleNumber(buffer.parseInt());
+      num value = buffer.parseNum();
+      listener.handleNumber(value);
     } else if (state == NUM_DOT_DIGIT || state == NUM_E_DIGIT) {
       listener.handleNumber(buffer.parseDouble());
     } else {
@@ -1230,9 +1234,11 @@
     int start = position;
     int length = chunkEnd;
     // Collects an int value while parsing. Used for both an integer literal,
-    // an the exponent part of a double literal.
+    // and the exponent part of a double literal.
+    // Stored as negative to ensure we can represent -2^63.
     int intValue = 0;
     double doubleValue = 0.0; // Collect double value while parsing.
+    // 1 if there is no leading -, -1 if there is.
     int sign = 1;
     bool isDouble = false;
     // Break this block when the end of the number literal is reached.
@@ -1261,8 +1267,22 @@
       // If starting with zero, next character must not be digit.
       if (digit <= 9) fail(position);
     } else {
+      int digitCount = 0;
       do {
-        intValue = 10 * intValue + digit;
+        if (digitCount >= 18) {
+          // Check for overflow.
+          // Is 1 if digit is 8 or 9 and sign == 0, or digit is 9 and sign < 0;
+          int highDigit = digit >> 3;
+          if (sign < 0) highDigit &= digit;
+          if (digitCount == 19 || intValue - highDigit < -922337203685477580) {
+            isDouble = true;
+            // Big value that we know is not trusted to be exact later,
+            // forcing reparsing using `double.parse`.
+            doubleValue = 9223372036854775808.0;
+          }
+        }
+        intValue = 10 * intValue - digit;
+        digitCount++;
         position++;
         if (position == length) return beginChunkNumber(NUM_DIGIT, start);
         char = getChar(position);
@@ -1270,8 +1290,10 @@
       } while (digit <= 9);
     }
     if (char == DECIMALPOINT) {
-      isDouble = true;
-      doubleValue = intValue.toDouble();
+      if (!isDouble) {
+        isDouble = true;
+        doubleValue = (intValue == 0) ? 0.0 : -intValue.toDouble();
+      }
       intValue = 0;
       position++;
       if (position == length) return beginChunkNumber(NUM_DOT, start);
@@ -1289,16 +1311,16 @@
     }
     if ((char | 0x20) == CHAR_e) {
       if (!isDouble) {
-        doubleValue = intValue.toDouble();
-        intValue = 0;
         isDouble = true;
+        doubleValue = (intValue == 0) ? 0.0 : -intValue.toDouble();
+        intValue = 0;
       }
       position++;
       if (position == length) return beginChunkNumber(NUM_E, start);
       char = getChar(position);
       int expSign = 1;
       int exponent = 0;
-      if (char == PLUS || char == MINUS) {
+      if (((char + 1) | 2) == 0x2e /*+ or -*/) {
         expSign = 0x2C - char; // -1 for MINUS, +1 for PLUS
         position++;
         if (position == length) return beginChunkNumber(NUM_E_SIGN, start);
@@ -1308,20 +1330,33 @@
       if (digit > 9) {
         fail(position, "Missing expected digit");
       }
+      bool exponentOverflow = false;
       do {
         exponent = 10 * exponent + digit;
+        if (exponent > 400) exponentOverflow = true;
         position++;
         if (position == length) return beginChunkNumber(NUM_E_DIGIT, start);
         char = getChar(position);
         digit = char ^ CHAR_0;
       } while (digit <= 9);
+      if (exponentOverflow) {
+        if (doubleValue == 0.0 || expSign < 0) {
+          listener.handleNumber(sign < 0 ? -0.0 : 0.0);
+        } else {
+          listener.handleNumber(
+              sign < 0 ? double.negativeInfinity : double.infinity);
+        }
+        return position;
+      }
       intValue += expSign * exponent;
     }
     if (!isDouble) {
-      listener.handleNumber(sign * intValue);
+      int bitFlag = -(sign + 1) >> 1; // 0 if sign == -1, -1 if sign == 1
+      // Negate if bitFlag is -1 by doing ~intValue + 1
+      listener.handleNumber((intValue ^ bitFlag) - bitFlag);
       return position;
     }
-    // Double values at or above this value (2 ** 53) may have lost precission.
+    // Double values at or above this value (2 ** 53) may have lost precision.
     // Only trust results that are below this value.
     const double maxExactDouble = 9007199254740992.0;
     if (doubleValue < maxExactDouble) {
diff --git a/runtime/lib/ffi.cc b/runtime/lib/ffi.cc
new file mode 100644
index 0000000..0621990
--- /dev/null
+++ b/runtime/lib/ffi.cc
@@ -0,0 +1,680 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 "include/dart_api.h"
+#include "vm/bootstrap_natives.h"
+#include "vm/class_finalizer.h"
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/exceptions.h"
+#include "vm/log.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
+#include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/symbols.h"
+
+namespace dart {
+
+// The following functions are runtime checks on type arguments.
+// Some checks are also performed in kernel transformation, these are asserts.
+// Some checks are only performed at runtime to allow for generic code, these
+// throw ArgumentExceptions.
+
+static void ThrowTypeArgumentError(const AbstractType& type_arg,
+                                   const char* expected) {
+  const String& error = String::Handle(String::NewFormatted(
+      "Type argument (%s) should be a %s",
+      String::Handle(type_arg.UserVisibleName()).ToCString(), expected));
+  Exceptions::ThrowArgumentError(error);
+}
+
+static bool IsPointerType(const AbstractType& type) {
+  // Do a fast check for predefined types.
+  classid_t type_cid = type.type_class_id();
+  if (RawObject::IsFfiPointerClassId(type_cid)) {
+    return true;
+  }
+
+  // Do a slow check for subtyping.
+  const Class& pointer_class =
+      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);
+  ASSERT(pointer_type.IsInstantiated());
+  ASSERT(type.IsInstantiated());
+  return type.IsSubtypeOf(pointer_type, Heap::kNew);
+}
+
+static bool IsConcreteNativeType(const AbstractType& type) {
+  // Do a fast check for predefined types.
+  classid_t type_cid = type.type_class_id();
+  if (RawObject::IsFfiNativeTypeTypeClassId(type_cid)) {
+    return false;
+  }
+  if (RawObject::IsFfiTypeClassId(type_cid)) {
+    return true;
+  }
+
+  // Do a slow check for subtyping.
+  const Class& native_type_class = Class::Handle(
+      Isolate::Current()->object_store()->ffi_native_type_class());
+  AbstractType& native_type_type =
+      AbstractType::Handle(native_type_class.DeclarationType());
+  return type.IsSubtypeOf(native_type_type, Heap::kNew);
+}
+
+static void CheckIsConcreteNativeType(const AbstractType& type) {
+  if (!IsConcreteNativeType(type)) {
+    ThrowTypeArgumentError(type, "concrete sub type of NativeType");
+  }
+}
+
+static bool IsNativeFunction(const AbstractType& type_arg) {
+  classid_t type_cid = type_arg.type_class_id();
+  return RawObject::IsFfiTypeNativeFunctionClassId(type_cid);
+}
+
+static void CheckSized(const AbstractType& type_arg) {
+  classid_t type_cid = type_arg.type_class_id();
+  if (RawObject::IsFfiTypeVoidClassId(type_cid) ||
+      RawObject::IsFfiTypeNativeFunctionClassId(type_cid)) {
+    const String& error = String::Handle(String::NewFormatted(
+        "%s does not have a predefined size (@unsized). "
+        "Unsized NativeTypes do not support [sizeOf] because their size "
+        "is unknown. "
+        "Consequently, [allocate], [Pointer.load], [Pointer.store], and "
+        "[Pointer.elementAt] are not available.",
+        String::Handle(type_arg.UserVisibleName()).ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+}
+
+// Checks that a dart type correspond to a [NativeType].
+// Because this is checked already in a kernel transformation, it does not throw
+// an ArgumentException but a boolean which should be asserted.
+//
+// [Int8]                               -> [int]
+// [Int16]                              -> [int]
+// [Int32]                              -> [int]
+// [Int64]                              -> [int]
+// [Uint8]                              -> [int]
+// [Uint16]                             -> [int]
+// [Uint32]                             -> [int]
+// [Uint64]                             -> [int]
+// [IntPtr]                             -> [int]
+// [Double]                             -> [double]
+// [Float]                              -> [double]
+// [Pointer]<T>                         -> [Pointer]<T>
+// T extends [Pointer]                  -> T
+// [NativeFunction]<T1 Function(T2, T3) -> S1 Function(S2, S3)
+//    where DartRepresentationOf(Tn) -> Sn
+static bool DartAndCTypeCorrespond(const AbstractType& native_type,
+                                   const AbstractType& dart_type) {
+  classid_t native_type_cid = native_type.type_class_id();
+  if (RawObject::IsFfiTypeIntClassId(native_type_cid)) {
+    return dart_type.IsSubtypeOf(AbstractType::Handle(Type::IntType()),
+                                 Heap::kNew);
+  }
+  if (RawObject::IsFfiTypeDoubleClassId(native_type_cid)) {
+    return dart_type.IsSubtypeOf(AbstractType::Handle(Type::Double()),
+                                 Heap::kNew);
+  }
+  if (RawObject::IsFfiPointerClassId(native_type_cid)) {
+    return native_type.Equals(dart_type) || dart_type.IsNullType();
+  }
+  if (RawObject::IsFfiTypeNativeFunctionClassId(native_type_cid)) {
+    if (!dart_type.IsFunctionType()) {
+      return false;
+    }
+    TypeArguments& nativefunction_type_args =
+        TypeArguments::Handle(native_type.arguments());
+    AbstractType& nativefunction_type_arg =
+        AbstractType::Handle(nativefunction_type_args.TypeAt(0));
+    if (!nativefunction_type_arg.IsFunctionType()) {
+      return false;
+    }
+    Function& dart_function = Function::Handle(((Type&)dart_type).signature());
+    if (dart_function.NumTypeParameters() != 0 ||
+        dart_function.HasOptionalPositionalParameters() ||
+        dart_function.HasOptionalNamedParameters()) {
+      return false;
+    }
+    Function& nativefunction_function =
+        Function::Handle(((Type&)nativefunction_type_arg).signature());
+    if (nativefunction_function.NumTypeParameters() != 0 ||
+        nativefunction_function.HasOptionalPositionalParameters() ||
+        nativefunction_function.HasOptionalNamedParameters()) {
+      return false;
+    }
+    if (!(dart_function.NumParameters() ==
+          nativefunction_function.NumParameters())) {
+      return false;
+    }
+    if (!DartAndCTypeCorrespond(
+            AbstractType::Handle(nativefunction_function.result_type()),
+            AbstractType::Handle(dart_function.result_type()))) {
+      return false;
+    }
+    for (intptr_t i = 0; i < dart_function.NumParameters(); i++) {
+      if (!DartAndCTypeCorrespond(
+              AbstractType::Handle(nativefunction_function.ParameterTypeAt(i)),
+              AbstractType::Handle(dart_function.ParameterTypeAt(i)))) {
+        return false;
+      }
+    }
+  }
+  return true;
+}
+
+// The following functions are runtime checks on arguments.
+
+// Note that expected_from and expected_to are inclusive.
+static void CheckRange(const Integer& argument_value,
+                       intptr_t expected_from,
+                       intptr_t expected_to,
+                       const char* argument_name) {
+  int64_t value = argument_value.AsInt64Value();
+  if (value < expected_from || expected_to < value) {
+    Exceptions::ThrowRangeError(argument_name, argument_value, expected_from,
+                                expected_to);
+  }
+}
+
+static const Pointer& AsPointer(const Instance& instance) {
+  if (!instance.IsPointer()) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Expected a Pointer object but found %s", instance.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+  return Pointer::Cast(instance);
+}
+
+static const Integer& AsInteger(const Instance& instance) {
+  if (!instance.IsInteger()) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Expected an int but found %s", instance.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+  return Integer::Cast(instance);
+}
+
+static const Double& AsDouble(const Instance& instance) {
+  if (!instance.IsDouble()) {
+    const String& error = String::Handle(String::NewFormatted(
+        "Expected a double but found %s", instance.ToCString()));
+    Exceptions::ThrowArgumentError(error);
+  }
+  return Double::Cast(instance);
+}
+
+// Native data types sizes in bytes
+
+static const size_t kSizeUnknown = 0;
+
+static const intptr_t kNumElementSizes = kFfiVoidCid - kFfiPointerCid + 1;
+
+static const size_t element_size_table[kNumElementSizes] = {
+    sizeof(intptr_t),  // kFfiPointerCid
+    kSizeUnknown,      // kFfiNativeFunctionCid
+    1,                 // kFfiInt8Cid
+    2,                 // kFfiInt16Cid
+    4,                 // kFfiInt32Cid
+    8,                 // kFfiInt64Cid
+    1,                 // kFfiUint8Cid
+    2,                 // kFfiUint16Cid
+    4,                 // kFfiUint32Cid
+    8,                 // kFfiUint64Cid
+    sizeof(intptr_t),  // kFfiIntPtrCid
+    4,                 // kFfiFloatCid
+    8,                 // kFfiDoubleCid
+    kSizeUnknown,      // kFfiVoidCid
+};
+
+static size_t ElementSizeInBytes(intptr_t class_id) {
+  ASSERT(RawObject::IsFfiTypeClassId(class_id));
+  ASSERT(class_id != kFfiNativeFunctionCid);
+  ASSERT(class_id != kFfiVoidCid);
+  intptr_t index = class_id - kFfiPointerCid;
+  return element_size_table[index];
+}
+
+// The remainder of this file implements the dart:ffi native methods.
+
+DEFINE_NATIVE_ENTRY(Ffi_allocate, 1, 1) {
+  // TODO(dacoharkes): When we have a way of determining the size of structs in
+  // the VM, change the signature so we can allocate structs, subtype of
+  // Pointer. https://github.com/dart-lang/sdk/issues/35782
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+
+  CheckIsConcreteNativeType(type_arg);
+  CheckSized(type_arg);
+
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, argCount, arguments->NativeArgAt(0));
+  int64_t count = argCount.AsInt64Value();
+  classid_t type_cid = type_arg.type_class_id();
+  int64_t max_count = INTPTR_MAX / ElementSizeInBytes(type_cid);
+  CheckRange(argCount, 1, max_count, "count");
+
+  size_t size = ElementSizeInBytes(type_cid) * count;
+  uint8_t* memory = reinterpret_cast<uint8_t*>(malloc(size));
+  if (memory == NULL) {
+    const String& error = String::Handle(String::NewFormatted(
+        "allocating (%" Pd ") bytes of memory failed", size));
+    Exceptions::ThrowArgumentError(error);
+  }
+
+  RawPointer* result = Pointer::New(type_arg, memory);
+  return result;
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_fromAddress, 1, 1) {
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  TypeArguments& type_args = TypeArguments::Handle(type_arg.arguments());
+  AbstractType& native_type = AbstractType::Handle(
+      type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos));
+  CheckIsConcreteNativeType(native_type);
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, arg_ptr, arguments->NativeArgAt(0));
+
+  uint8_t* address = reinterpret_cast<uint8_t*>(arg_ptr.AsInt64Value());
+  // TODO(dacoharkes): should this return NULL if addres is 0?
+  // https://github.com/dart-lang/sdk/issues/35756
+
+  RawPointer* result =
+      Pointer::New(native_type, address, type_arg.type_class_id());
+  return result;
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_elementAt, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, index, arguments->NativeArgAt(1));
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+  CheckSized(pointer_type_arg);
+
+  classid_t class_id = pointer_type_arg.type_class_id();
+  uint8_t* address = pointer.GetCMemoryAddress();
+  uint8_t* address_new =
+      address + index.AsInt64Value() * ElementSizeInBytes(class_id);
+  RawPointer* result = Pointer::New(pointer_type_arg, address_new);
+  return result;
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_offsetBy, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Integer, offset, arguments->NativeArgAt(1));
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+
+  uint8_t* address = pointer.GetCMemoryAddress();
+  uint8_t* address_new = address + offset.AsInt64Value();
+  RawPointer* result = Pointer::New(pointer_type_arg, address_new);
+  return result;
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_cast, 1, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  TypeArguments& type_args = TypeArguments::Handle(type_arg.arguments());
+  AbstractType& native_type = AbstractType::Handle(
+      type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos));
+  CheckIsConcreteNativeType(native_type);
+
+  uint8_t* address = pointer.GetCMemoryAddress();
+  RawPointer* result =
+      Pointer::New(native_type, address, type_arg.type_class_id());
+  return result;
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_free, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+
+  uint8_t* address = pointer.GetCMemoryAddress();
+  free(address);
+  pointer.SetCMemoryAddress(0);
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_address, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+
+  uint8_t* address = pointer.GetCMemoryAddress();
+  intptr_t int_ptr = reinterpret_cast<intptr_t>(address);
+  return Integer::NewFromUint64(int_ptr);
+}
+
+static RawInstance* BoxLoadPointer(uint8_t* address,
+                                   const AbstractType& instance_type_arg,
+                                   intptr_t type_cid) {
+  // TODO(dacoharkes): should this return NULL if addres is 0?
+  // https://github.com/dart-lang/sdk/issues/35756
+  if (address == 0) {  // 0 is the c++ null pointer
+    return Instance::null();
+  }
+  AbstractType& type_arg =
+      AbstractType::Handle(TypeArguments::Handle(instance_type_arg.arguments())
+                               .TypeAt(Pointer::kNativeTypeArgPos));
+  return Pointer::New(type_arg, address, type_cid);
+}
+
+static RawInstance* LoadValue(uint8_t* address,
+                              const AbstractType& instance_type_arg) {
+  classid_t type_cid = instance_type_arg.type_class_id();
+  switch (type_cid) {
+    case kFfiInt8Cid:
+      return Integer::New(*reinterpret_cast<int8_t*>(address));
+    case kFfiInt16Cid:
+      return Integer::New(*reinterpret_cast<int16_t*>(address));
+    case kFfiInt32Cid:
+      return Integer::New(*reinterpret_cast<int32_t*>(address));
+    case kFfiInt64Cid:
+      return Integer::New(*reinterpret_cast<int64_t*>(address));
+    case kFfiUint8Cid:
+      return Integer::NewFromUint64(*reinterpret_cast<uint8_t*>(address));
+    case kFfiUint16Cid:
+      return Integer::NewFromUint64(*reinterpret_cast<uint16_t*>(address));
+    case kFfiUint32Cid:
+      return Integer::NewFromUint64(*reinterpret_cast<uint32_t*>(address));
+    case kFfiUint64Cid:
+      return Integer::NewFromUint64(*reinterpret_cast<uint64_t*>(address));
+    case kFfiIntPtrCid:
+      return Integer::New(*reinterpret_cast<intptr_t*>(address));
+    case kFfiFloatCid:
+      return Double::New(*reinterpret_cast<float_t*>(address));
+    case kFfiDoubleCid:
+      return Double::New(*reinterpret_cast<double_t*>(address));
+    case kFfiPointerCid:
+    default:
+      ASSERT(IsPointerType(instance_type_arg));
+      return BoxLoadPointer(*reinterpret_cast<uint8_t**>(address),
+                            instance_type_arg, type_cid);
+  }
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_load, 1, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+  CheckSized(pointer_type_arg);
+  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, type_arg));
+
+  uint8_t* address = pointer.GetCMemoryAddress();
+  return LoadValue(address, pointer_type_arg);
+}
+
+static void StoreValue(const Pointer& pointer,
+                       classid_t type_cid,
+                       const Instance& new_value) {
+  uint8_t* address = pointer.GetCMemoryAddress();
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+  switch (type_cid) {
+    case kFfiInt8Cid:
+      *reinterpret_cast<int8_t*>(address) = AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiInt16Cid:
+      *reinterpret_cast<int16_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiInt32Cid:
+      *reinterpret_cast<int32_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiInt64Cid:
+      *reinterpret_cast<int64_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiUint8Cid:
+      *reinterpret_cast<uint8_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiUint16Cid:
+      *reinterpret_cast<uint16_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiUint32Cid:
+      *reinterpret_cast<uint32_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiUint64Cid:
+      *reinterpret_cast<uint64_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiIntPtrCid:
+      *reinterpret_cast<intptr_t*>(address) =
+          AsInteger(new_value).AsInt64Value();
+      break;
+    case kFfiFloatCid:
+      *reinterpret_cast<float*>(address) = AsDouble(new_value).value();
+      break;
+    case kFfiDoubleCid:
+      *reinterpret_cast<double*>(address) = AsDouble(new_value).value();
+      break;
+    case kFfiPointerCid:
+    default: {
+      ASSERT(IsPointerType(pointer_type_arg));
+      uint8_t* new_value_unwrapped = nullptr;
+      if (!new_value.IsNull()) {
+        ASSERT(new_value.IsPointer());
+        new_value_unwrapped = AsPointer(new_value).GetCMemoryAddress();
+        // TODO(dacoharkes): should this return NULL if addres is 0?
+        // https://github.com/dart-lang/sdk/issues/35756
+      }
+      *reinterpret_cast<uint8_t**>(address) = new_value_unwrapped;
+    } break;
+  }
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_store, 0, 2) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  GET_NATIVE_ARGUMENT(Instance, new_value, arguments->NativeArgAt(1));
+  AbstractType& arg_type = AbstractType::Handle(new_value.GetType(Heap::kNew));
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+  CheckSized(pointer_type_arg);
+  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, arg_type));
+
+  classid_t type_cid = pointer_type_arg.type_class_id();
+  StoreValue(pointer, type_cid, new_value);
+  return Object::null();
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_sizeOf, 1, 0) {
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  CheckIsConcreteNativeType(type_arg);
+  CheckSized(type_arg);
+
+  classid_t type_cid = type_arg.type_class_id();
+  return Smi::New(ElementSizeInBytes(type_cid));
+}
+
+// Generates assembly to trampoline from Dart into C++.
+//
+// Attaches assembly code to the function with the folling features:
+// - unboxes arguments
+// - puts the arguments on the c stack
+// - invokes the c function
+// - reads the the result
+// - boxes the result and returns it.
+//
+// It inspects the signature to know what to box/unbox
+// Parameter `function` has the Dart types in its signature
+// Parameter `c_signature` has the C++ types in its signature
+static RawCode* TrampolineCode(const Function& function,
+                               const Function& c_signature) {
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+  // Currently we generate the trampoline when calling asFunction(), this means
+  // the ffi cannot be used in AOT.
+  // In order make it work in AOT we need to:
+  // - collect all asFunction signatures ahead of time
+  // - generate trampolines for those
+  // - store these in the object store
+  // - and read these from the object store when calling asFunction()
+  // https://github.com/dart-lang/sdk/issues/35765
+  UNREACHABLE();
+#elif !defined(TARGET_ARCH_X64)
+  // https://github.com/dart-lang/sdk/issues/35774
+  UNREACHABLE();
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
+  // https://github.com/dart-lang/sdk/issues/35771 Windows
+  // https://github.com/dart-lang/sdk/issues/35772 Arm64
+  // https://github.com/dart-lang/sdk/issues/35773 DBC
+  UNREACHABLE();
+#else
+  extern void GenerateFfiTrampoline(Assembler * assembler,
+                                    const Function& signature);
+  ObjectPoolBuilder object_pool_builder;
+  Assembler assembler(&object_pool_builder);
+  GenerateFfiTrampoline(&assembler, c_signature);
+  const Code& code = Code::Handle(Code::FinalizeCode(
+      function, nullptr, &assembler, Code::PoolAttachment::kAttachPool));
+  code.set_exception_handlers(
+      ExceptionHandlers::Handle(ExceptionHandlers::New(0)));
+  return code.raw();
+#endif
+}
+
+// TODO(dacoharkes): Cache the trampolines.
+// We can possibly address simultaniously with 'precaching' in AOT.
+static RawFunction* TrampolineFunction(const Function& dart_signature,
+                                       const Function& c_signature) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  const String& name =
+      String::ZoneHandle(Symbols::New(Thread::Current(), "FfiTrampoline"));
+  const Library& lib = Library::Handle(Library::FfiLibrary());
+  const Class& owner_class = Class::Handle(lib.toplevel_class());
+  Function& function = Function::ZoneHandle(
+      zone, Function::New(name, RawFunction::kFfiTrampoline,
+                          true,   // is_static
+                          false,  // is_const
+                          false,  // is_abstract
+                          false,  // is_external
+                          true,   // is_native
+                          owner_class, TokenPosition::kMinSource));
+
+  function.set_num_fixed_parameters(dart_signature.num_fixed_parameters());
+  function.set_result_type(AbstractType::Handle(dart_signature.result_type()));
+  function.set_parameter_types(Array::Handle(dart_signature.parameter_types()));
+
+  const Code& code = Code::Handle(TrampolineCode(function, c_signature));
+  function.AttachCode(code);
+
+  return function.raw();
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_asFunction, 1, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(Pointer, pointer, arguments->NativeArgAt(0));
+  AbstractType& pointer_type_arg =
+      AbstractType::Handle(pointer.type_argument());
+  ASSERT(IsNativeFunction(pointer_type_arg));
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  ASSERT(DartAndCTypeCorrespond(pointer_type_arg, type_arg));
+
+  Function& dart_signature = Function::Handle(Type::Cast(type_arg).signature());
+  TypeArguments& nativefunction_type_args =
+      TypeArguments::Handle(pointer_type_arg.arguments());
+  AbstractType& nativefunction_type_arg =
+      AbstractType::Handle(nativefunction_type_args.TypeAt(0));
+  Function& c_signature =
+      Function::Handle(Type::Cast(nativefunction_type_arg).signature());
+  Function& function =
+      Function::Handle(TrampolineFunction(dart_signature, c_signature));
+
+  // Set the c function pointer in the context of the closure rather than in
+  // the function so that we can reuse the function for each c function with
+  // the same signature.
+  Context& context = Context::Handle(Context::New(1));
+  context.SetAt(0,
+                Object::Handle(Integer::NewFromUint64(
+                    reinterpret_cast<intptr_t>(pointer.GetCMemoryAddress()))));
+
+  RawClosure* raw_closure =
+      Closure::New(Object::null_type_arguments(), Object::null_type_arguments(),
+                   function, context, Heap::kOld);
+
+  return raw_closure;
+}
+
+// Generates assembly to trampoline from C++ back into Dart.
+static void* GenerateFfiInverseTrampoline(const Function& signature,
+                                          void* dart_entry_point) {
+#if defined(DART_PRECOMPILED_RUNTIME) || defined(DART_PRECOMPILER)
+  UNREACHABLE();
+#elif !defined(TARGET_ARCH_X64)
+  // https://github.com/dart-lang/sdk/issues/35774
+  UNREACHABLE();
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+  // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
+  // https://github.com/dart-lang/sdk/issues/35771 Windows
+  // https://github.com/dart-lang/sdk/issues/35772 Arm64
+  // https://github.com/dart-lang/sdk/issues/35773 DBC
+  UNREACHABLE();
+#else
+  extern void GenerateFfiInverseTrampoline(
+      Assembler * assembler, const Function& signature, void* dart_entry_point);
+  ObjectPoolBuilder object_pool_builder;
+  Assembler assembler(&object_pool_builder);
+  GenerateFfiInverseTrampoline(&assembler, signature, dart_entry_point);
+  const Code& code = Code::Handle(
+      Code::FinalizeCode("inverse trampoline", nullptr, &assembler,
+                         Code::PoolAttachment::kAttachPool, false));
+
+  uword entryPoint = code.EntryPoint();
+
+  return reinterpret_cast<void*>(entryPoint);
+#endif
+}
+
+// TODO(dacoharkes): Implement this feature.
+// https://github.com/dart-lang/sdk/issues/35761
+// For now, it always returns Pointer with address 0.
+DEFINE_NATIVE_ENTRY(Ffi_fromFunction, 1, 1) {
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(Closure, closure, arguments->NativeArgAt(0));
+
+  Function& c_signature = Function::Handle(((Type&)type_arg).signature());
+
+  Function& func = Function::Handle(closure.function());
+  Code& code = Code::Handle(func.EnsureHasCode());
+  void* entryPoint = reinterpret_cast<void*>(code.EntryPoint());
+
+  THR_Print("Ffi_fromFunction: %s\n", type_arg.ToCString());
+  THR_Print("Ffi_fromFunction: %s\n", c_signature.ToCString());
+  THR_Print("Ffi_fromFunction: %s\n", closure.ToCString());
+  THR_Print("Ffi_fromFunction: %s\n", func.ToCString());
+  THR_Print("Ffi_fromFunction: %s\n", code.ToCString());
+  THR_Print("Ffi_fromFunction: %p\n", entryPoint);
+  THR_Print("Ffi_fromFunction: %" Pd "\n", code.Size());
+
+  void* address = GenerateFfiInverseTrampoline(c_signature, entryPoint);
+
+  TypeArguments& type_args = TypeArguments::Handle(zone);
+  type_args = TypeArguments::New(1);
+  type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
+  type_args ^= type_args.Canonicalize();
+
+  Class& native_function_class = Class::Handle(
+      Isolate::Current()->class_table()->At(kFfiNativeFunctionCid));
+  native_function_class.EnsureIsFinalized(Thread::Current());
+
+  Type& native_function_type = Type::Handle(
+      Type::New(native_function_class, type_args, TokenPosition::kNoSource));
+  native_function_type ^=
+      ClassFinalizer::FinalizeType(Class::Handle(), native_function_type);
+  native_function_type ^= native_function_type.Canonicalize();
+
+  address = 0;  // https://github.com/dart-lang/sdk/issues/35761
+
+  Pointer& result = Pointer::Handle(
+      Pointer::New(native_function_type, reinterpret_cast<uint8_t*>(address)));
+
+  return result.raw();
+}
+
+}  // namespace dart
diff --git a/runtime/lib/ffi_dynamic_library.cc b/runtime/lib/ffi_dynamic_library.cc
new file mode 100644
index 0000000..b083e04
--- /dev/null
+++ b/runtime/lib/ffi_dynamic_library.cc
@@ -0,0 +1,114 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+// TODO(dacoharkes): implement dynamic libraries for other targets.
+// see
+// - runtime/vm/native_symbol.h
+// - runtime/vm/native_symbol_linux.cc
+// - runtime/bin/extensions.h (but we cannot import from bin)
+// - runtime/bin/extensions_linux.cc
+#else
+#include <dlfcn.h>
+#endif
+#include "include/dart_api.h"
+#include "vm/bootstrap_natives.h"
+#include "vm/exceptions.h"
+#include "vm/native_entry.h"
+
+namespace dart {
+
+// Concatenates a NULL terminated array of strings.
+// The returned string is scope allocated.
+// TODO(dacoharkes): Can we share this with runtime/bin/extensions.cc?
+const char* Concatenate(const char** strings) {
+  int size = 1;  // null termination.
+  for (int i = 0; strings[i] != NULL; i++) {
+    size += strlen(strings[i]);
+  }
+  char* result = reinterpret_cast<char*>(Dart_ScopeAllocate(size));
+  int index = 0;
+  for (int i = 0; strings[i] != NULL; i++) {
+    index += snprintf(result + index, size - index, "%s", strings[i]);
+  }
+  ASSERT(index == size - 1);
+  ASSERT(result[size - 1] == '\0');
+  return result;
+}
+
+// TODO(dacoharkes): Can we share this with runtime/bin/extensions.cc?
+const char* LibraryPath(const char* library_name) {
+  const char* library_prefix = "lib";
+#if defined(TARGET_OS_LINUX)
+  const char* library_extension = "so";
+#elif defined(TARGET_OS_MACOS)
+  const char* library_extension = "dylib";
+#else
+  const char* library_extension = "";
+  UNREACHABLE();
+#endif
+
+  const char* path_components[] = {
+      library_prefix, library_name, ".", library_extension, NULL,
+  };
+
+  return Concatenate(path_components);
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_dl_open, 0, 1) {
+#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+  UNREACHABLE();
+#else
+  GET_NON_NULL_NATIVE_ARGUMENT(String, argName, arguments->NativeArgAt(0));
+
+  dlerror();  // Clear any errors.
+  void* handle = dlopen(LibraryPath(argName.ToCString()), RTLD_LAZY);
+  if (handle == nullptr) {
+    char* error = dlerror();
+    const String& msg = String::Handle(
+        String::NewFormatted("Failed to load dynamic library(%s)", error));
+    Exceptions::ThrowArgumentError(msg);
+  }
+
+  return DynamicLibrary::New(handle);
+#endif
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_dl_lookup, 1, 2) {
+#if !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+  UNREACHABLE();
+#else
+  GET_NATIVE_TYPE_ARGUMENT(type_arg, arguments->NativeTypeArgAt(0));
+
+  GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
+  GET_NON_NULL_NATIVE_ARGUMENT(String, argSymbolName,
+                               arguments->NativeArgAt(1));
+
+  void* handle = dlib.GetHandle();
+
+  dlerror();  // Clear any errors.
+  uint8_t* pointer =
+      reinterpret_cast<uint8_t*>(dlsym(handle, argSymbolName.ToCString()));
+  char* error;
+  if ((error = dlerror()) != NULL) {
+    const String& msg = String::Handle(
+        String::NewFormatted("Failed to lookup symbol (%s)", error));
+    Exceptions::ThrowArgumentError(msg);
+  }
+
+  // TODO(dacoharkes): should this return NULL if addres is 0?
+  // https://github.com/dart-lang/sdk/issues/35756
+  RawPointer* result = Pointer::New(type_arg, pointer);
+  return result;
+#endif
+}
+
+DEFINE_NATIVE_ENTRY(Ffi_dl_getHandle, 0, 1) {
+  GET_NON_NULL_NATIVE_ARGUMENT(DynamicLibrary, dlib, arguments->NativeArgAt(0));
+
+  intptr_t handle = reinterpret_cast<intptr_t>(dlib.GetHandle());
+  return Integer::NewFromUint64(handle);
+}
+
+}  // namespace dart
diff --git a/runtime/lib/ffi_dynamic_library_patch.dart b/runtime/lib/ffi_dynamic_library_patch.dart
new file mode 100644
index 0000000..db45805
--- /dev/null
+++ b/runtime/lib/ffi_dynamic_library_patch.dart
@@ -0,0 +1,35 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:_internal" show patch;
+
+DynamicLibrary _open(String name) native "Ffi_dl_open";
+
+@patch
+class DynamicLibrary {
+  @patch
+  @pragma("vm:entry-point")
+  factory DynamicLibrary.open(String name) {
+    return _open(name);
+  }
+
+  @patch
+  Pointer<T> lookup<T extends NativeType>(String symbolName)
+      native "Ffi_dl_lookup";
+
+  // TODO(dacoharkes): Expose this to users, or extend Pointer?
+  // https://github.com/dart-lang/sdk/issues/35881
+  int getHandle() native "Ffi_dl_getHandle";
+
+  @patch
+  bool operator ==(other) {
+    if (other == null) return false;
+    return getHandle() == other.getHandle();
+  }
+
+  @patch
+  int get hashCode {
+    return getHandle().hashCode;
+  }
+}
diff --git a/runtime/lib/ffi_native_type_patch.dart b/runtime/lib/ffi_native_type_patch.dart
new file mode 100644
index 0000000..b12f0b8
--- /dev/null
+++ b/runtime/lib/ffi_native_type_patch.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 "dart:_internal" show patch;
+
+@patch
+@pragma("vm:entry-point")
+class NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class _NativeInteger extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class _NativeDouble extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class Int8 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int16 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int32 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Int64 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint8 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint16 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint32 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Uint64 extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class IntPtr extends _NativeInteger {}
+
+@patch
+@pragma("vm:entry-point")
+class Float extends _NativeDouble {}
+
+@patch
+@pragma("vm:entry-point")
+class Double extends _NativeDouble {}
+
+@patch
+@pragma("vm:entry-point")
+class Void extends NativeType {}
+
+@patch
+@pragma("vm:entry-point")
+class NativeFunction<T extends Function> extends NativeType {}
diff --git a/runtime/lib/ffi_patch.dart b/runtime/lib/ffi_patch.dart
new file mode 100644
index 0000000..c8fde6c
--- /dev/null
+++ b/runtime/lib/ffi_patch.dart
@@ -0,0 +1,55 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:_internal" show patch;
+
+@patch
+Pointer<T> allocate<T extends NativeType>({int count: 1}) native "Ffi_allocate";
+
+@patch
+T fromAddress<T extends Pointer>(int ptr) native "Ffi_fromAddress";
+
+@patch
+int sizeOf<T extends NativeType>() native "Ffi_sizeOf";
+
+@patch
+Pointer<NativeFunction<T>> fromFunction<T extends Function>(
+    @DartRepresentationOf("T") Function f) native "Ffi_fromFunction";
+
+@patch
+@pragma("vm:entry-point")
+class Pointer<T extends NativeType> {
+  @patch
+  void store(Object value) native "Ffi_store";
+
+  @patch
+  R load<R>() native "Ffi_load";
+
+  @patch
+  int get address native "Ffi_address";
+
+  // Note this could also be implmented without an extra native as offsetBy
+  // (elementSize()*index). This would be 2 native calls rather than one. What
+  // would be better?
+  @patch
+  Pointer<T> elementAt(int index) native "Ffi_elementAt";
+
+  // Note this could also be implmented without an extra  native as
+  // fromAddress(address). This would be 2 native calls rather than one.
+  // What would be better?
+  @patch
+  Pointer<T> offsetBy(int offsetInBytes) native "Ffi_offsetBy";
+
+  // Note this could also be implemented without an extra native as
+  // fromAddress(address). This would be 2 native calls rather than one.
+  // What would be better?
+  @patch
+  U cast<U extends Pointer>() native "Ffi_cast";
+
+  @patch
+  R asFunction<R extends Function>() native "Ffi_asFunction";
+
+  @patch
+  void free() native "Ffi_free";
+}
diff --git a/runtime/lib/ffi_sources.gni b/runtime/lib/ffi_sources.gni
new file mode 100644
index 0000000..fd625f4
--- /dev/null
+++ b/runtime/lib/ffi_sources.gni
@@ -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.
+
+# Sources visible via dart:ffi library.
+ffi_runtime_cc_files = [
+  "ffi.cc",
+  "ffi_dynamic_library.cc",
+]
+
+ffi_runtime_dart_files = [
+  "ffi_patch.dart",
+  "ffi_dynamic_library_patch.dart",
+  "ffi_native_type_patch.dart",
+]
+
+ffi_runtime_sources = ffi_runtime_cc_files + ffi_runtime_dart_files
diff --git a/runtime/lib/mirrors.cc b/runtime/lib/mirrors.cc
index d4916d0..81ce5c3 100644
--- a/runtime/lib/mirrors.cc
+++ b/runtime/lib/mirrors.cc
@@ -1032,6 +1032,8 @@
   GET_NON_NULL_NATIVE_ARGUMENT(MirrorReference, ref, arguments->NativeArgAt(1));
   const Library& library = Library::Handle(ref.GetLibraryReferent());
 
+  library.EnsureTopLevelClassIsFinalized();
+
   Instance& member_mirror = Instance::Handle();
   const GrowableObjectArray& member_mirrors =
       GrowableObjectArray::Handle(GrowableObjectArray::New());
diff --git a/runtime/observatory/tests/service/get_source_report_test.dart b/runtime/observatory/tests/service/get_source_report_test.dart
index f8dbfaaa..6b70552 100644
--- a/runtime/observatory/tests/service/get_source_report_test.dart
+++ b/runtime/observatory/tests/service/get_source_report_test.dart
@@ -34,6 +34,19 @@
   MyClass.myFunction(10000);
 }
 
+class MyConstClass {
+  const MyConstClass();
+  static const MyConstClass instance = null ?? const MyConstClass();
+
+  void foo() {
+    debugger();
+  }
+}
+
+void testFunction2() {
+  MyConstClass.instance.foo();
+}
+
 bool allRangesCompiled(coverage) {
   for (int i = 0; i < coverage['ranges'].length; i++) {
     if (!coverage['ranges'][i]['compiled']) {
@@ -78,9 +91,9 @@
     final numRanges = coverage['ranges'].length;
     expect(coverage['type'], equals('SourceReport'));
 
-    // Running in app_jitk mode will result in the number of ranges being 7
-    // during the training run and 8 when running from the snapshot.
-    expect(((numRanges == 7) || (numRanges == 8)), isTrue);
+    // Running in app_jitk mode will result in the number of ranges being 10
+    // during the training run and 11 when running from the snapshot.
+    expect(((numRanges == 10) || (numRanges == 11)), isTrue);
     expect(coverage['ranges'][0], equals(expectedRange));
     expect(coverage['scripts'].length, 1);
     expect(
@@ -95,7 +108,7 @@
     };
     coverage = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
     expect(coverage['type'], equals('SourceReport'));
-    expect(coverage['ranges'].length, numRanges);
+    expect(coverage['ranges'].length, numRanges + 3);
     expect(allRangesCompiled(coverage), isTrue);
 
     // One function
diff --git a/runtime/observatory/tests/service/regress_34841_lib.dart b/runtime/observatory/tests/service/regress_34841_lib.dart
new file mode 100644
index 0000000..304f6f5
--- /dev/null
+++ b/runtime/observatory/tests/service/regress_34841_lib.dart
@@ -0,0 +1,9 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Foo {
+  final String foo = () {
+    return StackTrace.current.toString();
+  }();
+}
diff --git a/runtime/observatory/tests/service/regress_34841_test.dart b/runtime/observatory/tests/service/regress_34841_test.dart
new file mode 100644
index 0000000..69acbad
--- /dev/null
+++ b/runtime/observatory/tests/service/regress_34841_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// While it's not (currently) necessary, add some noise here to push down token
+// positions in this file compared to the file regress_34841_lib.dart.
+// This is to ensure that any possible tokens in that file are just comments
+// (i.e. not actual) positions in this file.
+
+import 'package:observatory/service_io.dart';
+import 'package:unittest/unittest.dart';
+import 'test_helper.dart';
+import 'service_test_common.dart';
+import 'dart:developer';
+import 'regress_34841_lib.dart';
+
+class Bar extends Object with Foo {}
+
+void testFunction() {
+  Bar bar = new Bar();
+  print(bar.foo);
+  debugger();
+}
+
+var tests = <IsolateTest>[
+  hasStoppedAtBreakpoint,
+  (Isolate isolate) async {
+    var stack = await isolate.getStack();
+
+    // Make sure we are in the right place.
+    expect(stack.type, equals('Stack'));
+    expect(stack['frames'].length, greaterThanOrEqualTo(1));
+    expect(stack['frames'][0].function.name, equals('testFunction'));
+
+    var root = isolate.rootLibrary;
+    await root.load();
+    Script script = root.scripts.first;
+    await script.load();
+
+    var params = {
+      'reports': ['Coverage'],
+      'scriptId': script.id,
+      'forceCompile': true
+    };
+    var report = await isolate.invokeRpcNoUpgrade('getSourceReport', params);
+    List<dynamic> ranges = report['ranges'];
+    List<int> coveragePlaces = <int>[];
+    for (var range in ranges) {
+      for (int i in range["coverage"]["hits"]) {
+        coveragePlaces.add(i);
+      }
+      for (int i in range["coverage"]["misses"]) {
+        coveragePlaces.add(i);
+      }
+    }
+
+    // Make sure we can translate it all.
+    for (int place in coveragePlaces) {
+      int line = script.tokenToLine(place);
+      int column = script.tokenToCol(place);
+      if (line == null || column == null) {
+        throw "Token $place translated to $line:$column";
+      }
+    }
+  },
+];
+
+main(args) => runIsolateTests(args, tests, testeeConcurrent: testFunction);
diff --git a/runtime/observatory/tests/service/service_kernel.status b/runtime/observatory/tests/service/service_kernel.status
index 3b35e4f..b72cf4c 100644
--- a/runtime/observatory/tests/service/service_kernel.status
+++ b/runtime/observatory/tests/service/service_kernel.status
@@ -31,6 +31,7 @@
 get_user_level_retaining_path_rpc_test: SkipByDesign # No incremental compiler available.
 instance_field_order_rpc_test: SkipByDesign # No incremental compiler available.
 pause_on_exceptions_test: SkipByDesign # No incremental compiler available.
+regress_34841_test: RuntimeError # http://dartbug.com/34841
 rewind_optimized_out_test: SkipByDesign # No incremental compiler available.
 rewind_test: SkipByDesign # No incremental compiler available.
 simple_reload_test: RuntimeError, Timeout # Issue 35506
@@ -46,6 +47,7 @@
 evaluate_activation_test/instance: RuntimeError # http://dartbug.com/20047
 evaluate_activation_test/scope: RuntimeError # http://dartbug.com/20047
 pause_on_unhandled_async_exceptions2_test: Pass, Slow
+regress_34841_test: RuntimeError # http://dartbug.com/34841
 unused_changes_in_last_reload_test: RuntimeError
 
 [ $compiler == dartkp ]
diff --git a/runtime/observatory/tests/service/step_through_switch_with_continue_test.dart b/runtime/observatory/tests/service/step_through_switch_with_continue_test.dart
index cfcce49..d9afbb4 100644
--- a/runtime/observatory/tests/service/step_through_switch_with_continue_test.dart
+++ b/runtime/observatory/tests/service/step_through_switch_with_continue_test.dart
@@ -31,6 +31,7 @@
   "$file:${LINE+0}:5", // after 'code'
 
   "$file:${LINE+1}:11", // on switchOnMe
+  "$file:${LINE+17}:27", // on switchOnMe initializer starting '['
   "$file:${LINE+1}:22", // on length
 
   "$file:${LINE+2}:10", // on 0
diff --git a/runtime/platform/utils.h b/runtime/platform/utils.h
index 56c49bb..2951d43 100644
--- a/runtime/platform/utils.h
+++ b/runtime/platform/utils.h
@@ -6,6 +6,7 @@
 #define RUNTIME_PLATFORM_UTILS_H_
 
 #include <limits>
+#include <type_traits>
 
 #include "platform/assert.h"
 #include "platform/globals.h"
@@ -338,21 +339,24 @@
   }
 
   // Decode integer in SLEB128 format from |data| and update |byte_index|.
-  static intptr_t DecodeSLEB128(const uint8_t* data,
-                                const intptr_t data_length,
-                                intptr_t* byte_index) {
+  template <typename ValueType>
+  static ValueType DecodeSLEB128(const uint8_t* data,
+                                 const intptr_t data_length,
+                                 intptr_t* byte_index) {
     ASSERT(*byte_index < data_length);
     uword shift = 0;
-    intptr_t value = 0;
+    ValueType value = 0;
     uint8_t part = 0;
     do {
       part = data[(*byte_index)++];
-      value |= static_cast<intptr_t>(part & 0x7f) << shift;
+      value |= static_cast<ValueType>(part & 0x7f) << shift;
       shift += 7;
     } while ((part & 0x80) != 0);
 
-    if ((shift < (sizeof(value) * 8)) && ((part & 0x40) != 0)) {
-      value |= static_cast<intptr_t>(kUwordMax << shift);
+    if ((shift < (sizeof(ValueType) * CHAR_BIT)) && ((part & 0x40) != 0)) {
+      using Unsigned = typename std::make_unsigned<ValueType>::type;
+      const Unsigned kMax = std::numeric_limits<Unsigned>::max();
+      value |= static_cast<ValueType>(kMax << shift);
     }
     return value;
   }
diff --git a/runtime/tests/vm/dart/regress_35887_test.dart b/runtime/tests/vm/dart/regress_35887_test.dart
new file mode 100644
index 0000000..b0018fb
--- /dev/null
+++ b/runtime/tests/vm/dart/regress_35887_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.
+//
+// Regression test for dartbug.com/35887.
+//
+// The call specializer inserts a "CheckNull" into main() here, but CheckNull
+// was broken in JIT because it didn't create a deopt-info to hold the
+// environment in case the it was inside a try/catch block.
+//
+// VMOptions=--optimization_counter_threshold=10 --no-background-compilation
+
+import 'package:expect/expect.dart';
+
+class Value {
+  const Value(this.val);
+
+  final int val;
+}
+
+const int limit = 50;
+
+Value maybeWrap(int i) => i < limit ? new Value(i) : null;
+
+Future<void> test() async {
+  for (int i = 0; i < 60; ++i) {
+    if (maybeWrap(i).val == -1) {
+      // never mind we just do something with it
+      print(i);
+    }
+  }
+}
+
+void main() {
+  test().catchError((e) {});
+}
diff --git a/runtime/tests/vm/dart/slow_path_shared_stub_test.dart b/runtime/tests/vm/dart/slow_path_shared_stub_test.dart
index 87ce2ed..7c50e88 100644
--- a/runtime/tests/vm/dart/slow_path_shared_stub_test.dart
+++ b/runtime/tests/vm/dart/slow_path_shared_stub_test.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 // VMOptions=--optimization_counter_threshold=10 --no-background-compilation --shared-slow-path-triggers-gc
+// VMOptions=--optimization_counter_threshold=10 --no-background-compilation --shared-slow-path-triggers-gc --no-use-vfp
 
 // This tests the stackmaps and environments for safepoints corresponding to
 // slow-path code which uses shared runtime stubs.
diff --git a/runtime/tools/dartfuzz/README.md b/runtime/tools/dartfuzz/README.md
index 9c740b1..14398d7 100644
--- a/runtime/tools/dartfuzz/README.md
+++ b/runtime/tools/dartfuzz/README.md
@@ -48,19 +48,19 @@
     --dart-top        : sets DART_TOP explicitly through command line
     --mode1           : m1
     --mode2           : m2, and values one of
-        jit-[stress-][debug-]ia32  = Dart JIT (ia32)
-        jit-[stress-][debug-]x64   = Dart JIT (x64)
-        jit-[stress-][debug-]arm32 = Dart JIT (simarm)
-        jit-[stress-][debug-]arm64 = Dart JIT (simarm64)
-        jit-[stress-][debug-]dbc   = Dart JIT (simdbc)
-        jit-[stress-][debug-]dbc64 = Dart JIT (simdbc64)
-        aot-[debug-]x64            = Dart AOT (x64)
-        aot-[debug-]arm32          = Dart AOT (simarm)
-        aot-[debug-]arm64          = Dart AOT (simarm64)
-        kbc-int-[debug-]x64        = Dart KBC (interpreted bytecode)
-        kbc-mix-[debug-]x64        = Dart KBC (mixed-mode bytecode)
-        kbc-cmp-[debug-]x64        = Dart KBC (compiled bytecode)
-        js-x64                     = dart2js + Node.JS
+        jit-[debug-]ia32    = Dart JIT (ia32)
+        jit-[debug-]x64     = Dart JIT (x64)
+        jit-[debug-]arm32   = Dart JIT (simarm)
+        jit-[debug-]arm64   = Dart JIT (simarm64)
+        jit-[debug-]dbc     = Dart JIT (simdbc)
+        jit-[debug-]dbc64   = Dart JIT (simdbc64)
+        aot-[debug-]x64     = Dart AOT (x64)
+        aot-[debug-]arm32   = Dart AOT (simarm)
+        aot-[debug-]arm64   = Dart AOT (simarm64)
+        kbc-int-[debug-]x64 = Dart KBC (interpreted bytecode)
+        kbc-mix-[debug-]x64 = Dart KBC (mixed-mode bytecode)
+        kbc-cmp-[debug-]x64 = Dart KBC (compiled bytecode)
+        djs-x64             = dart2js + Node.JS
 
 If no modes are given, a random JIT and/or AOT combination is used.
 
diff --git a/runtime/tools/dartfuzz/dartfuzz_test.dart b/runtime/tools/dartfuzz/dartfuzz_test.dart
index 06545ca..148f19e 100644
--- a/runtime/tools/dartfuzz/dartfuzz_test.dart
+++ b/runtime/tools/dartfuzz/dartfuzz_test.dart
@@ -51,38 +51,70 @@
   // Factory.
   static TestRunner getTestRunner(String mode, String top, String tmp,
       Map<String, String> env, Random rand) {
+    String prefix = mode.substring(0, 3).toUpperCase();
     String tag = getTag(mode);
-    if (mode.startsWith('jit-stress'))
-      switch (rand.nextInt(6)) {
-        case 0:
-          return new TestRunnerJIT('JIT-NOFIELDGUARDS', tag, top, tmp, env,
-              ['--use_field_guards=false']);
-        case 1:
-          return new TestRunnerJIT(
-              'JIT-NOINTRINSIFY', tag, top, tmp, env, ['--intrinsify=false']);
-        case 2:
-          return new TestRunnerJIT('JIT-COMPACTEVERY', tag, top, tmp, env,
-              ['--gc_every=1000', '--use_compactor=true']);
-        case 3:
-          return new TestRunnerJIT('JIT-MARKSWEEPEVERY', tag, top, tmp, env,
-              ['--gc_every=1000', '--use_compactor=false']);
-        case 4:
-          return new TestRunnerJIT('JIT-DEPOPTEVERY', tag, top, tmp, env,
-              ['--deoptimize_every=100']);
-        case 5:
-          return new TestRunnerJIT('JIT-STACKTRACEEVERY', tag, top, tmp, env,
-              ['--stacktrace_every=100']);
-        case 6:
-          // Crashes (https://github.com/dart-lang/sdk/issues/35196):
-          return new TestRunnerJIT('JIT-OPTCOUNTER', tag, top, tmp, env,
-              ['--optimization_counter_threshold=1']);
+    // Prepare extra flags.
+    List<String> extraFlags = [];
+    if (mode.startsWith('kbc-int')) {
+      prefix += '-INT';
+      extraFlags += [
+        '--enable-interpreter',
+        '--compilation-counter-threshold=-1'
+      ];
+    } else if (mode.startsWith('kbc-mix')) {
+      prefix += '-MIX';
+      extraFlags += ['--enable-interpreter'];
+    } else if (mode.startsWith('kbc-cmp')) {
+      prefix += '-CMP';
+      extraFlags += ['--use-bytecode-compiler'];
+    }
+    // Every once in a while, stress test JIT.
+    if (mode.startsWith('jit') && rand.nextInt(4) == 0) {
+      final r = rand.nextInt(6);
+      if (r == 0) {
+        prefix += '-NOFIELDGUARDS';
+        extraFlags += ['--use_field_guards=false'];
+      } else if (r == 1) {
+        prefix += '-NOINTRINSIFY';
+        extraFlags += ['--intrinsify=false'];
+      } else if (r == 2) {
+        prefix += '-COMPACTEVERY';
+        extraFlags += ['--gc_every=1000', '--use_compactor=true'];
+      } else if (r == 3) {
+        prefix += '-MARKSWEEPEVERY';
+        extraFlags += ['--gc_every=1000', '--use_compactor=false'];
+      } else if (r == 4) {
+        prefix += '-DEPOPTEVERY';
+        extraFlags += ['--deoptimize_every=100'];
+      } else if (r == 5) {
+        prefix += '-STACKTRACEEVERY';
+        extraFlags += ['--stacktrace_every=100'];
+      } else if (r == 6) {
+        // Crashes (https://github.com/dart-lang/sdk/issues/35196):
+        prefix += '-OPTCOUNTER';
+        extraFlags += ['--optimization_counter_threshold=1'];
       }
-    if (mode.startsWith('jit'))
-      return new TestRunnerJIT('JIT', tag, top, tmp, env, []);
-    if (mode.startsWith('aot')) return new TestRunnerAOT(tag, top, tmp, env);
-    if (mode.startsWith('kbc'))
-      return new TestRunnerKBC(mode, tag, top, tmp, env);
-    if (mode.startsWith('js')) return new TestRunnerJS(tag, top, tmp, env);
+    }
+    // Every once in a while, disable VFP on arm32.
+    if (mode.contains('arm32') && rand.nextInt(4) == 0) {
+      prefix += '-noVFP';
+      extraFlags += ['--no-use-vfp'];
+    }
+    // Every once in a while, use -O3 compiler.
+    if (!mode.startsWith('djs') && rand.nextInt(4) == 0) {
+      prefix += '-O3';
+      extraFlags += ['--optimization_level=3'];
+    }
+    // Construct runner.
+    if (mode.startsWith('jit')) {
+      return new TestRunnerJIT(prefix, tag, top, tmp, env, extraFlags);
+    } else if (mode.startsWith('aot')) {
+      return new TestRunnerAOT(prefix, tag, top, tmp, env, extraFlags);
+    } else if (mode.startsWith('kbc')) {
+      return new TestRunnerKBC(prefix, tag, top, tmp, env, extraFlags);
+    } else if (mode.startsWith('djs')) {
+      return new TestRunnerDJS(prefix, tag, top, tmp, env);
+    }
     throw ('unknown runner in mode: $mode');
   }
 
@@ -106,13 +138,12 @@
 
 /// Concrete test runner of Dart JIT.
 class TestRunnerJIT implements TestRunner {
-  TestRunnerJIT(String prefix, String tag, String top, String tmp,
-      Map<String, String> e, List<String> extra_flags) {
+  TestRunnerJIT(String prefix, String tag, String top, String tmp, this.env,
+      List<String> extraFlags) {
     description = '$prefix-$tag';
     dart = '$top/out/$tag/dart';
     fileName = '$tmp/fuzz.dart';
-    env = e;
-    cmd = [dart, "--deterministic"] + extra_flags + [fileName];
+    cmd = [dart, "--deterministic"] + extraFlags + [fileName];
   }
 
   TestResult run() {
@@ -128,14 +159,16 @@
 
 /// Concrete test runner of Dart AOT.
 class TestRunnerAOT implements TestRunner {
-  TestRunnerAOT(String tag, String top, String tmp, Map<String, String> e) {
-    description = 'AOT-${tag}';
+  TestRunnerAOT(String prefix, String tag, String top, String tmp,
+      Map<String, String> e, List<String> extraFlags) {
+    description = '$prefix-$tag';
     precompiler = '$top/pkg/vm/tool/precompiler2';
     dart = '$top/pkg/vm/tool/dart_precompiled_runtime2';
     fileName = '$tmp/fuzz.dart';
     snapshot = '$tmp/snapshot';
     env = Map<String, String>.from(e);
     env['DART_CONFIGURATION'] = tag;
+    env['OPTIONS'] = extraFlags.join(' ');
   }
 
   TestResult run() {
@@ -156,28 +189,15 @@
 
 /// Concrete test runner of bytecode.
 class TestRunnerKBC implements TestRunner {
-  TestRunnerKBC(
-      String mode, String tag, String top, String tmp, Map<String, String> e) {
+  TestRunnerKBC(String prefix, String tag, String top, String tmp, this.env,
+      List<String> extraFlags) {
+    description = '$prefix-$tag';
     generate = '$top/pkg/vm/tool/gen_kernel';
     platform = '--platform=$top/out/$tag/vm_platform_strong.dill';
     dill = '$tmp/out.dill';
     dart = '$top/out/$tag/dart';
     fileName = '$tmp/fuzz.dart';
-    env = e;
-    cmd = [dart];
-    if (mode.startsWith('kbc-int')) {
-      description = 'KBC-INT-${tag}';
-      cmd += ['--enable-interpreter', '--compilation-counter-threshold=-1'];
-    } else if (mode.startsWith('kbc-mix')) {
-      description = 'KBC-MIX-${tag}';
-      cmd += ['--enable-interpreter'];
-    } else if (mode.startsWith('kbc-cmp')) {
-      description = 'KBC-CMP-${tag}';
-      cmd += ['--use-bytecode-compiler'];
-    } else {
-      throw ('unknown KBC mode: $mode');
-    }
-    cmd += [dill];
+    cmd = [dart] + extraFlags + [dill];
   }
 
   TestResult run() {
@@ -200,13 +220,12 @@
 }
 
 /// Concrete test runner of Dart2JS.
-class TestRunnerJS implements TestRunner {
-  TestRunnerJS(String tag, String top, String tmp, Map<String, String> e) {
-    description = 'Dart2JS-$tag';
+class TestRunnerDJS implements TestRunner {
+  TestRunnerDJS(String prefix, String tag, String top, String tmp, this.env) {
+    description = '$prefix-$tag';
     dart2js = '$top/sdk/bin/dart2js';
     fileName = '$tmp/fuzz.dart';
     js = '$tmp/out.js';
-    env = e;
   }
 
   TestResult run() {
@@ -525,18 +544,6 @@
     'jit-arm64',
     'jit-dbc',
     'jit-dbc64',
-    'jit-stress-debug-ia32',
-    'jit-stress-debug-x64',
-    'jit-stress-debug-arm32',
-    'jit-stress-debug-arm64',
-    'jit-stress-debug-dbc',
-    'jit-stress-debug-dbc64',
-    'jit-stress-ia32',
-    'jit-stress-x64',
-    'jit-stress-arm32',
-    'jit-stress-arm64',
-    'jit-stress-dbc',
-    'jit-stress-dbc64',
     'aot-debug-x64',
     'aot-x64',
     'kbc-int-debug-x64',
diff --git a/runtime/vm/BUILD.gn b/runtime/vm/BUILD.gn
index cd8eaf1..d018eb1 100644
--- a/runtime/vm/BUILD.gn
+++ b/runtime/vm/BUILD.gn
@@ -8,6 +8,7 @@
 import("../../sdk/lib/convert/convert_sources.gni")
 import("../../sdk/lib/core/core_sources.gni")
 import("../../sdk/lib/developer/developer_sources.gni")
+import("../../sdk/lib/ffi/ffi_sources.gni")
 import("../../sdk/lib/internal/internal_sources.gni")
 import("../../sdk/lib/isolate/isolate_sources.gni")
 import("../../sdk/lib/math/math_sources.gni")
@@ -16,13 +17,15 @@
 import("../../sdk/lib/typed_data/typed_data_sources.gni")
 import("../../sdk/lib/vmservice/vmservice_sources.gni")
 import("../../utils/compile_platform.gni")
-import("../bin/io_sources.gni")
 import("../bin/cli_sources.gni")
+import("../bin/io_sources.gni")
+import("../configs.gni")
 import("../lib/async_sources.gni")
 import("../lib/collection_sources.gni")
 import("../lib/convert_sources.gni")
 import("../lib/core_sources.gni")
 import("../lib/developer_sources.gni")
+import("../lib/ffi_sources.gni")
 import("../lib/internal_sources.gni")
 import("../lib/isolate_sources.gni")
 import("../lib/math_sources.gni")
@@ -30,7 +33,6 @@
 import("../lib/profiler_sources.gni")
 import("../lib/typed_data_sources.gni")
 import("../lib/vmservice_sources.gni")
-import("../configs.gni")
 import("../runtime_args.gni")
 import("compiler/compiler_sources.gni")
 import("heap/heap_sources.gni")
@@ -63,7 +65,7 @@
       # TODO(US-399): Remove time_service specific code when it is no longer
       # necessary.
       "//garnet/public/lib/component/cpp",
-      "//garnet/public/fidl/fuchsia.timezone",
+      "//sdk/fidl/fuchsia.timezone",
 
       # TODO(zra): When the platform-specific timeline code is moved out to
       # the embedder, this can go away.
@@ -84,12 +86,13 @@
 library_for_all_configs("libdart_lib") {
   target_type = "source_set"
   include_dirs = [ ".." ]
-  allsources = async_runtime_sources + collection_runtime_sources +
-               convert_runtime_sources + core_runtime_sources +
-               developer_runtime_sources + internal_runtime_sources +
-               isolate_runtime_sources + math_runtime_sources +
-               mirrors_runtime_sources + profiler_runtime_sources +
-               typed_data_runtime_sources + vmservice_runtime_sources
+  allsources =
+      async_runtime_sources + collection_runtime_sources +
+      convert_runtime_sources + core_runtime_sources +
+      developer_runtime_sources + internal_runtime_sources +
+      isolate_runtime_sources + math_runtime_sources + mirrors_runtime_sources +
+      profiler_runtime_sources + typed_data_runtime_sources +
+      vmservice_runtime_sources + ffi_runtime_sources
   sources = [ "bootstrap.cc" ] + rebase_path(allsources, ".", "../lib")
   snapshot_sources = []
   nosnapshot_sources = []
diff --git a/runtime/vm/bootstrap_natives.cc b/runtime/vm/bootstrap_natives.cc
index e02c6fa..a0e99e3 100644
--- a/runtime/vm/bootstrap_natives.cc
+++ b/runtime/vm/bootstrap_natives.cc
@@ -100,6 +100,11 @@
   library.set_native_entry_resolver(resolver);
   library.set_native_entry_symbol_resolver(symbol_resolver);
 
+  library = Library::FfiLibrary();
+  ASSERT(!library.IsNull());
+  library.set_native_entry_resolver(resolver);
+  library.set_native_entry_symbol_resolver(symbol_resolver);
+
   library = Library::InternalLibrary();
   ASSERT(!library.IsNull());
   library.set_native_entry_resolver(resolver);
diff --git a/runtime/vm/bootstrap_natives.h b/runtime/vm/bootstrap_natives.h
index 551784d..194a86c 100644
--- a/runtime/vm/bootstrap_natives.h
+++ b/runtime/vm/bootstrap_natives.h
@@ -350,7 +350,22 @@
   V(VMService_CancelStream, 1)                                                 \
   V(VMService_RequestAssets, 0)                                                \
   V(VMService_DecodeAssets, 1)                                                 \
-  V(VMService_spawnUriNotify, 2)
+  V(VMService_spawnUriNotify, 2)                                               \
+  V(Ffi_allocate, 1)                                                           \
+  V(Ffi_free, 1)                                                               \
+  V(Ffi_load, 1)                                                               \
+  V(Ffi_store, 2)                                                              \
+  V(Ffi_address, 1)                                                            \
+  V(Ffi_fromAddress, 1)                                                        \
+  V(Ffi_elementAt, 2)                                                          \
+  V(Ffi_offsetBy, 2)                                                           \
+  V(Ffi_cast, 1)                                                               \
+  V(Ffi_sizeOf, 0)                                                             \
+  V(Ffi_asFunction, 1)                                                         \
+  V(Ffi_fromFunction, 1)                                                       \
+  V(Ffi_dl_open, 1)                                                            \
+  V(Ffi_dl_lookup, 2)                                                          \
+  V(Ffi_dl_getHandle, 1)
 
 // List of bootstrap native entry points used in the dart:mirror library.
 #define MIRRORS_BOOTSTRAP_NATIVE_LIST(V)                                       \
diff --git a/runtime/vm/class_finalizer.cc b/runtime/vm/class_finalizer.cc
index a4c53f2..a60217b 100644
--- a/runtime/vm/class_finalizer.cc
+++ b/runtime/vm/class_finalizer.cc
@@ -191,11 +191,13 @@
     class_array = object_store->pending_classes();
     ASSERT(!class_array.IsNull());
     Class& cls = Class::Handle();
-    // First check all superclasses.
+    // Mark all classes as cycle-free (should be checked by front-end).
+    // TODO(alexmarkov): Cleanup is_cycle_free bit on classes.
     for (intptr_t i = 0; i < class_array.Length(); i++) {
       cls ^= class_array.At(i);
-      GrowableArray<intptr_t> visited_interfaces;
-      CheckSuperTypeAndInterfaces(cls, &visited_interfaces);
+      if (!cls.is_cycle_free()) {
+        cls.set_is_cycle_free();
+      }
     }
     // Finalize all classes.
     for (intptr_t i = 0; i < class_array.Length(); i++) {
@@ -976,6 +978,30 @@
   }
 }
 
+// For a class used as an interface marks this class and all its superclasses
+// implemented.
+//
+// Does not mark its interfaces implemented because those would already be
+// marked as such.
+static void MarkImplemented(Zone* zone, const Class& iface) {
+  if (iface.is_implemented()) {
+    return;
+  }
+
+  Class& cls = Class::Handle(zone, iface.raw());
+  AbstractType& type = AbstractType::Handle(zone);
+
+  while (!cls.is_implemented()) {
+    cls.set_is_implemented();
+
+    type = cls.super_type();
+    if (type.IsNull() || type.IsObjectType()) {
+      break;
+    }
+    cls = type.type_class();
+  }
+}
+
 void ClassFinalizer::FinalizeTypesInClass(const Class& cls) {
   Thread* thread = Thread::Current();
   HANDLESCOPE(thread);
@@ -985,12 +1011,6 @@
   if (FLAG_trace_class_finalization) {
     THR_Print("Finalize types in %s\n", cls.ToCString());
   }
-  if (!IsSuperCycleFree(cls)) {
-    const String& name = String::Handle(cls.Name());
-    ReportError(cls, cls.token_pos(),
-                "class '%s' has a cycle in its superclass relationship",
-                name.ToCString());
-  }
   // Finalize super class.
   Class& super_class = Class::Handle(cls.SuperClass());
   if (!super_class.IsNull()) {
@@ -1013,13 +1033,6 @@
     ASSERT(type.signature() == signature.raw());
     ASSERT(type.type_class() == cls.raw());
 
-    // Check for illegal self references.
-    GrowableArray<intptr_t> visited_aliases;
-    if (!IsTypedefCycleFree(cls, type, &visited_aliases)) {
-      const String& name = String::Handle(cls.Name());
-      ReportError(cls, cls.token_pos(),
-                  "typedef '%s' illegally refers to itself", name.ToCString());
-    }
     cls.set_is_type_finalized();
 
     // Finalize the result and parameter types of the signature
@@ -1047,35 +1060,10 @@
   // Finalize interface types (but not necessarily interface classes).
   Array& interface_types = Array::Handle(cls.interfaces());
   AbstractType& interface_type = AbstractType::Handle();
-  AbstractType& seen_interf = AbstractType::Handle();
   for (intptr_t i = 0; i < interface_types.Length(); i++) {
     interface_type ^= interface_types.At(i);
     interface_type = FinalizeType(cls, interface_type);
     interface_types.SetAt(i, interface_type);
-
-    // Check whether the interface is duplicated. We need to wait with
-    // this check until the super type and interface types are finalized,
-    // so that we can use Type::Equals() for the test.
-    // TODO(regis): This restriction about duplicated interfaces may get lifted.
-    ASSERT(interface_type.IsFinalized());
-    ASSERT(super_type.IsNull() || super_type.IsFinalized());
-    if (!super_type.IsNull() && interface_type.Equals(super_type)) {
-      ReportError(cls, cls.token_pos(),
-                  "super type '%s' may not be listed in "
-                  "implements clause of class '%s'",
-                  String::Handle(super_type.Name()).ToCString(),
-                  String::Handle(cls.Name()).ToCString());
-    }
-    for (intptr_t j = 0; j < i; j++) {
-      seen_interf ^= interface_types.At(j);
-      if (interface_type.Equals(seen_interf)) {
-        ReportError(cls, cls.token_pos(),
-                    "interface '%s' appears twice in "
-                    "implements clause of class '%s'",
-                    String::Handle(interface_type.Name()).ToCString(),
-                    String::Handle(cls.Name()).ToCString());
-      }
-    }
   }
   cls.set_is_type_finalized();
 
@@ -1090,10 +1078,15 @@
   // classes.
   Zone* zone = thread->zone();
   auto& interface_class = Class::Handle(zone);
+  const intptr_t mixin_index = cls.is_transformed_mixin_application()
+                                   ? interface_types.Length() - 1
+                                   : -1;
   for (intptr_t i = 0; i < interface_types.Length(); ++i) {
     interface_type ^= interface_types.At(i);
     interface_class = interface_type.type_class();
-    interface_class.AddDirectImplementor(cls);
+    MarkImplemented(thread->zone(), interface_class);
+    interface_class.AddDirectImplementor(cls,
+                                         /* is_mixin = */ i == mixin_index);
   }
 
   if (FLAG_use_cha_deopt) {
@@ -1108,11 +1101,6 @@
       interface_class.DisableCHAImplementorUsers();
     }
   }
-
-  // A top level class is loaded eagerly so just finalize it.
-  if (cls.IsTopLevel()) {
-    FinalizeClass(cls);
-  }
 }
 
 void ClassFinalizer::FinalizeClass(const Class& cls) {
@@ -1139,8 +1127,8 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
   // If loading from a kernel, make sure that the class is fully loaded.
-  // Top level classes are always fully loaded.
-  if (!cls.IsTopLevel() && cls.kernel_offset() > 0) {
+  ASSERT(cls.IsTopLevel() || (cls.kernel_offset() > 0));
+  if (!cls.is_loaded()) {
     kernel::KernelLoader::FinishLoading(cls);
     if (cls.is_finalized()) {
       return;
@@ -1174,9 +1162,6 @@
          cls.is_abstract() || (Array::Handle(cls.functions()).Length() > 0));
   FinalizeMemberTypes(cls);
   // Run additional checks after all types are finalized.
-  if (cls.is_const()) {
-    CheckForLegalConstClass(cls);
-  }
   if (FLAG_use_cha_deopt) {
     GrowableArray<intptr_t> cids;
     CollectFinalizedSuperClasses(cls, &cids);
@@ -1191,10 +1176,6 @@
 
 RawError* ClassFinalizer::LoadClassMembers(const Class& cls) {
   ASSERT(Thread::Current()->IsMutatorThread());
-  // If class is a top level class it is already loaded.
-  if (cls.IsTopLevel()) {
-    return Error::null();
-  }
   LongJumpScope jump;
   if (setjmp(*jump.Set()) == 0) {
     ClassFinalizer::FinalizeClass(cls);
@@ -1309,306 +1290,6 @@
   }
 }
 
-bool ClassFinalizer::IsSuperCycleFree(const Class& cls) {
-  Class& test1 = Class::Handle(cls.raw());
-  Class& test2 = Class::Handle(cls.SuperClass());
-  // A finalized class has been checked for cycles.
-  // Using the hare and tortoise algorithm for locating cycles.
-  while (!test1.is_type_finalized() && !test2.IsNull() &&
-         !test2.is_type_finalized()) {
-    if (test1.raw() == test2.raw()) {
-      // Found a cycle.
-      return false;
-    }
-    test1 = test1.SuperClass();
-    test2 = test2.SuperClass();
-    if (!test2.IsNull()) {
-      test2 = test2.SuperClass();
-    }
-  }
-  // No cycles.
-  return true;
-}
-
-// Returns false if a function type alias illegally refers to itself.
-bool ClassFinalizer::IsTypedefCycleFree(const Class& cls,
-                                        const AbstractType& type,
-                                        GrowableArray<intptr_t>* visited) {
-  ASSERT(visited != NULL);
-  bool checking_typedef = false;
-  if (type.IsType()) {
-    AbstractType& other_type = AbstractType::Handle();
-    if (type.IsFunctionType()) {
-      const Class& scope_class = Class::Handle(type.type_class());
-      const Function& signature_function =
-          Function::Handle(Type::Cast(type).signature());
-      // The signature function of this function type may be a local signature
-      // function used in a formal parameter type of the typedef signature, but
-      // not the typedef signature function itself, thus not qualifying as an
-      // illegal self reference.
-      if (!scope_class.is_type_finalized() && scope_class.IsTypedefClass() &&
-          (scope_class.signature_function() == signature_function.raw())) {
-        checking_typedef = true;
-        const intptr_t scope_class_id = scope_class.id();
-        ASSERT(visited != NULL);
-        for (intptr_t i = 0; i < visited->length(); i++) {
-          if ((*visited)[i] == scope_class_id) {
-            // We have already visited alias 'scope_class'. We found a cycle.
-            return false;
-          }
-        }
-        visited->Add(scope_class_id);
-      }
-      // Check the bounds of this function type.
-      const intptr_t num_type_params = scope_class.NumTypeParameters();
-      TypeParameter& type_param = TypeParameter::Handle();
-      const TypeArguments& type_params =
-          TypeArguments::Handle(scope_class.type_parameters());
-      ASSERT((type_params.IsNull() && (num_type_params == 0)) ||
-             (type_params.Length() == num_type_params));
-      for (intptr_t i = 0; i < num_type_params; i++) {
-        type_param ^= type_params.TypeAt(i);
-        other_type = type_param.bound();
-        if (!IsTypedefCycleFree(cls, other_type, visited)) {
-          return false;
-        }
-      }
-      // Check the result type of the signature of this function type.
-      other_type = signature_function.result_type();
-      if (!IsTypedefCycleFree(cls, other_type, visited)) {
-        return false;
-      }
-      // Check the parameter types of the signature of this function type.
-      const intptr_t num_parameters = signature_function.NumParameters();
-      for (intptr_t i = 0; i < num_parameters; i++) {
-        other_type = signature_function.ParameterTypeAt(i);
-        if (!IsTypedefCycleFree(cls, other_type, visited)) {
-          return false;
-        }
-      }
-    }
-    const TypeArguments& type_args = TypeArguments::Handle(type.arguments());
-    if (!type_args.IsNull()) {
-      for (intptr_t i = 0; i < type_args.Length(); i++) {
-        other_type = type_args.TypeAt(i);
-        if (!IsTypedefCycleFree(cls, other_type, visited)) {
-          return false;
-        }
-      }
-    }
-    if (checking_typedef) {
-      visited->RemoveLast();
-    }
-  }
-  return true;
-}
-
-// For a class used as an interface marks this class and all its superclasses
-// implemented.
-//
-// Does not mark its interfaces implemented because those would already be
-// marked as such.
-static void MarkImplemented(Zone* zone, const Class& iface) {
-  if (iface.is_implemented()) {
-    return;
-  }
-
-  Class& cls = Class::Handle(zone, iface.raw());
-  AbstractType& type = AbstractType::Handle(zone);
-
-  while (!cls.is_implemented()) {
-    cls.set_is_implemented();
-
-    type = cls.super_type();
-    if (type.IsNull() || type.IsObjectType()) {
-      break;
-    }
-    cls = type.type_class();
-  }
-}
-
-// Recursively walks the graph of explicitly declared super type and
-// interfaces.
-// Reports an error if there is a cycle in the graph. We detect cycles by
-// remembering interfaces we've visited in each path through the
-// graph. If we visit an interface a second time on a given path,
-// we found a loop.
-void ClassFinalizer::CheckSuperTypeAndInterfaces(
-    const Class& cls,
-    GrowableArray<intptr_t>* visited) {
-  if (cls.is_cycle_free()) {
-    return;
-  }
-  ASSERT(visited != NULL);
-  if (FLAG_trace_class_finalization) {
-    THR_Print("Checking super and interfaces: %s\n", cls.ToCString());
-  }
-  Zone* zone = Thread::Current()->zone();
-  const intptr_t cls_index = cls.id();
-  for (intptr_t i = 0; i < visited->length(); i++) {
-    if ((*visited)[i] == cls_index) {
-      // We have already visited class 'cls'. We found a cycle.
-      const String& class_name = String::Handle(zone, cls.Name());
-      ReportError(cls, cls.token_pos(), "cyclic reference found for class '%s'",
-                  class_name.ToCString());
-    }
-  }
-
-  // If the class/interface has no explicit super class/interfaces, we are done.
-  AbstractType& super_type = AbstractType::Handle(zone, cls.super_type());
-  Array& super_interfaces = Array::Handle(zone, cls.interfaces());
-  if ((super_type.IsNull() || super_type.IsObjectType()) &&
-      (super_interfaces.Length() == 0)) {
-    cls.set_is_cycle_free();
-    return;
-  }
-
-  // If cls belongs to core lib or is a synthetic class which could belong to
-  // the core library, the restrictions about allowed interfaces are lifted.
-  const bool exempt_from_hierarchy_restrictions =
-      cls.library() == Library::CoreLibrary() ||
-      String::Handle(cls.Name()).Equals(Symbols::DebugClassName());
-
-  // Check the super type and interfaces of cls.
-  visited->Add(cls_index);
-  AbstractType& interface = AbstractType::Handle(zone);
-  Class& interface_class = Class::Handle(zone);
-
-  // Check super type. Failures lead to a longjmp.
-  if (super_type.IsDynamicType()) {
-    ReportError(cls, cls.token_pos(), "class '%s' may not extend 'dynamic'",
-                String::Handle(zone, cls.Name()).ToCString());
-  }
-  interface_class = super_type.type_class();
-  if (interface_class.IsTypedefClass()) {
-    ReportError(cls, cls.token_pos(),
-                "class '%s' may not extend function type alias '%s'",
-                String::Handle(zone, cls.Name()).ToCString(),
-                String::Handle(zone, super_type.UserVisibleName()).ToCString());
-  }
-  if (interface_class.is_enum_class()) {
-    ReportError(cls, cls.token_pos(), "class '%s' may not extend enum '%s'",
-                String::Handle(zone, cls.Name()).ToCString(),
-                String::Handle(zone, interface_class.Name()).ToCString());
-  }
-
-  // If cls belongs to core lib or to core lib's implementation, restrictions
-  // about allowed interfaces are lifted.
-  if (!exempt_from_hierarchy_restrictions) {
-    // Prevent extending core implementation classes.
-    bool is_error = false;
-    switch (interface_class.id()) {
-      case kNumberCid:
-      case kIntegerCid:  // Class Integer, not int.
-      case kSmiCid:
-      case kMintCid:
-      case kDoubleCid:  // Class Double, not double.
-      case kOneByteStringCid:
-      case kTwoByteStringCid:
-      case kExternalOneByteStringCid:
-      case kExternalTwoByteStringCid:
-      case kBoolCid:
-      case kNullCid:
-      case kArrayCid:
-      case kImmutableArrayCid:
-      case kGrowableObjectArrayCid:
-#define DO_NOT_EXTEND_TYPED_DATA_CLASSES(clazz)                                \
-  case kTypedData##clazz##Cid:                                                 \
-  case kTypedData##clazz##ViewCid:                                             \
-  case kExternalTypedData##clazz##Cid:
-        CLASS_LIST_TYPED_DATA(DO_NOT_EXTEND_TYPED_DATA_CLASSES)
-#undef DO_NOT_EXTEND_TYPED_DATA_CLASSES
-      case kByteDataViewCid:
-      case kWeakPropertyCid:
-        is_error = true;
-        break;
-      default: {
-        // Special case: classes for which we don't have a known class id.
-        if (super_type.IsDoubleType() || super_type.IsIntType() ||
-            super_type.IsStringType()) {
-          is_error = true;
-        }
-        break;
-      }
-    }
-    if (is_error) {
-      const String& interface_name =
-          String::Handle(zone, interface_class.Name());
-      ReportError(cls, cls.token_pos(), "'%s' is not allowed to extend '%s'",
-                  String::Handle(zone, cls.Name()).ToCString(),
-                  interface_name.ToCString());
-    }
-  }
-  // Now check the super interfaces of the super type.
-  CheckSuperTypeAndInterfaces(interface_class, visited);
-
-  // Check interfaces. Failures lead to a longjmp.
-  for (intptr_t i = 0; i < super_interfaces.Length(); i++) {
-    interface ^= super_interfaces.At(i);
-    ASSERT(!interface.IsTypeParameter());  // Should be detected by parser.
-    if (interface.IsDynamicType()) {
-      ReportError(cls, cls.token_pos(),
-                  "'dynamic' may not be used as interface");
-    }
-    interface_class = interface.type_class();
-    if (interface_class.IsTypedefClass()) {
-      const String& interface_name =
-          String::Handle(zone, interface_class.Name());
-      ReportError(cls, cls.token_pos(),
-                  "function type alias '%s' may not be used as interface",
-                  interface_name.ToCString());
-    }
-    if (interface_class.is_enum_class()) {
-      const String& interface_name =
-          String::Handle(zone, interface_class.Name());
-      ReportError(cls, cls.token_pos(),
-                  "enum '%s' may not be used as interface",
-                  interface_name.ToCString());
-    }
-    // Verify that unless cls belongs to core lib, it cannot extend, implement,
-    // or mixin any of Null, bool, num, int, double, String, dynamic.
-    if (!exempt_from_hierarchy_restrictions) {
-      if (interface.IsBoolType() || interface.IsNullType() ||
-          interface.IsNumberType() || interface.IsIntType() ||
-          interface.IsDoubleType() || interface.IsStringType() ||
-          interface.IsDynamicType()) {
-        const String& interface_name =
-            String::Handle(zone, interface_class.Name());
-        ReportError(cls, cls.token_pos(),
-                    "'%s' is not allowed to extend or implement '%s'",
-                    String::Handle(zone, cls.Name()).ToCString(),
-                    interface_name.ToCString());
-      }
-    }
-
-    // Now check the super interfaces.
-    CheckSuperTypeAndInterfaces(interface_class, visited);
-    MarkImplemented(zone, interface_class);
-  }
-  visited->RemoveLast();
-  cls.set_is_cycle_free();
-}
-
-// A class is marked as constant if it has one constant constructor.
-// A constant class can only have final instance fields.
-// Note: we must check for cycles before checking for const properties.
-void ClassFinalizer::CheckForLegalConstClass(const Class& cls) {
-  ASSERT(cls.is_const());
-  const Array& fields_array = Array::Handle(cls.fields());
-  intptr_t len = fields_array.Length();
-  Field& field = Field::Handle();
-  for (intptr_t i = 0; i < len; i++) {
-    field ^= fields_array.At(i);
-    if (!field.is_static() && !field.is_final()) {
-      const String& class_name = String::Handle(cls.Name());
-      const String& field_name = String::Handle(field.name());
-      ReportError(cls, field.token_pos(),
-                  "const class '%s' has non-final field '%s'",
-                  class_name.ToCString(), field_name.ToCString());
-    }
-  }
-}
-
 void ClassFinalizer::PrintClassInformation(const Class& cls) {
   Thread* thread = Thread::Current();
   HANDLESCOPE(thread);
@@ -1704,6 +1385,7 @@
   String& name = String::Handle(zone);
   String& expected_name = String::Handle(zone);
   Error& error = Error::Handle(zone);
+  TypeParameter& type_param = TypeParameter::Handle(zone);
 
   // First verify field offsets of all the TypedDataView classes.
   for (intptr_t cid = kTypedDataInt8ArrayViewCid;
@@ -1762,6 +1444,15 @@
   name ^= field.name();
   expected_name ^= String::New("_data");
   ASSERT(String::EqualsIgnoringPrivateKey(name, expected_name));
+
+  // Now verify field offsets of 'Pointer' class.
+  cls = class_table.At(kFfiPointerCid);
+  error = cls.EnsureIsFinalized(thread);
+  ASSERT(error.IsNull());
+  ASSERT(cls.NumOwnTypeArguments() == 1);
+  type_param ^= TypeParameter::RawCast(
+      TypeArguments::Handle(cls.type_parameters()).TypeAt(0));
+  ASSERT(Pointer::kNativeTypeArgPos == type_param.index());
 #endif
 }
 
diff --git a/runtime/vm/class_finalizer.h b/runtime/vm/class_finalizer.h
index a720aa0..91292e9 100644
--- a/runtime/vm/class_finalizer.h
+++ b/runtime/vm/class_finalizer.h
@@ -74,13 +74,6 @@
 
  private:
   static void AllocateEnumValues(const Class& enum_cls);
-  static bool IsSuperCycleFree(const Class& cls);
-  static bool IsTypedefCycleFree(const Class& cls,
-                                 const AbstractType& type,
-                                 GrowableArray<intptr_t>* visited);
-  static void CheckForLegalConstClass(const Class& cls);
-  static void CheckSuperTypeAndInterfaces(const Class& cls,
-                                          GrowableArray<intptr_t>* visited);
   static void FinalizeTypeParameters(const Class& cls,
                                      PendingTypes* pending_types = NULL);
   static intptr_t ExpandAndFinalizeTypeArguments(const Class& cls,
diff --git a/runtime/vm/class_finalizer_test.cc b/runtime/vm/class_finalizer_test.cc
index 42fee86..a1440d2 100644
--- a/runtime/vm/class_finalizer_test.cc
+++ b/runtime/vm/class_finalizer_test.cc
@@ -51,23 +51,4 @@
   EXPECT(ClassFinalizer::ProcessPendingClasses());
 }
 
-ISOLATE_UNIT_TEST_CASE(ClassFinalize_Cycles) {
-  Zone* zone = thread->zone();
-  Isolate* isolate = thread->isolate();
-  ObjectStore* object_store = isolate->object_store();
-  const GrowableObjectArray& pending_classes =
-      GrowableObjectArray::Handle(zone, object_store->pending_classes());
-  GrowableArray<const Class*> classes;
-  classes.Add(&Class::Handle(CreateTestClass("Jungfrau")));
-  pending_classes.Add(*classes[0]);
-  classes.Add(&Class::Handle(CreateTestClass("Eiger")));
-  pending_classes.Add(*classes[1]);
-  // Create a cycle.
-  classes[0]->set_super_type(
-      Type::Handle(Type::NewNonParameterizedType(*classes[1])));
-  classes[1]->set_super_type(
-      Type::Handle(Type::NewNonParameterizedType(*classes[0])));
-  EXPECT(!ClassFinalizer::ProcessPendingClasses());
-}
-
 }  // namespace dart
diff --git a/runtime/vm/class_id.h b/runtime/vm/class_id.h
index 90b1988..ddbd7a0 100644
--- a/runtime/vm/class_id.h
+++ b/runtime/vm/class_id.h
@@ -19,6 +19,7 @@
   V(ClosureData)                                                               \
   V(SignatureData)                                                             \
   V(RedirectionData)                                                           \
+  V(FfiTrampolineData)                                                         \
   V(Field)                                                                     \
   V(Script)                                                                    \
   V(Library)                                                                   \
@@ -65,6 +66,8 @@
   V(Float64x2)                                                                 \
   V(TypedData)                                                                 \
   V(ExternalTypedData)                                                         \
+  V(Pointer)                                                                   \
+  V(DynamicLibrary)                                                            \
   V(Capability)                                                                \
   V(ReceivePort)                                                               \
   V(SendPort)                                                                  \
@@ -102,6 +105,27 @@
   V(Int32x4Array)                                                              \
   V(Float64x2Array)
 
+#define CLASS_LIST_FFI_TYPE_MARKER(V)                                          \
+  V(Int8)                                                                      \
+  V(Int16)                                                                     \
+  V(Int32)                                                                     \
+  V(Int64)                                                                     \
+  V(Uint8)                                                                     \
+  V(Uint16)                                                                    \
+  V(Uint32)                                                                    \
+  V(Uint64)                                                                    \
+  V(IntPtr)                                                                    \
+  V(Float)                                                                     \
+  V(Double)                                                                    \
+  V(Void)
+
+#define CLASS_LIST_FFI(V)                                                      \
+  V(Pointer)                                                                   \
+  V(NativeFunction)                                                            \
+  CLASS_LIST_FFI_TYPE_MARKER(V)                                                \
+  V(NativeType)                                                                \
+  V(DynamicLibrary)
+
 #define DART_CLASS_LIST_TYPED_DATA(V)                                          \
   V(Int8)                                                                      \
   V(Uint8)                                                                     \
@@ -152,6 +176,10 @@
   CLASS_LIST(DEFINE_OBJECT_KIND)
 #undef DEFINE_OBJECT_KIND
 
+#define DEFINE_OBJECT_KIND(clazz) kFfi##clazz##Cid,
+      CLASS_LIST_FFI(DEFINE_OBJECT_KIND)
+#undef DEFINE_OBJECT_KIND
+
 // clang-format off
 #define DEFINE_OBJECT_KIND(clazz) kTypedData##clazz##Cid,
   CLASS_LIST_TYPED_DATA(DEFINE_OBJECT_KIND)
diff --git a/runtime/vm/class_table.cc b/runtime/vm/class_table.cc
index 21ea84d..6da5677 100644
--- a/runtime/vm/class_table.cc
+++ b/runtime/vm/class_table.cc
@@ -205,11 +205,9 @@
   }
 }
 
-#if defined(DEBUG)
 void ClassTable::Unregister(intptr_t index) {
   table_[index] = ClassAndSize(NULL);
 }
-#endif
 
 void ClassTable::Remap(intptr_t* old_to_new_cid) {
   ASSERT(Thread::Current()->IsAtSafepoint());
diff --git a/runtime/vm/class_table.h b/runtime/vm/class_table.h
index b87d242..bbf55b9 100644
--- a/runtime/vm/class_table.h
+++ b/runtime/vm/class_table.h
@@ -226,9 +226,7 @@
 
   void AllocateIndex(intptr_t index);
 
-#if defined(DEBUG)
   void Unregister(intptr_t index);
-#endif
 
   void Remap(intptr_t* old_to_new_cids);
 
diff --git a/runtime/vm/clustered_snapshot.cc b/runtime/vm/clustered_snapshot.cc
index 7261e1c..2f07321 100644
--- a/runtime/vm/clustered_snapshot.cc
+++ b/runtime/vm/clustered_snapshot.cc
@@ -876,16 +876,16 @@
         s->Push(field->ptr()->value_.static_value_);
       } else {
         // Otherwise, for static fields we write out the initial static value.
-        s->Push(field->ptr()->initializer_.saved_value_);
+        s->Push(field->ptr()->saved_initial_value_);
       }
     } else {
       s->Push(field->ptr()->value_.offset_);
     }
-    // Write out the initializer function or saved initial value.
-    if (kind == Snapshot::kFullAOT) {
-      s->Push(field->ptr()->initializer_.precompiled_);
-    } else {
-      s->Push(field->ptr()->initializer_.saved_value_);
+    // Write out the initializer function
+    s->Push(field->ptr()->initializer_);
+    if (kind != Snapshot::kFullAOT) {
+      // Write out the saved initial value
+      s->Push(field->ptr()->saved_initial_value_);
     }
     if (kind != Snapshot::kFullAOT) {
       // Write out the guarded list length.
@@ -927,16 +927,15 @@
           WriteField(field, value_.static_value_);
         } else {
           // Otherwise, for static fields we write out the initial static value.
-          WriteField(field, initializer_.saved_value_);
+          WriteField(field, saved_initial_value_);
         }
       } else {
         WriteField(field, value_.offset_);
       }
       // Write out the initializer function or saved initial value.
-      if (kind == Snapshot::kFullAOT) {
-        WriteField(field, initializer_.precompiled_);
-      } else {
-        WriteField(field, initializer_.saved_value_);
+      WriteField(field, initializer_);
+      if (kind != Snapshot::kFullAOT) {
+        WriteField(field, saved_initial_value_);
       }
       if (kind != Snapshot::kFullAOT) {
         // Write out the guarded list length.
@@ -1051,7 +1050,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawScript* script = objects_[i];
-      AutoTraceObject(script);
+      AutoTraceObjectName(script, script->ptr()->url_);
       WriteFromTo(script);
       s->Write<int32_t>(script->ptr()->line_offset_);
       s->Write<int32_t>(script->ptr()->col_offset_);
@@ -1128,7 +1127,6 @@
       s->Write<int32_t>(lib->ptr()->index_);
       s->Write<uint16_t>(lib->ptr()->num_imports_);
       s->Write<int8_t>(lib->ptr()->load_state_);
-      s->Write<bool>(lib->ptr()->corelib_imported_);
       s->Write<bool>(lib->ptr()->is_dart_scheme_);
       s->Write<bool>(lib->ptr()->debuggable_);
       if (s->kind() != Snapshot::kFullAOT) {
@@ -1170,7 +1168,6 @@
       lib->ptr()->index_ = d->Read<int32_t>();
       lib->ptr()->num_imports_ = d->Read<uint16_t>();
       lib->ptr()->load_state_ = d->Read<int8_t>();
-      lib->ptr()->corelib_imported_ = d->Read<bool>();
       lib->ptr()->is_dart_scheme_ = d->Read<bool>();
       lib->ptr()->debuggable_ = d->Read<bool>();
       lib->ptr()->is_in_fullsnapshot_ = true;
@@ -1576,7 +1573,9 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawBytecode* bytecode = objects_[i];
+      s->Write<int32_t>(bytecode->ptr()->instructions_size_);
       WriteFromTo(bytecode);
+      s->Write<int32_t>(bytecode->ptr()->instructions_binary_offset_);
       s->Write<int32_t>(bytecode->ptr()->source_positions_binary_offset_);
     }
   }
@@ -1608,10 +1607,25 @@
       RawBytecode* bytecode = reinterpret_cast<RawBytecode*>(d->Ref(id));
       Deserializer::InitializeHeader(bytecode, kBytecodeCid,
                                      Bytecode::InstanceSize(), is_vm_object);
+      bytecode->ptr()->instructions_ = 0;
+      bytecode->ptr()->instructions_size_ = d->Read<int32_t>();
       ReadFromTo(bytecode);
+      bytecode->ptr()->instructions_binary_offset_ = d->Read<int32_t>();
       bytecode->ptr()->source_positions_binary_offset_ = d->Read<int32_t>();
     }
   }
+
+  void PostLoad(const Array& refs, Snapshot::Kind kind, Zone* zone) {
+    Bytecode& bytecode = Bytecode::Handle(zone);
+    ExternalTypedData& binary = ExternalTypedData::Handle(zone);
+
+    for (intptr_t i = start_index_; i < stop_index_; i++) {
+      bytecode ^= refs.At(i);
+      binary = bytecode.GetBinary(zone);
+      bytecode.set_instructions(reinterpret_cast<uword>(
+          binary.DataAddr(bytecode.instructions_binary_offset())));
+    }
+  }
 };
 
 class ObjectPoolSerializationCluster : public SerializationCluster {
@@ -2147,7 +2161,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawUnlinkedCall* unlinked = objects_[i];
-      AutoTraceObject(unlinked);
+      AutoTraceObjectName(unlinked, unlinked->ptr()->target_name_);
       WriteFromTo(unlinked);
     }
   }
@@ -2214,7 +2228,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawICData* ic = objects_[i];
-      AutoTraceObject(ic);
+      AutoTraceObjectName(ic, ic->ptr()->target_name_);
       WriteFromTo(ic);
       if (kind != Snapshot::kFullAOT) {
         NOT_IN_PRECOMPILED(s->Write<int32_t>(ic->ptr()->deopt_id_));
@@ -2284,7 +2298,7 @@
     intptr_t count = objects_.length();
     for (intptr_t i = 0; i < count; i++) {
       RawMegamorphicCache* cache = objects_[i];
-      AutoTraceObject(cache);
+      AutoTraceObjectName(cache, cache->ptr()->target_name_);
       WriteFromTo(cache);
       s->Write<int32_t>(cache->ptr()->filled_entry_count_);
     }
@@ -3142,7 +3156,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 class MintSerializationCluster : public SerializationCluster {
  public:
-  MintSerializationCluster() : SerializationCluster("Mint") {}
+  MintSerializationCluster() : SerializationCluster("int") {}
   ~MintSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
@@ -3230,7 +3244,7 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 class DoubleSerializationCluster : public SerializationCluster {
  public:
-  DoubleSerializationCluster() : SerializationCluster("Double") {}
+  DoubleSerializationCluster() : SerializationCluster("double") {}
   ~DoubleSerializationCluster() {}
 
   void Trace(Serializer* s, RawObject* object) {
@@ -4659,9 +4673,10 @@
   // These objects are always allocated by Object::InitOnce, so they are not
   // written into the snapshot.
 
-  AddBaseObject(Object::null(), "Null", "<null>");
-  AddBaseObject(Object::sentinel().raw(), "Sentinel");
-  AddBaseObject(Object::transition_sentinel().raw(), "Sentinel");
+  AddBaseObject(Object::null(), "Null", "null");
+  AddBaseObject(Object::sentinel().raw(), "Null", "sentinel");
+  AddBaseObject(Object::transition_sentinel().raw(), "Null",
+                "transition_sentinel");
   AddBaseObject(Object::empty_array().raw(), "Array", "<empty_array>");
   AddBaseObject(Object::zero_array().raw(), "Array", "<zero_array>");
   AddBaseObject(Object::dynamic_type().raw(), "Type", "<dynamic type>");
@@ -4687,8 +4702,8 @@
                   "ArgumentsDescriptor", "<cached arguments descriptor>");
   }
   for (intptr_t i = 0; i < ICData::kCachedICDataArrayCount; i++) {
-    AddBaseObject(ICData::cached_icdata_arrays_[i], "ICData",
-                  "<cached icdata>");
+    AddBaseObject(ICData::cached_icdata_arrays_[i], "Array",
+                  "<empty icdata entries>");
   }
 
   ClassTable* table = isolate()->class_table();
@@ -5249,7 +5264,7 @@
   }
 
   thread()->isolate()->class_table()->CopySizesFromClassObjects();
-  heap_->old_space()->EvaluateSnapshotLoad();
+  heap_->old_space()->EvaluateAfterLoading();
 
 #if defined(DEBUG)
   Isolate* isolate = thread()->isolate();
diff --git a/runtime/vm/compilation_trace.cc b/runtime/vm/compilation_trace.cc
index 442db7c..29cdfa2 100644
--- a/runtime/vm/compilation_trace.cc
+++ b/runtime/vm/compilation_trace.cc
@@ -320,13 +320,17 @@
 static char* CompilerFlags() {
   TextBuffer buffer(64);
 
-#define ADD_FLAG(flag) buffer.AddString(FLAG_##flag ? " " #flag : "no " #flag)
+#define ADD_FLAG(flag) buffer.AddString(FLAG_##flag ? " " #flag : " no-" #flag)
   ADD_FLAG(enable_asserts);
   ADD_FLAG(use_field_guards);
   ADD_FLAG(use_osr);
   ADD_FLAG(causal_async_stacks);
   ADD_FLAG(fields_may_be_reset);
 #undef ADD_FLAG
+  buffer.AddString(FLAG_use_bytecode_compiler || FLAG_enable_interpreter
+                       ? " bytecode"
+                       : " no-bytecode");
+
   return buffer.Steal();
 }
 
diff --git a/runtime/vm/compiler/aot/aot_call_specializer.cc b/runtime/vm/compiler/aot/aot_call_specializer.cc
index 9c0544a..23e66c0 100644
--- a/runtime/vm/compiler/aot/aot_call_specializer.cc
+++ b/runtime/vm/compiler/aot/aot_call_specializer.cc
@@ -416,7 +416,7 @@
 }
 
 // Modulo against a constant power-of-two can be optimized into a mask.
-// x % y -> x & (y - 1)
+// x % y -> x & (|y| - 1)  for smi masks only
 Definition* AotCallSpecializer::TryOptimizeMod(TemplateDartCall<0>* instr,
                                                Token::Kind op_kind,
                                                Value* left_value,
@@ -426,8 +426,11 @@
   }
 
   const Object& rhs = right_value->BoundConstant();
-  int64_t modulus = Utils::Abs(rhs.IsSmi() ? Smi::Cast(rhs).Value()
-                                           : Mint::Cast(rhs).value());
+  const int64_t value = Integer::Cast(rhs).AsInt64Value();  // smi and mint
+  if (value == kMinInt64) {
+    return nullptr;  // non-smi mask
+  }
+  const int64_t modulus = Utils::Abs(value);
   if (!Utils::IsPowerOfTwo(modulus) || !Smi::IsValid(modulus - 1)) {
     return nullptr;
   }
@@ -622,13 +625,13 @@
     return false;
   }
 
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
+    return false;
+  }
+
   Definition* replacement = NULL;
 
   if (instr->ArgumentCount() == 2) {
-    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
-      return false;
-    }
-
     Value* left_value = instr->PushArgumentAt(0)->value();
     Value* right_value = instr->PushArgumentAt(1)->value();
     CompileType* left_type = left_value->Type();
diff --git a/runtime/vm/compiler/aot/precompiler.cc b/runtime/vm/compiler/aot/precompiler.cc
index bc61d2a..2187130 100644
--- a/runtime/vm/compiler/aot/precompiler.cc
+++ b/runtime/vm/compiler/aot/precompiler.cc
@@ -325,7 +325,6 @@
 
       // Clear these before dropping classes as they may hold onto otherwise
       // dead instances of classes we will remove or otherwise unused symbols.
-      DropScriptData();
       I->object_store()->set_unique_dynamic_targets(Array::null_array());
       Class& null_class = Class::Handle(Z);
       Function& null_function = Function::Handle(Z);
@@ -367,7 +366,7 @@
     Symbols::GetStats(I, &symbols_before, &capacity);
   }
 
-  Symbols::Compact(I);
+  Symbols::Compact();
 
   if (FLAG_trace_precompiler) {
     Symbols::GetStats(I, &symbols_after, &capacity);
@@ -878,8 +877,8 @@
       // Should not be in the middle of initialization while precompiling.
       ASSERT(value.raw() != Object::transition_sentinel().raw());
 
-      if (!field.HasPrecompiledInitializer() ||
-          !Function::Handle(Z, field.PrecompiledInitializer()).HasCode()) {
+      if (!field.HasInitializer() ||
+          !Function::Handle(Z, field.Initializer()).HasCode()) {
         if (FLAG_trace_precompiler) {
           THR_Print("Precompiling initializer for %s\n", field.ToCString());
         }
@@ -891,7 +890,7 @@
         const Function& initializer =
             Function::Handle(Z, CompileStaticInitializer(field));
         ASSERT(!initializer.IsNull());
-        field.SetPrecompiledInitializer(initializer);
+        field.SetInitializer(initializer);
         AddCalleesOf(initializer, gop_offset);
       }
     }
@@ -1538,12 +1537,13 @@
   {
     CanonicalTypeSet types_table(Z, object_store->canonical_types());
     types_array = HashTables::ToArray(types_table, false);
-    for (intptr_t i = 0; i < (types_array.Length() - 1); i++) {
+    for (intptr_t i = 0; i < types_array.Length(); i++) {
       type ^= types_array.At(i);
       bool retain = types_to_retain_.HasKey(&type);
       if (retain) {
         retained_types.Add(type);
       } else {
+        type.ClearCanonical();
         dropped_type_count_++;
       }
     }
@@ -1575,12 +1575,13 @@
     CanonicalTypeArgumentsSet typeargs_table(
         Z, object_store->canonical_type_arguments());
     typeargs_array = HashTables::ToArray(typeargs_table, false);
-    for (intptr_t i = 0; i < (typeargs_array.Length() - 1); i++) {
+    for (intptr_t i = 0; i < typeargs_array.Length(); i++) {
       typeargs ^= typeargs_array.At(i);
       bool retain = typeargs_to_retain_.HasKey(&typeargs);
       if (retain) {
         retained_typeargs.Add(typeargs);
       } else {
+        typeargs.ClearCanonical();
         dropped_typearg_count_++;
       }
     }
@@ -1602,21 +1603,6 @@
   object_store->set_canonical_type_arguments(typeargs_table.Release());
 }
 
-void Precompiler::DropScriptData() {
-  Library& lib = Library::Handle(Z);
-  Array& scripts = Array::Handle(Z);
-  Script& script = Script::Handle(Z);
-  for (intptr_t i = 0; i < libraries_.Length(); i++) {
-    lib ^= libraries_.At(i);
-    scripts = lib.LoadedScripts();
-    for (intptr_t j = 0; j < scripts.Length(); j++) {
-      script ^= scripts.At(j);
-      script.set_compile_time_constants(Array::null_array());
-      script.set_source(String::null_string());
-    }
-  }
-}
-
 void Precompiler::TraceTypesFromRetainedClasses() {
   auto& lib = Library::Handle(Z);
   auto& cls = Class::Handle(Z);
@@ -1739,6 +1725,8 @@
   Array& scripts = Array::Handle(Z);
   Script& script = Script::Handle(Z);
   KernelProgramInfo& program_info = KernelProgramInfo::Handle(Z);
+  const TypedData& null_typed_data = TypedData::Handle(Z);
+  const KernelProgramInfo& null_info = KernelProgramInfo::Handle(Z);
 
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
     lib ^= libraries_.At(i);
@@ -1772,11 +1760,6 @@
       }
       dict.SetAt(j, Object::null_object());
     }
-    lib.RehashDictionary(dict, used * 4 / 3 + 1);
-    if (!(retain_root_library_caches_ &&
-          (lib.raw() == I->object_store()->root_library()))) {
-      lib.DropDependenciesAndCaches();
-    }
 
     scripts = lib.LoadedScripts();
     if (!scripts.IsNull()) {
@@ -1785,17 +1768,34 @@
         program_info = script.kernel_program_info();
         if (!program_info.IsNull()) {
           program_info.set_constants(Array::null_array());
+          program_info.set_scripts(Array::null_array());
+          program_info.set_libraries_cache(Array::null_array());
+          program_info.set_classes_cache(Array::null_array());
+          program_info.set_bytecode_component(Array::null_array());
         }
+        script.set_resolved_url(String::null_string());
+        script.set_compile_time_constants(Array::null_array());
+        script.set_line_starts(null_typed_data);
+        script.set_debug_positions(Array::null_array());
+        script.set_yield_positions(Array::null_array());
+        script.set_kernel_program_info(null_info);
+        script.set_source(String::null_string());
       }
     }
+
+    lib.RehashDictionary(dict, used * 4 / 3 + 1);
+    if (!(retain_root_library_caches_ &&
+          (lib.raw() == I->object_store()->root_library()))) {
+      lib.DropDependenciesAndCaches();
+    }
   }
 }
 
 void Precompiler::DropClasses() {
   Class& cls = Class::Handle(Z);
   Array& constants = Array::Handle(Z);
+  const Script& null_script = Script::Handle(Z);
 
-#if defined(DEBUG)
   // We are about to remove classes from the class table. For this to be safe,
   // there must be no instances of these classes on the heap, not even
   // corpses because the class table entry may be used to find the size of
@@ -1803,7 +1803,6 @@
   // we continue.
   I->heap()->CollectAllGarbage();
   I->heap()->WaitForSweeperTasks(T);
-#endif
 
   ClassTable* class_table = I->class_table();
   intptr_t num_cids = class_table->NumCids();
@@ -1831,7 +1830,7 @@
     constants = cls.constants();
     ASSERT(constants.Length() == 0);
 
-#if defined(DEBUG)
+#if !defined(PRODUCT)
     intptr_t instances =
         class_table->StatsWithUpdatedSize(cid)->post_gc.new_count +
         class_table->StatsWithUpdatedSize(cid)->post_gc.old_count;
@@ -1846,10 +1845,9 @@
       THR_Print("Dropping class %" Pd " %s\n", cid, cls.ToCString());
     }
 
-#if defined(DEBUG)
     class_table->Unregister(cid);
-#endif
     cls.set_id(kIllegalCid);  // We check this when serializing.
+    cls.set_script(null_script);
   }
 }
 
@@ -1860,6 +1858,7 @@
       Library::Handle(Z, I->object_store()->root_library());
   Library& lib = Library::Handle(Z);
   Class& toplevel_class = Class::Handle(Z);
+  const Script& null_script = Script::Handle(Z);
 
   for (intptr_t i = 0; i < libraries_.Length(); i++) {
     lib ^= libraries_.At(i);
@@ -1894,10 +1893,10 @@
       retained_libraries.Add(lib);
     } else {
       toplevel_class = lib.toplevel_class();
-#if defined(DEBUG)
+
       I->class_table()->Unregister(toplevel_class.id());
-#endif
       toplevel_class.set_id(kIllegalCid);  // We check this when serializing.
+      toplevel_class.set_script(null_script);
 
       dropped_library_count_++;
       lib.set_index(-1);
@@ -1925,6 +1924,7 @@
       if (!function.HasCode()) {
         return;
       }
+
       code_ = function.CurrentCode();
       table_ = code_.static_calls_target_table();
       StaticCallsTable static_calls(table_);
@@ -2146,11 +2146,6 @@
       str = Symbols::New(T, str);
       str = obfuscator.Rename(str, /*atomic=*/true);
       script.set_url(str);
-
-      str = script.resolved_url();
-      str = Symbols::New(T, str);
-      str = obfuscator.Rename(str, /*atomic=*/true);
-      script.set_resolved_url(str);
     }
 
     Library& lib = Library::Handle();
diff --git a/runtime/vm/compiler/aot/precompiler.h b/runtime/vm/compiler/aot/precompiler.h
index 742a8eb..28c0a67 100644
--- a/runtime/vm/compiler/aot/precompiler.h
+++ b/runtime/vm/compiler/aot/precompiler.h
@@ -293,7 +293,6 @@
   void TraceTypesFromRetainedClasses();
   void DropTypes();
   void DropTypeArguments();
-  void DropScriptData();
   void DropMetadata();
   void DropLibraryEntries();
   void DropClasses();
diff --git a/runtime/vm/compiler/asm_intrinsifier.cc b/runtime/vm/compiler/asm_intrinsifier.cc
new file mode 100644
index 0000000..6cc847a
--- /dev/null
+++ b/runtime/vm/compiler/asm_intrinsifier.cc
@@ -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.
+// Class for intrinsifying functions.
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/asm_intrinsifier.h"
+
+namespace dart {
+namespace compiler {
+
+#if !defined(TARGET_ARCH_DBC)
+
+void AsmIntrinsifier::String_identityHash(Assembler* assembler,
+                                          Label* normal_ir_body) {
+  String_getHashCode(assembler, normal_ir_body);
+}
+
+void AsmIntrinsifier::Double_identityHash(Assembler* assembler,
+                                          Label* normal_ir_body) {
+  Double_hashCode(assembler, normal_ir_body);
+}
+
+void AsmIntrinsifier::RegExp_ExecuteMatch(Assembler* assembler,
+                                          Label* normal_ir_body) {
+  AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(assembler, normal_ir_body,
+                                                /*sticky=*/false);
+}
+
+void AsmIntrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler,
+                                                Label* normal_ir_body) {
+  AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(assembler, normal_ir_body,
+                                                /*sticky=*/true);
+}
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/asm_intrinsifier.h b/runtime/vm/compiler/asm_intrinsifier.h
new file mode 100644
index 0000000..9f7e5d7
--- /dev/null
+++ b/runtime/vm/compiler/asm_intrinsifier.h
@@ -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.
+// Class for intrinsifying functions.
+
+#ifndef RUNTIME_VM_COMPILER_ASM_INTRINSIFIER_H_
+#define RUNTIME_VM_COMPILER_ASM_INTRINSIFIER_H_
+
+#include "vm/allocation.h"
+#include "vm/compiler/recognized_methods_list.h"
+
+namespace dart {
+
+// Forward declarations.
+class FlowGraphCompiler;
+class Function;
+class TargetEntryInstr;
+class ParsedFunction;
+class FlowGraph;
+
+namespace compiler {
+class Assembler;
+class Label;
+
+class AsmIntrinsifier : public AllStatic {
+ public:
+  static intptr_t ParameterSlotFromSp();
+
+  static void IntrinsicCallPrologue(Assembler* assembler);
+  static void IntrinsicCallEpilogue(Assembler* assembler);
+
+ private:
+  friend class Intrinsifier;
+
+  // The "_A" value used in the intrinsification of
+  // `runtime/lib/math_patch.dart:_Random._nextState()`
+  static const int64_t kRandomAValue = 0xffffda61;
+
+  static bool CanIntrinsify(const Function& function);
+
+#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
+  static void enum_name(Assembler* assembler, Label* normal_ir_body);
+  ALL_INTRINSICS_LIST(DECLARE_FUNCTION)
+
+  // On DBC all intrinsics are handled the same way.
+#if defined(TARGET_ARCH_DBC)
+  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
+#endif  // defined(TARGET_ARCH_DBC)
+
+#undef DECLARE_FUNCTION
+
+  static void IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                           Label* normal_ir_body,
+                                           bool sticky);
+};
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_ASM_INTRINSIFIER_H_
diff --git a/runtime/vm/compiler/intrinsifier_arm.cc b/runtime/vm/compiler/asm_intrinsifier_arm.cc
similarity index 70%
rename from runtime/vm/compiler/intrinsifier_arm.cc
rename to runtime/vm/compiler/asm_intrinsifier_arm.cc
index beb9d4e..c00607e 100644
--- a/runtime/vm/compiler/intrinsifier_arm.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm.cc
@@ -1,23 +1,18 @@
-// Copyright (c) 2013, 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.
 
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM.
 #if defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
 
-#include "vm/compiler/intrinsifier.h"
+#define SHOULD_NOT_INCLUDE_RUNTIME
 
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp_assembler.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
 
 namespace dart {
+namespace compiler {
 
 // When entering intrinsics code:
 // R4: Arguments descriptor
@@ -29,7 +24,7 @@
 
 #define __ assembler->
 
-intptr_t Intrinsifier::ParameterSlotFromSp() {
+intptr_t AsmIntrinsifier::ParameterSlotFromSp() {
   return -1;
 }
 
@@ -37,7 +32,7 @@
   return ((1 << reg) & kAbiPreservedCpuRegs) != 0;
 }
 
-void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
   ASSERT(IsABIPreservedRegister(CODE_REG));
   ASSERT(IsABIPreservedRegister(ARGS_DESC_REG));
   ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
@@ -47,49 +42,50 @@
   assembler->mov(CALLEE_SAVED_TEMP, Operand(LR));
 }
 
-void Intrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   // Restore LR.
   assembler->Comment("IntrinsicCallEpilogue");
   assembler->mov(LR, Operand(CALLEE_SAVED_TEMP));
 }
 
-// Allocate a GrowableObjectArray using the backing array specified.
+// Allocate a GrowableObjectArray:: using the backing array specified.
 // On stack: type argument (+1), data (+0).
-void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
   // The newly allocated object is returned in R0.
-  const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
-  const intptr_t kArrayOffset = 0 * kWordSize;
+  const intptr_t kTypeArgumentsOffset = 1 * target::kWordSize;
+  const intptr_t kArrayOffset = 0 * target::kWordSize;
 
   // Try allocating in new space.
-  const Class& cls = Class::Handle(
-      Isolate::Current()->object_store()->growable_object_array_class());
+  const Class& cls = GrowableObjectArrayClass();
   __ TryAllocate(cls, normal_ir_body, R0, R1);
 
   // Store backing array object in growable array object.
   __ ldr(R1, Address(SP, kArrayOffset));  // Data argument.
   // R0 is new, no barrier needed.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, GrowableObjectArray::data_offset()), R1);
+      R0, FieldAddress(R0, target::GrowableObjectArray::data_offset()), R1);
 
   // R0: new growable array object start as a tagged pointer.
   // Store the type argument field in the growable array object.
   __ ldr(R1, Address(SP, kTypeArgumentsOffset));  // Type argument.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), R1);
+      R0,
+      FieldAddress(R0, target::GrowableObjectArray::type_arguments_offset()),
+      R1);
 
   // Set the length field in the growable array object to 0.
   __ LoadImmediate(R1, 0);
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, GrowableObjectArray::length_offset()), R1);
+      R0, FieldAddress(R0, target::GrowableObjectArray::length_offset()), R1);
   __ Ret();  // Returns the newly allocated object in R0.
 
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
+#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_shift)                      \
   Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  const intptr_t kArrayLengthStackOffset = 0 * target::kWordSize;              \
   NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R2, cid));                      \
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(R2, normal_ir_body));                 \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
@@ -106,10 +102,11 @@
   __ b(normal_ir_body, GT);                                                    \
   __ mov(R2, Operand(R2, LSL, scale_shift));                                   \
   const intptr_t fixed_size_plus_alignment_padding =                           \
-      sizeof(Raw##type_name) + kObjectAlignment - 1;                           \
+      target::TypedData::InstanceSize() +                                      \
+      target::ObjectAlignment::kObjectAlignment - 1;                           \
   __ AddImmediate(R2, fixed_size_plus_alignment_padding);                      \
-  __ bic(R2, R2, Operand(kObjectAlignment - 1));                               \
-  __ ldr(R0, Address(THR, Thread::top_offset()));                              \
+  __ bic(R2, R2, Operand(target::ObjectAlignment::kObjectAlignment - 1));      \
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));                      \
                                                                                \
   /* R2: allocation size. */                                                   \
   __ adds(R1, R0, Operand(R2));                                                \
@@ -119,14 +116,14 @@
   /* R0: potential new object start. */                                        \
   /* R1: potential next object start. */                                       \
   /* R2: allocation size. */                                                   \
-  __ ldr(IP, Address(THR, Thread::end_offset()));                              \
+  __ ldr(IP, Address(THR, target::Thread::end_offset()));                      \
   __ cmp(R1, Operand(IP));                                                     \
   __ b(normal_ir_body, CS);                                                    \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
   NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid));                      \
-  __ str(R1, Address(THR, Thread::top_offset()));                              \
+  __ str(R1, Address(THR, target::Thread::top_offset()));                      \
   __ AddImmediate(R0, kHeapObjectTag);                                         \
   /* Initialize the tags. */                                                   \
   /* R0: new object start as a tagged pointer. */                              \
@@ -134,19 +131,20 @@
   /* R2: allocation size. */                                                   \
   /* R4: allocation stats address */                                           \
   {                                                                            \
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);                  \
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);            \
     __ mov(R3,                                                                 \
-           Operand(R2, LSL, RawObject::kSizeTagPos - kObjectAlignmentLog2),    \
+           Operand(R2, LSL,                                                    \
+                   target::RawObject::kTagBitsSizeTagPos -                     \
+                       target::ObjectAlignment::kObjectAlignmentLog2),         \
            LS);                                                                \
     __ mov(R3, Operand(0), HI);                                                \
                                                                                \
     /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags = 0;                                                         \
-    tags = RawObject::ClassIdTag::update(cid, tags);                           \
-    tags = RawObject::NewBit::update(true, tags);                              \
+    uint32_t tags =                                                            \
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
     __ LoadImmediate(TMP, tags);                                               \
     __ orr(R3, R3, Operand(TMP));                                              \
-    __ str(R3, FieldAddress(R0, type_name::tags_offset())); /* Tags. */        \
+    __ str(R3, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */   \
   }                                                                            \
   /* Set the length field. */                                                  \
   /* R0: new object start as a tagged pointer. */                              \
@@ -155,7 +153,7 @@
   /* R4: allocation stats address. */                                          \
   __ ldr(R3, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
   __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, type_name::length_offset()), R3);                   \
+      R0, FieldAddress(R0, target::TypedData::length_offset()), R3);           \
   /* Initialize all array elements to 0. */                                    \
   /* R0: new object start as a tagged pointer. */                              \
   /* R1: new object end address. */                                            \
@@ -166,14 +164,14 @@
   /* data area to be initialized. */                                           \
   __ LoadImmediate(R8, 0);                                                     \
   __ mov(R9, Operand(R8));                                                     \
-  __ AddImmediate(R3, R0, sizeof(Raw##type_name) - 1);                         \
+  __ AddImmediate(R3, R0, target::TypedData::InstanceSize() - 1);              \
   Label init_loop;                                                             \
   __ Bind(&init_loop);                                                         \
-  __ AddImmediate(R3, 2 * kWordSize);                                          \
+  __ AddImmediate(R3, 2 * target::kWordSize);                                  \
   __ cmp(R3, Operand(R1));                                                     \
-  __ strd(R8, R9, R3, -2 * kWordSize, LS);                                     \
+  __ strd(R8, R9, R3, -2 * target::kWordSize, LS);                             \
   __ b(&init_loop, CC);                                                        \
-  __ str(R8, Address(R3, -2 * kWordSize), HI);                                 \
+  __ str(R8, Address(R3, -2 * target::kWordSize), HI);                         \
                                                                                \
   NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2));                 \
   __ Ret();                                                                    \
@@ -197,12 +195,12 @@
 }
 
 #define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler,         \
-                                                 Label* normal_ir_body) {      \
-    intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);     \
-    intptr_t max_len = TypedData::MaxNewSpaceElements(kTypedData##clazz##Cid); \
+  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
+                                                    Label* normal_ir_body) {   \
+    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
+    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
     int shift = GetScaleFactor(size);                                          \
-    TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift); \
+    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, shift);            \
   }
 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
 #undef TYPED_DATA_ALLOCATOR
@@ -210,28 +208,28 @@
 // Loads args from stack into R0 and R1
 // Tests if they are smis, jumps to label not_smi if not.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
-  __ ldr(R0, Address(SP, +0 * kWordSize));
-  __ ldr(R1, Address(SP, +1 * kWordSize));
+  __ ldr(R0, Address(SP, +0 * target::kWordSize));
+  __ ldr(R1, Address(SP, +1 * target::kWordSize));
   __ orr(TMP, R0, Operand(R1));
   __ tst(TMP, Operand(kSmiTagMask));
   __ b(not_smi, NE);
 }
 
-void Intrinsifier::Integer_addFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_addFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ adds(R0, R0, Operand(R1));                     // Adds.
-  __ bx(LR, VC);                                    // Return if no overflow.
+  __ adds(R0, R0, Operand(R1));                      // Adds.
+  __ bx(LR, VC);                                     // Return if no overflow.
   // Otherwise fall through.
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
   Integer_addFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_subFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_subFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R0, Operand(R1));  // Subtract.
   __ bx(LR, VC);                 // Return if no overflow.
@@ -239,7 +237,7 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R1, Operand(R0));  // Subtract.
   __ bx(LR, VC);                 // Return if no overflow.
@@ -247,8 +245,8 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mulFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mulFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
   __ SmiUntag(R0);           // Untags R0. We only want result shifted by one.
   __ smull(R0, IP, R0, R1);  // IP:R0 <- R0 * R1.
@@ -257,7 +255,7 @@
   __ Bind(normal_ir_body);  // Fall through on overflow.
 }
 
-void Intrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
   Integer_mulFromInteger(assembler, normal_ir_body);
 }
 
@@ -316,14 +314,14 @@
 //      res = res + right;
 //    }
 //  }
-void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_moduloFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   if (!TargetCPUFeatures::can_divide()) {
     return;
   }
   // Check to see if we have integer division
-  __ ldr(R1, Address(SP, +0 * kWordSize));
-  __ ldr(R0, Address(SP, +1 * kWordSize));
+  __ ldr(R1, Address(SP, +0 * target::kWordSize));
+  __ ldr(R0, Address(SP, +1 * target::kWordSize));
   __ orr(TMP, R0, Operand(R1));
   __ tst(TMP, Operand(kSmiTagMask));
   __ b(normal_ir_body, NE);
@@ -349,8 +347,8 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_truncDivide(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
+                                          Label* normal_ir_body) {
   if (!TargetCPUFeatures::can_divide()) {
     return;
   }
@@ -373,9 +371,10 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_negate(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, +0 * kWordSize));  // Grab first argument.
-  __ tst(R0, Operand(kSmiTagMask));         // Test for Smi.
+void AsmIntrinsifier::Integer_negate(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Grab first argument.
+  __ tst(R0, Operand(kSmiTagMask));                 // Test for Smi.
   __ b(normal_ir_body, NE);
   __ rsbs(R0, R0, Operand(0));  // R0 is a Smi. R0 <- 0 - R0.
   __ bx(LR, VC);  // Return if there wasn't overflow, fall through otherwise.
@@ -383,8 +382,8 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
   __ and_(R0, R0, Operand(R1));
 
@@ -392,12 +391,13 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAnd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
+                                               Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
   __ orr(R0, R0, Operand(R1));
 
@@ -405,12 +405,13 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOr(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_bitOrFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
   __ eor(R0, R0, Operand(R1));
 
@@ -418,15 +419,16 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXor(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitXorFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ CompareImmediate(R0, Smi::RawValue(Smi::kBits));
+  __ CompareImmediate(R0, target::ToRawSmi(target::Smi::kBits));
   __ b(normal_ir_body, HI);
 
   __ SmiUntag(R0);
@@ -459,12 +461,12 @@
   // Now NOTFP has the bits that fall off of R1 on a left shift.
   __ mov(R1, Operand(R1, LSL, R0));  // R1 gets the low bits.
 
-  const Class& mint_class =
-      Class::Handle(Isolate::Current()->object_store()->mint_class());
+  const Class& mint_class = MintClass();
   __ TryAllocate(mint_class, normal_ir_body, R0, R2);
 
-  __ str(R1, FieldAddress(R0, Mint::value_offset()));
-  __ str(NOTFP, FieldAddress(R0, Mint::value_offset() + kWordSize));
+  __ str(R1, FieldAddress(R0, target::Mint::value_offset()));
+  __ str(NOTFP,
+         FieldAddress(R0, target::Mint::value_offset() + target::kWordSize));
   __ Ret();
   __ Bind(normal_ir_body);
 }
@@ -489,8 +491,9 @@
   __ b(not_smi_or_mint, NE);
 
   // Mint.
-  __ ldr(res_lo, FieldAddress(reg, Mint::value_offset()));
-  __ ldr(res_hi, FieldAddress(reg, Mint::value_offset() + kWordSize));
+  __ ldr(res_lo, FieldAddress(reg, target::Mint::value_offset()));
+  __ ldr(res_hi,
+         FieldAddress(reg, target::Mint::value_offset() + target::kWordSize));
   __ Bind(&done);
 }
 
@@ -504,10 +507,10 @@
   __ cmp(R1, Operand(R0));
   __ b(&is_true, true_condition);
   __ Bind(&is_false);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
   __ Bind(&is_true);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ Ret();
 
   // 64-bit comparison
@@ -551,39 +554,39 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LT);
 }
 
-void Intrinsifier::Integer_lessThan(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Integer_greaterThanFromInt(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThan(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
+                                          Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GT);
 }
 
-void Intrinsifier::Integer_lessEqualThan(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
+                                            Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LE);
 }
 
-void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterEqualThan(Assembler* assembler,
+                                               Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GE);
 }
 
 // This is called for Smi and Mint receivers. The right argument
 // can be Smi, Mint or double.
-void Intrinsifier::Integer_equalToInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   Label true_label, check_for_mint;
   // For integer receiver '===' check first.
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));
   __ cmp(R0, Operand(R1));
   __ b(&true_label, EQ);
 
@@ -592,10 +595,10 @@
   __ b(&check_for_mint, NE);  // If R0 or R1 is not a smi do Mint checks.
 
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
   __ Bind(&true_label);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ Ret();
 
   // At least one of the arguments was not Smi.
@@ -611,7 +614,8 @@
 
   __ CompareClassId(R0, kDoubleCid, R2);
   __ b(normal_ir_body, EQ);
-  __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
+  __ LoadObject(R0,
+                CastHandle<Object>(FalseObject()));  // Smi == Mint -> false.
   __ Ret();
 
   __ Bind(&receiver_not_smi);
@@ -621,18 +625,19 @@
   __ b(normal_ir_body, NE);
   // Receiver is Mint, return false if right is Smi.
   __ tst(R0, Operand(kSmiTagMask));
-  __ LoadObject(R0, Bool::False(), EQ);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), EQ);
   __ bx(LR, EQ);
   // TODO(srdjan): Implement Mint == Mint comparison.
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equal(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift amount in R0. Value to shift in R1.
 
@@ -651,15 +656,17 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Smi_bitNegate(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ mvn(R0, Operand(R0));
   __ bic(R0, R0, Operand(kSmiTagMask));  // Remove inverted smi-tag.
   __ Ret();
 }
 
-void Intrinsifier::Smi_bitLength(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ SmiUntag(R0);
   // XOR with sign bit to complement bits if value is negative.
   __ eor(R0, R0, Operand(R0, ASR, 31));
@@ -669,29 +676,29 @@
   __ Ret();
 }
 
-void Intrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
   // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi.
-  __ ldrd(R0, R1, SP, 2 * kWordSize);
+  __ ldrd(R0, R1, SP, 2 * target::kWordSize);
   // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0.
-  __ ldrd(R2, R3, SP, 0 * kWordSize);
+  __ ldrd(R2, R3, SP, 0 * target::kWordSize);
   __ SmiUntag(R3);
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R8 = &x_digits[0]
-  __ add(R8, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R8, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // NOTFP = &x_digits[x_used]
   __ add(NOTFP, R8, Operand(R0, LSL, 1));
   // R6 = &r_digits[1]
   __ add(R6, R2,
-         Operand(TypedData::data_offset() - kHeapObjectTag +
+         Operand(target::TypedData::data_offset() - kHeapObjectTag +
                  kBytesPerBigIntDigit));
   // R6 = &r_digits[x_used + n ~/ _DIGIT_BITS + 1]
   __ add(R4, R4, Operand(R0, ASR, 1));
@@ -710,25 +717,25 @@
   __ teq(NOTFP, Operand(R8));
   __ b(&loop, NE);
   __ str(R9, Address(R6, -kBytesPerBigIntDigit, Address::PreIndex));
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ Ret();
 }
 
-void Intrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
   // R0 = x_used, R1 = x_digits, x_used > 0, x_used is Smi.
-  __ ldrd(R0, R1, SP, 2 * kWordSize);
+  __ ldrd(R0, R1, SP, 2 * target::kWordSize);
   // R2 = r_digits, R3 = n, n is Smi, n % _DIGIT_BITS != 0.
-  __ ldrd(R2, R3, SP, 0 * kWordSize);
+  __ ldrd(R2, R3, SP, 0 * target::kWordSize);
   __ SmiUntag(R3);
   // R4 = n ~/ _DIGIT_BITS
   __ Asr(R4, R3, Operand(5));
   // R6 = &r_digits[0]
-  __ add(R6, R2, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R6, R2, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // NOTFP = &x_digits[n ~/ _DIGIT_BITS]
-  __ add(NOTFP, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   __ add(NOTFP, NOTFP, Operand(R4, LSL, 2));
   // R8 = &r_digits[x_used - n ~/ _DIGIT_BITS - 1]
   __ add(R4, R4, Operand(1));
@@ -753,29 +760,30 @@
   __ teq(R6, Operand(R8));
   __ b(&loop, NE);
   __ str(R9, Address(R6, 0));
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ Ret();
 }
 
-void Intrinsifier::Bigint_absAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
   // R0 = used, R1 = digits
-  __ ldrd(R0, R1, SP, 3 * kWordSize);
+  __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ add(R1, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R2 = a_used, R3 = a_digits
-  __ ldrd(R2, R3, SP, 1 * kWordSize);
+  __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8 = r_digits
-  __ ldr(R8, Address(SP, 0 * kWordSize));
+  __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -812,29 +820,30 @@
   __ adc(R4, R4, Operand(0));
   __ str(R4, Address(R8, 0));
 
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ Ret();
 }
 
-void Intrinsifier::Bigint_absSub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absSub(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
   // R0 = used, R1 = digits
-  __ ldrd(R0, R1, SP, 3 * kWordSize);
+  __ ldrd(R0, R1, SP, 3 * target::kWordSize);
   // R1 = &digits[0]
-  __ add(R1, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R1, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R2 = a_used, R3 = a_digits
-  __ ldrd(R2, R3, SP, 1 * kWordSize);
+  __ ldrd(R2, R3, SP, 1 * target::kWordSize);
   // R3 = &a_digits[0]
-  __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8 = r_digits
-  __ ldr(R8, Address(SP, 0 * kWordSize));
+  __ ldr(R8, Address(SP, 0 * target::kWordSize));
   // R8 = &r_digits[0]
-  __ add(R8, R8, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R8, R8, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // NOTFP = &digits[a_used >> 1], a_used is Smi.
   __ add(NOTFP, R1, Operand(R2, LSL, 1));
@@ -867,11 +876,12 @@
   __ b(&carry_loop, NE);
 
   __ Bind(&done);
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ Ret();
 }
 
-void Intrinsifier::Bigint_mulAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulAdd(Uint32List x_digits, int xi,
   //                    Uint32List m_digits, int i,
@@ -901,26 +911,26 @@
 
   Label done;
   // R3 = x, no_op if x == 0
-  __ ldrd(R0, R1, SP, 5 * kWordSize);  // R0 = xi as Smi, R1 = x_digits.
+  __ ldrd(R0, R1, SP, 5 * target::kWordSize);  // R0 = xi as Smi, R1 = x_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R3, FieldAddress(R1, TypedData::data_offset()));
+  __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
   // R8 = SmiUntag(n), no_op if n == 0
-  __ ldr(R8, Address(SP, 0 * kWordSize));
+  __ ldr(R8, Address(SP, 0 * target::kWordSize));
   __ Asrs(R8, R8, Operand(kSmiTagSize));
   __ b(&done, EQ);
 
   // R4 = mip = &m_digits[i >> 1]
-  __ ldrd(R0, R1, SP, 3 * kWordSize);  // R0 = i as Smi, R1 = m_digits.
+  __ ldrd(R0, R1, SP, 3 * target::kWordSize);  // R0 = i as Smi, R1 = m_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R9 = ajp = &a_digits[j >> 1]
-  __ ldrd(R0, R1, SP, 1 * kWordSize);  // R0 = j as Smi, R1 = a_digits.
+  __ ldrd(R0, R1, SP, 1 * target::kWordSize);  // R0 = j as Smi, R1 = a_digits.
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R9, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R9, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R1 = c = 0
   __ mov(R1, Operand(0));
@@ -968,11 +978,12 @@
   __ b(&propagate_carry_loop, CS);
 
   __ Bind(&done);
-  __ mov(R0, Operand(Smi::RawValue(1)));  // One digit processed.
+  __ mov(R0, Operand(target::ToRawSmi(1)));  // One digit processed.
   __ Ret();
 }
 
-void Intrinsifier::Bigint_sqrAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _sqrAdd(Uint32List x_digits, int i,
   //                    Uint32List a_digits, int used) {
@@ -1000,9 +1011,9 @@
   // }
 
   // R4 = xip = &x_digits[i >> 1]
-  __ ldrd(R2, R3, SP, 2 * kWordSize);  // R2 = i as Smi, R3 = x_digits
+  __ ldrd(R2, R3, SP, 2 * target::kWordSize);  // R2 = i as Smi, R3 = x_digits
   __ add(R3, R3, Operand(R2, LSL, 1));
-  __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -1011,9 +1022,9 @@
   __ b(&x_zero, EQ);
 
   // NOTFP = ajp = &a_digits[i]
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // a_digits
-  __ add(R1, R1, Operand(R2, LSL, 2));     // j == 2*i, i is Smi.
-  __ add(NOTFP, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
+  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
+  __ add(NOTFP, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R8:R0 = t = x*x + *ajp
   __ ldr(R0, Address(NOTFP, 0));
@@ -1028,7 +1039,7 @@
   __ mov(R9, Operand(0));
 
   // int n = used - i - 1; while (--n >= 0) ...
-  __ ldr(R0, Address(SP, 0 * kWordSize));  // used is Smi
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));  // used is Smi
   __ sub(R6, R0, Operand(R2));
   __ mov(R0, Operand(2));  // n = used - i - 2; if (n >= 0) ... while (--n >= 0)
   __ rsbs(R6, R0, Operand(R6, ASR, kSmiTagSize));
@@ -1081,17 +1092,17 @@
   __ strd(R8, R9, NOTFP, 0);
 
   __ Bind(&x_zero);
-  __ mov(R0, Operand(Smi::RawValue(1)));  // One digit processed.
+  __ mov(R0, Operand(target::ToRawSmi(1)));  // One digit processed.
   __ Ret();
 }
 
-void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
+                                                   Label* normal_ir_body) {
   // No unsigned 64-bit / 32-bit divide instruction.
 }
 
-void Intrinsifier::Montgomery_mulMod(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
+                                        Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulMod(Uint32List args, Uint32List digits, int i) {
   //   uint32_t rho = args[_RHO];  // _RHO == 2.
@@ -1102,25 +1113,25 @@
   // }
 
   // R4 = args
-  __ ldr(R4, Address(SP, 2 * kWordSize));  // args
+  __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
 
   // R3 = rho = args[2]
-  __ ldr(R3,
-         FieldAddress(R4, TypedData::data_offset() + 2 * kBytesPerBigIntDigit));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1]
-  __ ldrd(R0, R1, SP, 0 * kWordSize);  // R0 = i as Smi, R1 = digits
+  __ ldrd(R0, R1, SP, 0 * target::kWordSize);  // R0 = i as Smi, R1 = digits
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R2, FieldAddress(R1, TypedData::data_offset()));
+  __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
 
   // R1:R0 = t = rho*d
   __ umull(R0, R1, R2, R3);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ str(R0,
-         FieldAddress(R4, TypedData::data_offset() + 4 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  4 * kBytesPerBigIntDigit));
 
-  __ mov(R0, Operand(Smi::RawValue(1)));  // One digit processed.
+  __ mov(R0, Operand(target::ToRawSmi(1)));  // One digit processed.
   __ Ret();
 }
 
@@ -1130,7 +1141,7 @@
 static void TestLastArgumentIsDouble(Assembler* assembler,
                                      Label* is_smi,
                                      Label* not_double_smi) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ tst(R0, Operand(kSmiTagMask));
   __ b(is_smi, EQ);
   __ CompareClassId(R0, kDoubleCid, R1);
@@ -1151,17 +1162,17 @@
     TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
     // Both arguments are double, right operand is in R0.
 
-    __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+    __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Bind(&double_op);
-    __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
 
     __ vcmpd(D0, D1);
     __ vmstat();
-    __ LoadObject(R0, Bool::False());
+    __ LoadObject(R0, CastHandle<Object>(FalseObject()));
     // Return false if D0 or D1 was NaN before checking true condition.
     __ bx(LR, VS);
-    __ LoadObject(R0, Bool::True(), true_condition);
+    __ LoadObject(R0, CastHandle<Object>(TrueObject()), true_condition);
     __ Ret();
 
     __ Bind(&is_smi);  // Convert R0 to a double.
@@ -1173,27 +1184,28 @@
   }
 }
 
-void Intrinsifier::Double_greaterThan(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
+                                         Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, HI);
 }
 
-void Intrinsifier::Double_greaterEqualThan(Assembler* assembler,
-                                           Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
+                                              Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, CS);
 }
 
-void Intrinsifier::Double_lessThan(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
+                                      Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, CC);
 }
 
-void Intrinsifier::Double_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_equal(Assembler* assembler,
+                                   Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, EQ);
 }
 
-void Intrinsifier::Double_lessEqualThan(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
+                                           Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, LS);
 }
 
@@ -1207,10 +1219,10 @@
 
     TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
     // Both arguments are double, right operand is in R0.
-    __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+    __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Bind(&double_op);
-    __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     switch (kind) {
       case Token::kADD:
         __ vaddd(D0, D0, D1);
@@ -1227,11 +1239,10 @@
       default:
         UNREACHABLE();
     }
-    const Class& double_class =
-        Class::Handle(Isolate::Current()->object_store()->double_class());
+    const Class& double_class = DoubleClass();
     __ TryAllocate(double_class, normal_ir_body, R0,
                    R1);  // Result register.
-    __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Ret();
     __ Bind(&is_smi);  // Convert R0 to a double.
     __ SmiUntag(R0);
@@ -1242,114 +1253,113 @@
   }
 }
 
-void Intrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
 }
 
-void Intrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
 }
 
-void Intrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
 }
 
-void Intrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kDIV);
 }
 
 // Left is double, right is integer (Mint or Smi)
-void Intrinsifier::Double_mulFromInteger(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
+                                            Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
     Label fall_through;
     // Only smis allowed.
-    __ ldr(R0, Address(SP, 0 * kWordSize));
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
     __ tst(R0, Operand(kSmiTagMask));
     __ b(normal_ir_body, NE);
     // Is Smi.
     __ SmiUntag(R0);
     __ vmovsr(S0, R0);
     __ vcvtdi(D1, S0);
-    __ ldr(R0, Address(SP, 1 * kWordSize));
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 1 * target::kWordSize));
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ vmuld(D0, D0, D1);
-    const Class& double_class =
-        Class::Handle(Isolate::Current()->object_store()->double_class());
+    const Class& double_class = DoubleClass();
     __ TryAllocate(double_class, normal_ir_body, R0,
                    R1);  // Result register.
-    __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Ret();
     __ Bind(normal_ir_body);
   }
 }
 
-void Intrinsifier::DoubleFromInteger(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
+                                        Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
     Label fall_through;
 
-    __ ldr(R0, Address(SP, 0 * kWordSize));
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
     __ tst(R0, Operand(kSmiTagMask));
     __ b(normal_ir_body, NE);
     // Is Smi.
     __ SmiUntag(R0);
     __ vmovsr(S0, R0);
     __ vcvtdi(D0, S0);
-    const Class& double_class =
-        Class::Handle(Isolate::Current()->object_store()->double_class());
+    const Class& double_class = DoubleClass();
     __ TryAllocate(double_class, normal_ir_body, R0,
                    R1);  // Result register.
-    __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Ret();
     __ Bind(normal_ir_body);
   }
 }
 
-void Intrinsifier::Double_getIsNaN(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
+                                      Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
-    __ ldr(R0, Address(SP, 0 * kWordSize));
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ vcmpd(D0, D0);
     __ vmstat();
-    __ LoadObject(R0, Bool::False(), VC);
-    __ LoadObject(R0, Bool::True(), VS);
+    __ LoadObject(R0, CastHandle<Object>(FalseObject()), VC);
+    __ LoadObject(R0, CastHandle<Object>(TrueObject()), VS);
     __ Ret();
   }
 }
 
-void Intrinsifier::Double_getIsInfinite(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
+                                           Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
-    __ ldr(R0, Address(SP, 0 * kWordSize));
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
     // R1 <- value[0:31], R2 <- value[32:63]
-    __ LoadFieldFromOffset(kWord, R1, R0, Double::value_offset());
-    __ LoadFieldFromOffset(kWord, R2, R0, Double::value_offset() + kWordSize);
+    __ LoadFieldFromOffset(kWord, R1, R0, target::Double::value_offset());
+    __ LoadFieldFromOffset(kWord, R2, R0,
+                           target::Double::value_offset() + target::kWordSize);
 
     // If the low word isn't 0, then it isn't infinity.
     __ cmp(R1, Operand(0));
-    __ LoadObject(R0, Bool::False(), NE);
+    __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
     __ bx(LR, NE);  // Return if NE.
 
     // Mask off the sign bit.
     __ AndImmediate(R2, R2, 0x7FFFFFFF);
     // Compare with +infinity.
     __ CompareImmediate(R2, 0x7FF00000);
-    __ LoadObject(R0, Bool::False(), NE);
+    __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
     __ bx(LR, NE);
 
-    __ LoadObject(R0, Bool::True());
+    __ LoadObject(R0, CastHandle<Object>(TrueObject()));
     __ Ret();
   }
 }
 
-void Intrinsifier::Double_getIsNegative(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
+                                           Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
     Label is_false, is_true, is_zero;
-    __ ldr(R0, Address(SP, 0 * kWordSize));
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ vcmpdz(D0);
     __ vmstat();
     __ b(&is_false, VS);  // NaN -> false.
@@ -1357,11 +1367,11 @@
     __ b(&is_false, CS);  // >= 0 -> false.
 
     __ Bind(&is_true);
-    __ LoadObject(R0, Bool::True());
+    __ LoadObject(R0, CastHandle<Object>(TrueObject()));
     __ Ret();
 
     __ Bind(&is_false);
-    __ LoadObject(R0, Bool::False());
+    __ LoadObject(R0, CastHandle<Object>(FalseObject()));
     __ Ret();
 
     __ Bind(&is_zero);
@@ -1374,13 +1384,13 @@
   }
 }
 
-void Intrinsifier::DoubleToInteger(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::DoubleToInteger(Assembler* assembler,
+                                      Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
     Label fall_through;
 
-    __ ldr(R0, Address(SP, 0 * kWordSize));
-    __ LoadDFromOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ ldr(R0, Address(SP, 0 * target::kWordSize));
+    __ LoadDFromOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
 
     // Explicit NaN check, since ARM gives an FPU exception if you try to
     // convert NaN to an int.
@@ -1399,8 +1409,8 @@
   }
 }
 
-void Intrinsifier::Double_hashCode(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
+                                      Label* normal_ir_body) {
   // TODO(dartbug.com/31174): Convert this to a graph intrinsic.
 
   if (!TargetCPUFeatures::vfp_supported()) return;
@@ -1408,8 +1418,8 @@
   // Load double value and check that it isn't NaN, since ARM gives an
   // FPU exception if you try to convert NaN to an int.
   Label double_hash;
-  __ ldr(R1, Address(SP, 0 * kWordSize));
-  __ LoadDFromOffset(D0, R1, Double::value_offset() - kHeapObjectTag);
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));
+  __ LoadDFromOffset(D0, R1, target::Double::value_offset() - kHeapObjectTag);
   __ vcmpd(D0, D0);
   __ vmstat();
   __ b(&double_hash, VS);
@@ -1435,8 +1445,8 @@
 
   // Convert the double bits to a hash code that fits in a Smi.
   __ Bind(&double_hash);
-  __ ldr(R0, FieldAddress(R1, Double::value_offset()));
-  __ ldr(R1, FieldAddress(R1, Double::value_offset() + 4));
+  __ ldr(R0, FieldAddress(R1, target::Double::value_offset()));
+  __ ldr(R1, FieldAddress(R1, target::Double::value_offset() + 4));
   __ eor(R0, R0, Operand(R1));
   __ AndImmediate(R0, R0, kSmiMax);
   __ SmiTag(R0);
@@ -1446,19 +1456,18 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
   if (TargetCPUFeatures::vfp_supported()) {
     Label is_smi, double_op;
     TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
     // Argument is double and is in R0.
-    __ LoadDFromOffset(D1, R0, Double::value_offset() - kHeapObjectTag);
+    __ LoadDFromOffset(D1, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Bind(&double_op);
     __ vsqrtd(D0, D1);
-    const Class& double_class =
-        Class::Handle(Isolate::Current()->object_store()->double_class());
+    const Class& double_class = DoubleClass();
     __ TryAllocate(double_class, normal_ir_body, R0,
                    R1);  // Result register.
-    __ StoreDToOffset(D0, R0, Double::value_offset() - kHeapObjectTag);
+    __ StoreDToOffset(D0, R0, target::Double::value_offset() - kHeapObjectTag);
     __ Ret();
     __ Bind(&is_smi);
     __ SmiUntag(R0);
@@ -1472,30 +1481,25 @@
 //    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
 //    _state[kSTATE_LO] = state & _MASK_32;
 //    _state[kSTATE_HI] = state >> 32;
-void Intrinsifier::Random_nextState(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  ASSERT(!math_lib.IsNull());
-  const Class& random_class =
-      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
-  ASSERT(!random_class.IsNull());
-  const Field& state_field = Field::ZoneHandle(
-      random_class.LookupInstanceFieldAllowPrivate(Symbols::_state()));
-  ASSERT(!state_field.IsNull());
-  const int64_t a_int_value = Intrinsifier::kRandomAValue;
+void AsmIntrinsifier::Random_nextState(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  const Field& state_field = LookupMathRandomStateFieldOffset();
+  const int64_t a_int_value = AsmIntrinsifier::kRandomAValue;
+
   // 'a_int_value' is a mask.
   ASSERT(Utils::IsUint(32, a_int_value));
   int32_t a_int32_value = static_cast<int32_t>(a_int_value);
 
   // Receiver.
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   // Field '_state'.
-  __ ldr(R1, FieldAddress(R0, state_field.Offset()));
+  __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
 
-  const int64_t disp_0 = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
+  const int64_t disp_0 =
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
   const int64_t disp_1 =
-      disp_0 + Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
+      disp_0 + target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
 
   __ LoadImmediate(R0, a_int32_value);
   __ LoadFromOffset(kWord, R2, R1, disp_0 - kHeapObjectTag);
@@ -1505,17 +1509,18 @@
   __ umlal(R3, R8, R0, R2);  // R8:R3 <- R8:R3 + R0 * R2.
   __ StoreToOffset(kWord, R3, R1, disp_0 - kHeapObjectTag);
   __ StoreToOffset(kWord, R8, R1, disp_1 - kHeapObjectTag);
-  ASSERT(Smi::RawValue(0) == 0);
+  ASSERT(target::ToRawSmi(0) == 0);
   __ eor(R0, R0, Operand(R0));
   __ Ret();
 }
 
-void Intrinsifier::ObjectEquals(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
+void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
+                                   Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));
   __ cmp(R0, Operand(R1));
-  __ LoadObject(R0, Bool::False(), NE);
-  __ LoadObject(R0, Bool::True(), EQ);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()), EQ);
   __ Ret();
 }
 
@@ -1565,10 +1570,10 @@
 }
 
 // Return type quickly for simple types (not parameterized and not signature).
-void Intrinsifier::ObjectRuntimeType(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label use_declaration_type, not_double, not_integer;
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
   __ CompareImmediate(R1, kClosureCid);
@@ -1581,49 +1586,50 @@
   __ b(&not_double, NE);
 
   __ LoadIsolate(R0);
-  __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(kWord, R0, R0, ObjectStore::double_type_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::ObjectStore::double_type_offset());
   __ Ret();
 
   __ Bind(&not_double);
   JumpIfNotInteger(assembler, R1, R0, &not_integer);
   __ LoadIsolate(R0);
-  __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(kWord, R0, R0, ObjectStore::int_type_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::ObjectStore::int_type_offset());
   __ Ret();
 
   __ Bind(&not_integer);
   JumpIfNotString(assembler, R1, R0, &use_declaration_type);
   __ LoadIsolate(R0);
-  __ LoadFromOffset(kWord, R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(kWord, R0, R0, ObjectStore::string_type_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(kWord, R0, R0, target::ObjectStore::string_type_offset());
   __ Ret();
 
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);  // Overwrites R1.
-  __ ldrh(R3, FieldAddress(R2, Class::num_type_arguments_offset()));
+  __ ldrh(R3, FieldAddress(
+                  R2, target::Class::num_type_arguments_offset_in_bytes()));
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
-  __ ldr(R0, FieldAddress(R2, Class::declaration_type_offset()));
-  __ CompareObject(R0, Object::null_object());
+  __ ldr(R0, FieldAddress(R2, target::Class::declaration_type_offset()));
+  __ CompareObject(R0, NullObject());
   __ b(normal_ir_body, EQ);
   __ Ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label different_cids, equal, not_equal, not_integer;
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
   // Check if left hand size is a closure. Closures are handled in the runtime.
   __ CompareImmediate(R1, kClosureCid);
   __ b(normal_ir_body, EQ);
 
-  __ ldr(R0, Address(SP, 1 * kWordSize));
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R2, R0);
 
   // Check whether class ids match. If class ids don't match objects can still
@@ -1636,12 +1642,13 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(R3, R1);
-  __ ldrh(R3, FieldAddress(R3, Class::num_type_arguments_offset()));
+  __ ldrh(R3, FieldAddress(
+                  R3, target::Class::num_type_arguments_offset_in_bytes()));
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
   __ Bind(&equal);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ Ret();
 
   // Class ids are different. Check if we are comparing runtime types of
@@ -1662,26 +1669,26 @@
 
   // Neither strings nor integers and have different class ids.
   __ Bind(&not_equal);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::String_getHashCode(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, String::hash_offset()));
+void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::String::hash_offset()));
   __ cmp(R0, Operand(0));
   __ bx(LR, NE);
   // Hash not yet computed.
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Type_getHashCode(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, Type::hash_offset()));
+void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::Type::hash_offset()));
   __ cmp(R0, Operand(0));
   __ bx(LR, NE);
   // Hash not yet computed.
@@ -1694,9 +1701,10 @@
                                             Label* return_true,
                                             Label* return_false) {
   __ SmiUntag(R1);
-  __ ldr(R8, FieldAddress(R0, String::length_offset()));  // this.length
+  __ ldr(R8, FieldAddress(R0, target::String::length_offset()));  // this.length
   __ SmiUntag(R8);
-  __ ldr(R9, FieldAddress(R2, String::length_offset()));  // other.length
+  __ ldr(R9,
+         FieldAddress(R2, target::String::length_offset()));  // other.length
   __ SmiUntag(R9);
 
   // if (other.length == 0) return true;
@@ -1713,19 +1721,19 @@
   __ b(return_false, GT);
 
   if (receiver_cid == kOneByteStringCid) {
-    __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R0, target::OneByteString::data_offset() - kHeapObjectTag);
     __ add(R0, R0, Operand(R1));
   } else {
     ASSERT(receiver_cid == kTwoByteStringCid);
-    __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R0, target::TwoByteString::data_offset() - kHeapObjectTag);
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R1));
   }
   if (other_cid == kOneByteStringCid) {
-    __ AddImmediate(R2, OneByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R2, target::OneByteString::data_offset() - kHeapObjectTag);
   } else {
     ASSERT(other_cid == kTwoByteStringCid);
-    __ AddImmediate(R2, TwoByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R2, target::TwoByteString::data_offset() - kHeapObjectTag);
   }
 
   // i = 0
@@ -1761,13 +1769,13 @@
 // bool _substringMatches(int start, String other)
 // This intrinsic handles a OneByteString or TwoByteString receiver with a
 // OneByteString other.
-void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   Label return_true, return_false, try_two_byte;
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // this
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // start
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // other
-  __ Push(R4);                             // Make ARGS_DESC_REG available.
+  __ ldr(R0, Address(SP, 2 * target::kWordSize));  // this
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // start
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // other
+  __ Push(R4);  // Make ARGS_DESC_REG available.
 
   __ tst(R1, Operand(kSmiTagMask));
   __ b(normal_ir_body, NE);  // 'start' is not a Smi.
@@ -1792,48 +1800,51 @@
 
   __ Bind(&return_true);
   __ Pop(R4);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ Ret();
 
   __ Bind(&return_false);
   __ Pop(R4);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
 
   __ Bind(normal_ir_body);
   __ Pop(R4);
 }
 
-void Intrinsifier::Object_getHash(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Object_getHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
   UNREACHABLE();
 }
 
-void Intrinsifier::Object_setHash(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Object_setHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
   UNREACHABLE();
 }
 
-void Intrinsifier::StringBaseCharAt(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Label try_two_byte_string;
 
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // String.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // String.
   __ tst(R1, Operand(kSmiTagMask));
   __ b(normal_ir_body, NE);  // Index is not a Smi.
   // Range check.
-  __ ldr(R2, FieldAddress(R0, String::length_offset()));
+  __ ldr(R2, FieldAddress(R0, target::String::length_offset()));
   __ cmp(R1, Operand(R2));
   __ b(normal_ir_body, CS);  // Runtime throws exception.
 
   __ CompareClassId(R0, kOneByteStringCid, R3);
   __ b(&try_two_byte_string, NE);
   __ SmiUntag(R1);
-  __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R0, target::OneByteString::data_offset() - kHeapObjectTag);
   __ ldrb(R1, Address(R0, R1));
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
+  __ CompareImmediate(R1, target::Symbols::kNumberOfOneCharCodeSymbols);
   __ b(normal_ir_body, GE);
-  __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset()));
-  __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(R0, Address(THR, target::Thread::predefined_symbols_address_offset()));
+  __ AddImmediate(
+      R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
   __ ldr(R0, Address(R0, R1, LSL, 2));
   __ Ret();
 
@@ -1841,45 +1852,47 @@
   __ CompareClassId(R0, kTwoByteStringCid, R3);
   __ b(normal_ir_body, NE);
   ASSERT(kSmiTagShift == 1);
-  __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R0, target::TwoByteString::data_offset() - kHeapObjectTag);
   __ ldrh(R1, Address(R0, R1));
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
+  __ CompareImmediate(R1, target::Symbols::kNumberOfOneCharCodeSymbols);
   __ b(normal_ir_body, GE);
-  __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset()));
-  __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(R0, Address(THR, target::Thread::predefined_symbols_address_offset()));
+  __ AddImmediate(
+      R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
   __ ldr(R0, Address(R0, R1, LSL, 2));
   __ Ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseIsEmpty(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, String::length_offset()));
-  __ cmp(R0, Operand(Smi::RawValue(0)));
-  __ LoadObject(R0, Bool::True(), EQ);
-  __ LoadObject(R0, Bool::False(), NE);
+void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::String::length_offset()));
+  __ cmp(R0, Operand(target::ToRawSmi(0)));
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()), EQ);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
   __ Ret();
 }
 
-void Intrinsifier::OneByteString_getHashCode(Assembler* assembler,
-                                             Label* normal_ir_body) {
-  __ ldr(R1, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R1, String::hash_offset()));
+void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
+                                                Label* normal_ir_body) {
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R1, target::String::hash_offset()));
   __ cmp(R0, Operand(0));
   __ bx(LR, NE);  // Return if already computed.
 
-  __ ldr(R2, FieldAddress(R1, String::length_offset()));
+  __ ldr(R2, FieldAddress(R1, target::String::length_offset()));
 
   Label done;
   // If the string is empty, set the hash to 1, and return.
-  __ cmp(R2, Operand(Smi::RawValue(0)));
+  __ cmp(R2, Operand(target::ToRawSmi(0)));
   __ b(&done, EQ);
 
   __ SmiUntag(R2);
   __ mov(R3, Operand(0));
-  __ AddImmediate(R8, R1, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R8, R1,
+                  target::OneByteString::data_offset() - kHeapObjectTag);
   // R1: Instance of OneByteString.
   // R2: String length, untagged integer.
   // R3: Loop counter, untagged integer.
@@ -1911,14 +1924,15 @@
   __ eor(R0, R0, Operand(R0, LSR, 11));
   __ add(R0, R0, Operand(R0, LSL, 15));
   // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
-  __ LoadImmediate(R2, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
+  __ LoadImmediate(R2,
+                   (static_cast<intptr_t>(1) << target::String::kHashBits) - 1);
   __ and_(R0, R0, Operand(R2));
   __ cmp(R0, Operand(0));
   // return hash_ == 0 ? 1 : hash_;
   __ Bind(&done);
   __ mov(R0, Operand(1), EQ);
   __ SmiTag(R0);
-  __ StoreIntoSmiField(FieldAddress(R1, String::hash_offset()), R0);
+  __ StoreIntoSmiField(FieldAddress(R1, target::String::hash_offset()), R0);
   __ Ret();
 }
 
@@ -1937,12 +1951,14 @@
   // TODO(koda): Protect against negative length and overflow here.
   __ SmiUntag(length_reg);
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawString) + kObjectAlignment - 1;
+      target::String::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
   __ AddImmediate(length_reg, fixed_size_plus_alignment_padding);
-  __ bic(length_reg, length_reg, Operand(kObjectAlignment - 1));
+  __ bic(length_reg, length_reg,
+         Operand(target::ObjectAlignment::kObjectAlignment - 1));
 
   const intptr_t cid = kOneByteStringCid;
-  __ ldr(R0, Address(THR, Thread::top_offset()));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
 
   // length_reg: allocation size.
   __ adds(R1, R0, Operand(length_reg));
@@ -1952,14 +1968,14 @@
   // R0: potential new object start.
   // R1: potential next object start.
   // R2: allocation size.
-  __ ldr(NOTFP, Address(THR, Thread::end_offset()));
+  __ ldr(NOTFP, Address(THR, target::Thread::end_offset()));
   __ cmp(R1, Operand(NOTFP));
   __ b(&fail, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
   NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid));
-  __ str(R1, Address(THR, Thread::top_offset()));
+  __ str(R1, Address(THR, target::Thread::top_offset()));
   __ AddImmediate(R0, kHeapObjectTag);
 
   // Initialize the tags.
@@ -1968,28 +1984,29 @@
   // R2: allocation size.
   // R4: allocation stats address.
   {
-    const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
+    const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
 
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);
     __ mov(R3, Operand(R2, LSL, shift), LS);
     __ mov(R3, Operand(0), HI);
 
     // Get the class index and insert it into the tags.
     // R3: size and bit tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
     __ LoadImmediate(TMP, tags);
     __ orr(R3, R3, Operand(TMP));
-    __ str(R3, FieldAddress(R0, String::tags_offset()));  // Store tags.
+    __ str(R3, FieldAddress(R0, target::Object::tags_offset()));  // Store tags.
   }
 
   // Set the length field using the saved length (R8).
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()),
-                              R8);
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::String::length_offset()), R8);
   // Clear hash.
   __ LoadImmediate(TMP, 0);
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::hash_offset()), TMP);
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::String::hash_offset()), TMP);
 
   NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2));
   __ b(ok);
@@ -2002,11 +2019,11 @@
 // Arg1: Start index as Smi.
 // Arg2: End index as Smi.
 // The indexes must be valid.
-void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
-                                                    Label* normal_ir_body) {
-  const intptr_t kStringOffset = 2 * kWordSize;
-  const intptr_t kStartIndexOffset = 1 * kWordSize;
-  const intptr_t kEndIndexOffset = 0 * kWordSize;
+void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
+                                                       Label* normal_ir_body) {
+  const intptr_t kStringOffset = 2 * target::kWordSize;
+  const intptr_t kStartIndexOffset = 1 * target::kWordSize;
+  const intptr_t kEndIndexOffset = 0 * target::kWordSize;
   Label ok;
 
   __ ldr(R2, Address(SP, kEndIndexOffset));
@@ -2025,7 +2042,7 @@
   __ SmiUntag(R1);
   __ add(R3, R3, Operand(R1));
   // Calculate start address and untag (- 1).
-  __ AddImmediate(R3, OneByteString::data_offset() - 1);
+  __ AddImmediate(R3, target::OneByteString::data_offset() - 1);
 
   // R3: Start address to copy from (untagged).
   // R1: Untagged start index.
@@ -2049,7 +2066,7 @@
   __ AddImmediate(R8, 1);
   __ sub(R2, R2, Operand(1));
   __ cmp(R2, Operand(0));
-  __ strb(R1, FieldAddress(NOTFP, OneByteString::data_offset()));
+  __ strb(R1, FieldAddress(NOTFP, target::OneByteString::data_offset()));
   __ AddImmediate(NOTFP, 1);
   __ b(&loop, GT);
 
@@ -2058,21 +2075,22 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteStringSetAt(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // OneByteString.
+void AsmIntrinsifier::OneByteStringSetAt(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // Value.
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 2 * target::kWordSize));  // OneByteString.
   __ SmiUntag(R1);
   __ SmiUntag(R2);
-  __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R3, R0,
+                  target::OneByteString::data_offset() - kHeapObjectTag);
   __ strb(R2, Address(R3, R1));
   __ Ret();
 }
 
-void Intrinsifier::OneByteString_allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Length.
+void AsmIntrinsifier::OneByteString_allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // Length.
   Label ok;
   TryAllocateOnebyteString(assembler, &ok, normal_ir_body);
 
@@ -2087,8 +2105,8 @@
                            Label* normal_ir_body,
                            intptr_t string_cid) {
   Label is_true, is_false, loop;
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // This.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Other.
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // This.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Other.
 
   // Are identical?
   __ cmp(R0, Operand(R1));
@@ -2101,8 +2119,8 @@
   __ b(normal_ir_body, NE);
 
   // Have same length?
-  __ ldr(R2, FieldAddress(R0, String::length_offset()));
-  __ ldr(R3, FieldAddress(R1, String::length_offset()));
+  __ ldr(R2, FieldAddress(R0, target::String::length_offset()));
+  __ ldr(R3, FieldAddress(R1, target::String::length_offset()));
   __ cmp(R2, Operand(R3));
   __ b(&is_false, NE);
 
@@ -2111,8 +2129,8 @@
   ASSERT((string_cid == kOneByteStringCid) ||
          (string_cid == kTwoByteStringCid));
   const intptr_t offset = (string_cid == kOneByteStringCid)
-                              ? OneByteString::data_offset()
-                              : TwoByteString::data_offset();
+                              ? target::OneByteString::data_offset()
+                              : target::TwoByteString::data_offset();
   __ AddImmediate(R0, offset - kHeapObjectTag);
   __ AddImmediate(R1, offset - kHeapObjectTag);
   __ SmiUntag(R2);
@@ -2138,33 +2156,33 @@
   __ b(&loop);
 
   __ Bind(&is_true);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ Ret();
 
   __ Bind(&is_false);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kOneByteStringCid);
 }
 
-void Intrinsifier::TwoByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kTwoByteStringCid);
 }
 
-void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
-                                                Label* normal_ir_body,
-                                                bool sticky) {
+void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                                   Label* normal_ir_body,
+                                                   bool sticky) {
   if (FLAG_interpret_irregexp) return;
 
-  static const intptr_t kRegExpParamOffset = 2 * kWordSize;
-  static const intptr_t kStringParamOffset = 1 * kWordSize;
+  static const intptr_t kRegExpParamOffset = 2 * target::kWordSize;
+  static const intptr_t kStringParamOffset = 1 * target::kWordSize;
   // start_index smi is located at offset 0.
 
   // Incoming registers:
@@ -2178,82 +2196,85 @@
   __ ldr(R1, Address(SP, kStringParamOffset));
   __ LoadClassId(R1, R1);
   __ AddImmediate(R1, -kOneByteStringCid);
-  __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
-  __ ldr(R0,
-         FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
+  __ add(R1, R2, Operand(R1, LSL, target::kWordSizeLog2));
+  __ ldr(R0, FieldAddress(R1, target::RegExp::function_offset(kOneByteStringCid,
+                                                              sticky)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in R0, the argument descriptor in R4, and IC-Data in R9.
   __ eor(R9, R9, Operand(R9));
 
   // Tail-call the function.
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 }
 
 // On stack: user tag (+0).
-void Intrinsifier::UserTag_makeCurrent(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
+                                          Label* normal_ir_body) {
   // R1: Isolate.
   __ LoadIsolate(R1);
   // R0: Current user tag.
-  __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
+  __ ldr(R0, Address(R1, target::Isolate::current_tag_offset()));
   // R2: UserTag.
-  __ ldr(R2, Address(SP, +0 * kWordSize));
-  // Set Isolate::current_tag_.
-  __ str(R2, Address(R1, Isolate::current_tag_offset()));
+  __ ldr(R2, Address(SP, +0 * target::kWordSize));
+  // Set target::Isolate::current_tag_.
+  __ str(R2, Address(R1, target::Isolate::current_tag_offset()));
   // R2: UserTag's tag.
-  __ ldr(R2, FieldAddress(R2, UserTag::tag_offset()));
-  // Set Isolate::user_tag_.
-  __ str(R2, Address(R1, Isolate::user_tag_offset()));
+  __ ldr(R2, FieldAddress(R2, target::UserTag::tag_offset()));
+  // Set target::Isolate::user_tag_.
+  __ str(R2, Address(R1, target::Isolate::user_tag_offset()));
   __ Ret();
 }
 
-void Intrinsifier::UserTag_defaultTag(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
+                                         Label* normal_ir_body) {
   __ LoadIsolate(R0);
-  __ ldr(R0, Address(R0, Isolate::default_tag_offset()));
+  __ ldr(R0, Address(R0, target::Isolate::default_tag_offset()));
   __ Ret();
 }
 
-void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
+                                             Label* normal_ir_body) {
   __ LoadIsolate(R0);
-  __ ldr(R0, Address(R0, Isolate::current_tag_offset()));
+  __ ldr(R0, Address(R0, target::Isolate::current_tag_offset()));
   __ Ret();
 }
 
-void Intrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
+                                                   Label* normal_ir_body) {
 #if !defined(SUPPORT_TIMELINE)
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ Ret();
 #else
   // Load TimelineStream*.
-  __ ldr(R0, Address(THR, Thread::dart_stream_offset()));
+  __ ldr(R0, Address(THR, target::Thread::dart_stream_offset()));
   // Load uintptr_t from TimelineStream*.
-  __ ldr(R0, Address(R0, TimelineStream::enabled_offset()));
+  __ ldr(R0, Address(R0, target::TimelineStream::enabled_offset()));
   __ cmp(R0, Operand(0));
-  __ LoadObject(R0, Bool::True(), NE);
-  __ LoadObject(R0, Bool::False(), EQ);
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()), NE);
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()), EQ);
   __ Ret();
 #endif
 }
 
-void Intrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
-                                              Label* normal_ir_body) {
-  __ LoadObject(R0, Object::null_object());
-  __ str(R0, Address(THR, Thread::async_stack_trace_offset()));
+void AsmIntrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  __ LoadObject(R0, NullObject());
+  __ str(R0, Address(THR, target::Thread::async_stack_trace_offset()));
   __ Ret();
 }
 
-void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
-                                            Label* normal_ir_body) {
-  __ ldr(R0, Address(THR, Thread::async_stack_trace_offset()));
-  __ LoadObject(R0, Object::null_object());
+void AsmIntrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ ldr(R0, Address(THR, target::Thread::async_stack_trace_offset()));
+  __ LoadObject(R0, NullObject());
   __ Ret();
 }
 
+#undef __
+
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/intrinsifier_arm64.cc b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
similarity index 71%
rename from runtime/vm/compiler/intrinsifier_arm64.cc
rename to runtime/vm/compiler/asm_intrinsifier_arm64.cc
index 79a6cc4..6ba42cd 100644
--- a/runtime/vm/compiler/intrinsifier_arm64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_arm64.cc
@@ -1,22 +1,18 @@
-// Copyright (c) 2014, 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.
 
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM64.
 #if defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
 
-#include "vm/compiler/intrinsifier.h"
+#define SHOULD_NOT_INCLUDE_RUNTIME
 
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp_assembler.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
 
 namespace dart {
+namespace compiler {
 
 // When entering intrinsics code:
 // R4: Arguments descriptor
@@ -28,7 +24,7 @@
 
 #define __ assembler->
 
-intptr_t Intrinsifier::ParameterSlotFromSp() {
+intptr_t AsmIntrinsifier::ParameterSlotFromSp() {
   return -1;
 }
 
@@ -36,7 +32,7 @@
   return ((1 << reg) & kAbiPreservedCpuRegs) != 0;
 }
 
-void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
   ASSERT(IsABIPreservedRegister(CODE_REG));
   ASSERT(!IsABIPreservedRegister(ARGS_DESC_REG));
   ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
@@ -51,40 +47,41 @@
   assembler->mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
 }
 
-void Intrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   assembler->Comment("IntrinsicCallEpilogue");
   assembler->mov(LR, CALLEE_SAVED_TEMP);
   assembler->mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
 }
 
-// Allocate a GrowableObjectArray using the backing array specified.
+// Allocate a GrowableObjectArray:: using the backing array specified.
 // On stack: type argument (+1), data (+0).
-void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
   // The newly allocated object is returned in R0.
-  const intptr_t kTypeArgumentsOffset = 1 * kWordSize;
-  const intptr_t kArrayOffset = 0 * kWordSize;
+  const intptr_t kTypeArgumentsOffset = 1 * target::kWordSize;
+  const intptr_t kArrayOffset = 0 * target::kWordSize;
 
   // Try allocating in new space.
-  const Class& cls = Class::Handle(
-      Isolate::Current()->object_store()->growable_object_array_class());
+  const Class& cls = GrowableObjectArrayClass();
   __ TryAllocate(cls, normal_ir_body, R0, R1);
 
   // Store backing array object in growable array object.
   __ ldr(R1, Address(SP, kArrayOffset));  // Data argument.
   // R0 is new, no barrier needed.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, GrowableObjectArray::data_offset()), R1);
+      R0, FieldAddress(R0, target::GrowableObjectArray::data_offset()), R1);
 
   // R0: new growable array object start as a tagged pointer.
   // Store the type argument field in the growable array object.
   __ ldr(R1, Address(SP, kTypeArgumentsOffset));  // Type argument.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, GrowableObjectArray::type_arguments_offset()), R1);
+      R0,
+      FieldAddress(R0, target::GrowableObjectArray::type_arguments_offset()),
+      R1);
 
   // Set the length field in the growable array object to 0.
   __ LoadImmediate(R1, 0);
-  __ str(R1, FieldAddress(R0, GrowableObjectArray::length_offset()));
+  __ str(R1, FieldAddress(R0, target::GrowableObjectArray::length_offset()));
   __ ret();  // Returns the newly allocated object in R0.
 
   __ Bind(normal_ir_body);
@@ -107,9 +104,9 @@
   return -1;
 }
 
-#define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_shift)           \
+#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_shift)                      \
   Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 0 * kWordSize;                      \
+  const intptr_t kArrayLengthStackOffset = 0 * target::kWordSize;              \
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, R2, normal_ir_body));            \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
   /* Check that length is a positive Smi. */                                   \
@@ -124,10 +121,12 @@
   __ b(normal_ir_body, GT);                                                    \
   __ LslImmediate(R2, R2, scale_shift);                                        \
   const intptr_t fixed_size_plus_alignment_padding =                           \
-      sizeof(Raw##type_name) + kObjectAlignment - 1;                           \
+      target::TypedData::InstanceSize() +                                      \
+      target::ObjectAlignment::kObjectAlignment - 1;                           \
   __ AddImmediate(R2, fixed_size_plus_alignment_padding);                      \
-  __ andi(R2, R2, Immediate(~(kObjectAlignment - 1)));                         \
-  __ ldr(R0, Address(THR, Thread::top_offset()));                              \
+  __ andi(R2, R2,                                                              \
+          Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));        \
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));                      \
                                                                                \
   /* R2: allocation size. */                                                   \
   __ adds(R1, R0, Operand(R2));                                                \
@@ -137,13 +136,13 @@
   /* R0: potential new object start. */                                        \
   /* R1: potential next object start. */                                       \
   /* R2: allocation size. */                                                   \
-  __ ldr(R6, Address(THR, Thread::end_offset()));                              \
+  __ ldr(R6, Address(THR, target::Thread::end_offset()));                      \
   __ cmp(R1, Operand(R6));                                                     \
   __ b(normal_ir_body, CS);                                                    \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ str(R1, Address(THR, Thread::top_offset()));                              \
+  __ str(R1, Address(THR, target::Thread::top_offset()));                      \
   __ AddImmediate(R0, kHeapObjectTag);                                         \
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2));                   \
   /* Initialize the tags. */                                                   \
@@ -151,24 +150,25 @@
   /* R1: new object end address. */                                            \
   /* R2: allocation size. */                                                   \
   {                                                                            \
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);                  \
-    __ LslImmediate(R2, R2, RawObject::kSizeTagPos - kObjectAlignmentLog2);    \
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);            \
+    __ LslImmediate(R2, R2,                                                    \
+                    target::RawObject::kTagBitsSizeTagPos -                    \
+                        target::ObjectAlignment::kObjectAlignmentLog2);        \
     __ csel(R2, ZR, R2, HI);                                                   \
                                                                                \
     /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags = 0;                                                         \
-    tags = RawObject::ClassIdTag::update(cid, tags);                           \
-    tags = RawObject::NewBit::update(true, tags);                              \
+    uint32_t tags =                                                            \
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
     __ LoadImmediate(TMP, tags);                                               \
     __ orr(R2, R2, Operand(TMP));                                              \
-    __ str(R2, FieldAddress(R0, type_name::tags_offset())); /* Tags. */        \
+    __ str(R2, FieldAddress(R0, target::Object::tags_offset())); /* Tags. */   \
   }                                                                            \
   /* Set the length field. */                                                  \
   /* R0: new object start as a tagged pointer. */                              \
   /* R1: new object end address. */                                            \
   __ ldr(R2, Address(SP, kArrayLengthStackOffset)); /* Array length. */        \
   __ StoreIntoObjectNoBarrier(                                                 \
-      R0, FieldAddress(R0, type_name::length_offset()), R2);                   \
+      R0, FieldAddress(R0, target::TypedData::length_offset()), R2);           \
   /* Initialize all array elements to 0. */                                    \
   /* R0: new object start as a tagged pointer. */                              \
   /* R1: new object end address. */                                            \
@@ -176,13 +176,13 @@
   /* R3: scratch register. */                                                  \
   /* data area to be initialized. */                                           \
   __ mov(R3, ZR);                                                              \
-  __ AddImmediate(R2, R0, sizeof(Raw##type_name) - 1);                         \
+  __ AddImmediate(R2, R0, target::TypedData::InstanceSize() - 1);              \
   Label init_loop, done;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmp(R2, Operand(R1));                                                     \
   __ b(&done, CS);                                                             \
   __ str(R3, Address(R2, 0));                                                  \
-  __ add(R2, R2, Operand(kWordSize));                                          \
+  __ add(R2, R2, Operand(target::kWordSize));                                  \
   __ b(&init_loop);                                                            \
   __ Bind(&done);                                                              \
                                                                                \
@@ -190,12 +190,12 @@
   __ Bind(normal_ir_body);
 
 #define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler,         \
-                                                 Label* normal_ir_body) {      \
-    intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);     \
-    intptr_t max_len = TypedData::MaxNewSpaceElements(kTypedData##clazz##Cid); \
+  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
+                                                    Label* normal_ir_body) {   \
+    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
+    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
     int shift = GetScaleFactor(size);                                          \
-    TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, shift); \
+    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, shift);            \
   }
 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
 #undef TYPED_DATA_ALLOCATOR
@@ -203,27 +203,27 @@
 // Loads args from stack into R0 and R1
 // Tests if they are smis, jumps to label not_smi if not.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
-  __ ldr(R0, Address(SP, +0 * kWordSize));
-  __ ldr(R1, Address(SP, +1 * kWordSize));
+  __ ldr(R0, Address(SP, +0 * target::kWordSize));
+  __ ldr(R1, Address(SP, +1 * target::kWordSize));
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, not_smi);
 }
 
-void Intrinsifier::Integer_addFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_addFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
-  __ adds(R0, R0, Operand(R1));                     // Adds.
-  __ b(normal_ir_body, VS);                         // Fall-through on overflow.
+  __ adds(R0, R0, Operand(R1));                      // Adds.
+  __ b(normal_ir_body, VS);  // Fall-through on overflow.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
   Integer_addFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_subFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_subFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R0, Operand(R1));  // Subtract.
   __ b(normal_ir_body, VS);      // Fall-through on overflow.
@@ -231,7 +231,7 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ subs(R0, R1, Operand(R0));  // Subtract.
   __ b(normal_ir_body, VS);      // Fall-through on overflow.
@@ -239,8 +239,8 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mulFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mulFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // checks two smis
   __ SmiUntag(R0);  // Untags R6. We only want result shifted by one.
 
@@ -254,7 +254,7 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
   Integer_mulFromInteger(assembler, normal_ir_body);
 }
 
@@ -315,12 +315,12 @@
 //      res = res + right;
 //    }
 //  }
-void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_moduloFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   // Check to see if we have integer division
   Label neg_remainder, fall_through;
-  __ ldr(R1, Address(SP, +0 * kWordSize));
-  __ ldr(R0, Address(SP, +1 * kWordSize));
+  __ ldr(R1, Address(SP, +0 * target::kWordSize));
+  __ ldr(R0, Address(SP, +1 * target::kWordSize));
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, normal_ir_body);
   // R1: Tagged left (dividend).
@@ -348,8 +348,8 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_truncDivide(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
+                                          Label* normal_ir_body) {
   // Check to see if we have integer division
 
   TestBothArgumentsSmis(assembler, normal_ir_body);
@@ -370,8 +370,9 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_negate(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, +0 * kWordSize));  // Grab first argument.
+void AsmIntrinsifier::Integer_negate(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Grab first argument.
   __ BranchIfNotSmi(R0, normal_ir_body);
   __ negs(R0, R0);
   __ b(normal_ir_body, VS);
@@ -379,43 +380,46 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
   __ and_(R0, R0, Operand(R1));
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAnd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
+                                               Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
   __ orr(R0, R0, Operand(R1));
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOr(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_bitOrFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);  // Checks two smis.
   __ eor(R0, R0, Operand(R1));
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXor(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitXorFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
   const Register right = R0;
@@ -424,7 +428,7 @@
   const Register result = R0;
 
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ CompareImmediate(right, reinterpret_cast<int64_t>(Smi::New(Smi::kBits)));
+  __ CompareImmediate(right, target::ToRawSmi(target::Smi::kBits));
   __ b(normal_ir_body, CS);
 
   // Left is not a constant.
@@ -448,46 +452,46 @@
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // R0 contains the right argument, R1 the left.
   __ CompareRegisters(R1, R0);
-  __ LoadObject(R0, Bool::False());
-  __ LoadObject(TMP, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  __ LoadObject(TMP, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, true_condition);
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LT);
 }
 
-void Intrinsifier::Integer_lessThan(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Integer_greaterThanFromInt(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThan(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
+                                          Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GT);
 }
 
-void Intrinsifier::Integer_lessEqualThan(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
+                                            Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LE);
 }
 
-void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterEqualThan(Assembler* assembler,
+                                               Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GE);
 }
 
 // This is called for Smi and Mint receivers. The right argument
 // can be Smi, Mint or double.
-void Intrinsifier::Integer_equalToInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   Label true_label, check_for_mint;
   // For integer receiver '===' check first.
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));
   __ cmp(R0, Operand(R1));
   __ b(&true_label, EQ);
 
@@ -496,10 +500,10 @@
   // If R0 or R1 is not a smi do Mint checks.
 
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // At least one of the arguments was not Smi.
@@ -514,7 +518,8 @@
 
   __ CompareClassId(R0, kDoubleCid);
   __ b(normal_ir_body, EQ);
-  __ LoadObject(R0, Bool::False());  // Smi == Mint -> false.
+  __ LoadObject(R0,
+                CastHandle<Object>(FalseObject()));  // Smi == Mint -> false.
   __ ret();
 
   __ Bind(&receiver_not_smi);
@@ -524,18 +529,19 @@
   __ b(normal_ir_body, NE);
   // Receiver is Mint, return false if right is Smi.
   __ BranchIfNotSmi(R0, normal_ir_body);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equal(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift amount in R0. Value to shift in R1.
 
@@ -555,15 +561,17 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Smi_bitNegate(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ mvn(R0, R0);
   __ andi(R0, R0, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
   __ ret();
 }
 
-void Intrinsifier::Smi_bitLength(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ SmiUntag(R0);
   // XOR with sign bit to complement bits if value is negative.
   __ eor(R0, R0, Operand(R0, ASR, 63));
@@ -574,31 +582,31 @@
   __ ret();
 }
 
-void Intrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
   // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi.
-  __ ldp(R2, R3, Address(SP, 2 * kWordSize, Address::PairOffset));
+  __ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
   __ add(R2, R2, Operand(2));  // x_used > 0, Smi. R2 = x_used + 1, round up.
   __ AsrImmediate(R2, R2, 2);  // R2 = num of digit pairs to read.
   // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0.
-  __ ldp(R4, R5, Address(SP, 0 * kWordSize, Address::PairOffset));
+  __ ldp(R4, R5, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ SmiUntag(R5);
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R6 = &x_digits[0]
-  __ add(R6, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R6, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // R7 = &x_digits[2*R2]
   __ add(R7, R6, Operand(R2, LSL, 3));
   // R8 = &r_digits[2*1]
   __ add(R8, R4,
-         Operand(TypedData::data_offset() - kHeapObjectTag +
+         Operand(target::TypedData::data_offset() - kHeapObjectTag +
                  2 * kBytesPerBigIntDigit));
   // R8 = &r_digits[2*(R2 + n ~/ (2*_DIGIT_BITS) + 1)]
   __ add(R0, R0, Operand(R2));
@@ -619,27 +627,27 @@
   __ cmp(R7, Operand(R6));
   __ b(&loop, NE);
   __ str(R1, Address(R8, -2 * kBytesPerBigIntDigit, Address::PreIndex));
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
   // R2 = x_used, R3 = x_digits, x_used > 0, x_used is Smi.
-  __ ldp(R2, R3, Address(SP, 2 * kWordSize, Address::PairOffset));
+  __ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
   __ add(R2, R2, Operand(2));  // x_used > 0, Smi. R2 = x_used + 1, round up.
   __ AsrImmediate(R2, R2, 2);  // R2 = num of digit pairs to read.
   // R4 = r_digits, R5 = n, n is Smi, n % _DIGIT_BITS != 0.
-  __ ldp(R4, R5, Address(SP, 0 * kWordSize, Address::PairOffset));
+  __ ldp(R4, R5, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ SmiUntag(R5);
   // R0 = n ~/ (2*_DIGIT_BITS)
   __ AsrImmediate(R0, R5, 6);
   // R8 = &r_digits[0]
-  __ add(R8, R4, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R8, R4, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   // R7 = &x_digits[2*(n ~/ (2*_DIGIT_BITS))]
-  __ add(R7, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R7, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
   __ add(R7, R7, Operand(R0, LSL, 3));
   // R6 = &r_digits[2*(R2 - n ~/ (2*_DIGIT_BITS) - 1)]
   __ add(R0, R0, Operand(1));
@@ -666,33 +674,34 @@
   __ cmp(R8, Operand(R6));
   __ b(&loop, NE);
   __ str(R1, Address(R8, 0));
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
   // R2 = used, R3 = digits
-  __ ldp(R2, R3, Address(SP, 3 * kWordSize, Address::PairOffset));
+  __ ldp(R2, R3, Address(SP, 3 * target::kWordSize, Address::PairOffset));
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
-  __ ldp(R4, R5, Address(SP, 1 * kWordSize, Address::PairOffset));
+  __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6 = r_digits
-  __ ldr(R6, Address(SP, 0 * kWordSize));
+  __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -731,33 +740,34 @@
   __ str(R0, Address(R6, 0));
 
   __ Bind(&done);
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absSub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absSub(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
   // R2 = used, R3 = digits
-  __ ldp(R2, R3, Address(SP, 3 * kWordSize, Address::PairOffset));
+  __ ldp(R2, R3, Address(SP, 3 * target::kWordSize, Address::PairOffset));
   __ add(R2, R2, Operand(2));  // used > 0, Smi. R2 = used + 1, round up.
   __ add(R2, ZR, Operand(R2, ASR, 2));  // R2 = num of digit pairs to process.
   // R3 = &digits[0]
-  __ add(R3, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R3, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R4 = a_used, R5 = a_digits
-  __ ldp(R4, R5, Address(SP, 1 * kWordSize, Address::PairOffset));
+  __ ldp(R4, R5, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R4, R4, Operand(2));  // a_used > 0, Smi. R4 = a_used + 1, round up.
   __ add(R4, ZR, Operand(R4, ASR, 2));  // R4 = num of digit pairs to process.
   // R5 = &a_digits[0]
-  __ add(R5, R5, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R5, R5, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6 = r_digits
-  __ ldr(R6, Address(SP, 0 * kWordSize));
+  __ ldr(R6, Address(SP, 0 * target::kWordSize));
   // R6 = &r_digits[0]
-  __ add(R6, R6, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R6, R6, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R7 = &digits[a_used rounded up to even number].
   __ add(R7, R3, Operand(R4, LSL, 3));
@@ -790,11 +800,12 @@
   __ cbnz(&carry_loop, R9);
 
   __ Bind(&done);
-  __ LoadObject(R0, Object::null_object());
+  __ LoadObject(R0, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_mulAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulAdd(Uint32List x_digits, int xi,
   //                    Uint32List m_digits, int i,
@@ -826,29 +837,29 @@
   Label done;
   // R3 = x, no_op if x == 0
   // R0 = xi as Smi, R1 = x_digits.
-  __ ldp(R0, R1, Address(SP, 5 * kWordSize, Address::PairOffset));
+  __ ldp(R0, R1, Address(SP, 5 * target::kWordSize, Address::PairOffset));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R3, FieldAddress(R1, TypedData::data_offset()));
+  __ ldr(R3, FieldAddress(R1, target::TypedData::data_offset()));
   __ tst(R3, Operand(R3));
   __ b(&done, EQ);
 
   // R6 = (SmiUntag(n) + 1)/2, no_op if n == 0
-  __ ldr(R6, Address(SP, 0 * kWordSize));
+  __ ldr(R6, Address(SP, 0 * target::kWordSize));
   __ add(R6, R6, Operand(2));
   __ adds(R6, ZR, Operand(R6, ASR, 2));  // SmiUntag(R6) and set cc.
   __ b(&done, EQ);
 
   // R4 = mip = &m_digits[i >> 1]
   // R0 = i as Smi, R1 = m_digits.
-  __ ldp(R0, R1, Address(SP, 3 * kWordSize, Address::PairOffset));
+  __ ldp(R0, R1, Address(SP, 3 * target::kWordSize, Address::PairOffset));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R4, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R4, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R5 = ajp = &a_digits[j >> 1]
   // R0 = j as Smi, R1 = a_digits.
-  __ ldp(R0, R1, Address(SP, 1 * kWordSize, Address::PairOffset));
+  __ ldp(R0, R1, Address(SP, 1 * target::kWordSize, Address::PairOffset));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R1 = c = 0
   __ mov(R1, ZR);
@@ -900,11 +911,12 @@
   __ b(&propagate_carry_loop, CS);
 
   __ Bind(&done);
-  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
+  __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_sqrAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _sqrAdd(Uint32List x_digits, int i,
   //                    Uint32List a_digits, int used) {
@@ -933,9 +945,9 @@
 
   // R4 = xip = &x_digits[i >> 1]
   // R2 = i as Smi, R3 = x_digits
-  __ ldp(R2, R3, Address(SP, 2 * kWordSize, Address::PairOffset));
+  __ ldp(R2, R3, Address(SP, 2 * target::kWordSize, Address::PairOffset));
   __ add(R3, R3, Operand(R2, LSL, 1));
-  __ add(R4, R3, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ add(R4, R3, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R3 = x = *xip++, return if x == 0
   Label x_zero;
@@ -944,9 +956,9 @@
   __ b(&x_zero, EQ);
 
   // R5 = ajp = &a_digits[i]
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // a_digits
-  __ add(R1, R1, Operand(R2, LSL, 2));     // j == 2*i, i is Smi.
-  __ add(R5, R1, Operand(TypedData::data_offset() - kHeapObjectTag));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // a_digits
+  __ add(R1, R1, Operand(R2, LSL, 2));             // j == 2*i, i is Smi.
+  __ add(R5, R1, Operand(target::TypedData::data_offset() - kHeapObjectTag));
 
   // R6:R1 = t = x*x + *ajp
   __ ldr(R0, Address(R5, 0));
@@ -960,7 +972,7 @@
   __ str(R1, Address(R5, 2 * kBytesPerBigIntDigit, Address::PostIndex));
 
   // int n = (used - i + 1)/2 - 1
-  __ ldr(R0, Address(SP, 0 * kWordSize));  // used is Smi
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));  // used is Smi
   __ sub(R8, R0, Operand(R2));
   __ add(R8, R8, Operand(2));
   __ movn(R0, Immediate(1), 0);          // R0 = ~1 = -2.
@@ -1014,12 +1026,12 @@
   __ stp(R6, R7, Address(R5, 0, Address::PairOffset));
 
   __ Bind(&x_zero);
-  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
+  __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
+                                                   Label* normal_ir_body) {
   // There is no 128-bit by 64-bit division instruction on arm64, so we use two
   // 64-bit by 32-bit divisions and two 64-bit by 64-bit multiplications to
   // adjust the two 32-bit digits of the estimated quotient.
@@ -1065,16 +1077,17 @@
   // }
 
   // R4 = args
-  __ ldr(R4, Address(SP, 2 * kWordSize));  // args
+  __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
 
   // R3 = yt = args[0..1]
-  __ ldr(R3, FieldAddress(R4, TypedData::data_offset()));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset()));
 
   // R2 = dh = digits[(i >> 1) - 1 .. i >> 1]
   // R0 = i as Smi, R1 = digits
-  __ ldp(R0, R1, Address(SP, 0 * kWordSize, Address::PairOffset));
+  __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R2, FieldAddress(R1, TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ ldr(R2, FieldAddress(
+                 R1, target::TypedData::data_offset() - kBytesPerBigIntDigit));
 
   // R0 = qd = (DIGIT_MASK << 32) | DIGIT_MASK = -1
   __ movn(R0, Immediate(0), 0);
@@ -1085,8 +1098,8 @@
   __ b(&return_qd, EQ);
 
   // R1 = dl = digits[(i >> 1) - 3 .. (i >> 1) - 2]
-  __ ldr(R1,
-         FieldAddress(R1, TypedData::data_offset() - 3 * kBytesPerBigIntDigit));
+  __ ldr(R1, FieldAddress(R1, target::TypedData::data_offset() -
+                                  3 * kBytesPerBigIntDigit));
 
   // R5 = yth = yt >> 32
   __ orr(R5, ZR, Operand(R3, LSR, 32));
@@ -1190,15 +1203,15 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ str(R0,
-         FieldAddress(R4, TypedData::data_offset() + 2 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
-  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
+  __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Montgomery_mulMod(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
+                                        Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulMod(Uint32List args, Uint32List digits, int i) {
   //   uint64_t rho = args[_RHO .. _RHO_HI];  // _RHO == 2, _RHO_HI == 3.
@@ -1209,26 +1222,26 @@
   // }
 
   // R4 = args
-  __ ldr(R4, Address(SP, 2 * kWordSize));  // args
+  __ ldr(R4, Address(SP, 2 * target::kWordSize));  // args
 
   // R3 = rho = args[2..3]
-  __ ldr(R3,
-         FieldAddress(R4, TypedData::data_offset() + 2 * kBytesPerBigIntDigit));
+  __ ldr(R3, FieldAddress(R4, target::TypedData::data_offset() +
+                                  2 * kBytesPerBigIntDigit));
 
   // R2 = digits[i >> 1 .. (i >> 1) + 1]
   // R0 = i as Smi, R1 = digits
-  __ ldp(R0, R1, Address(SP, 0 * kWordSize, Address::PairOffset));
+  __ ldp(R0, R1, Address(SP, 0 * target::kWordSize, Address::PairOffset));
   __ add(R1, R1, Operand(R0, LSL, 1));
-  __ ldr(R2, FieldAddress(R1, TypedData::data_offset()));
+  __ ldr(R2, FieldAddress(R1, target::TypedData::data_offset()));
 
   // R0 = rho*d mod DIGIT_BASE
   __ mul(R0, R2, R3);  // R0 = low64(R2*R3).
 
   // args[4 .. 5] = R0
-  __ str(R0,
-         FieldAddress(R4, TypedData::data_offset() + 4 * kBytesPerBigIntDigit));
+  __ str(R0, FieldAddress(R4, target::TypedData::data_offset() +
+                                  4 * kBytesPerBigIntDigit));
 
-  __ LoadImmediate(R0, Smi::RawValue(2));  // Two digits processed.
+  __ LoadImmediate(R0, target::ToRawSmi(2));  // Two digits processed.
   __ ret();
 }
 
@@ -1238,7 +1251,7 @@
 static void TestLastArgumentIsDouble(Assembler* assembler,
                                      Label* is_smi,
                                      Label* not_double_smi) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ BranchIfSmi(R0, is_smi);
   __ CompareClassId(R0, kDoubleCid);
   __ b(not_double_smi, NE);
@@ -1257,18 +1270,18 @@
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in R0.
 
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
+  __ LoadDFieldFromOffset(V1, R0, target::Double::value_offset());
   __ Bind(&double_op);
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
 
   __ fcmpd(V0, V1);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   // Return false if D0 or D1 was NaN before checking true condition.
   __ b(&not_nan, VC);
   __ ret();
   __ Bind(&not_nan);
-  __ LoadObject(TMP, Bool::True());
+  __ LoadObject(TMP, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, true_condition);
   __ ret();
 
@@ -1279,27 +1292,28 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_greaterThan(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
+                                         Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, HI);
 }
 
-void Intrinsifier::Double_greaterEqualThan(Assembler* assembler,
-                                           Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
+                                              Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, CS);
 }
 
-void Intrinsifier::Double_lessThan(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
+                                      Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, CC);
 }
 
-void Intrinsifier::Double_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_equal(Assembler* assembler,
+                                   Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, EQ);
 }
 
-void Intrinsifier::Double_lessEqualThan(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
+                                           Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, LS);
 }
 
@@ -1312,10 +1326,10 @@
 
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in R0.
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
+  __ LoadDFieldFromOffset(V1, R0, target::Double::value_offset());
   __ Bind(&double_op);
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Left argument.
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Left argument.
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
   switch (kind) {
     case Token::kADD:
       __ faddd(V0, V0, V1);
@@ -1332,10 +1346,9 @@
     default:
       UNREACHABLE();
   }
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, R0, R1);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
+  __ StoreDFieldToOffset(V0, R0, target::Double::value_offset());
   __ ret();
 
   __ Bind(&is_smi);  // Convert R0 to a double.
@@ -1346,93 +1359,91 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
 }
 
-void Intrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
 }
 
-void Intrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
 }
 
-void Intrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kDIV);
 }
 
 // Left is double, right is integer (Mint or Smi)
-void Intrinsifier::Double_mulFromInteger(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
+                                            Label* normal_ir_body) {
   // Only smis allowed.
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ BranchIfNotSmi(R0, normal_ir_body);
   // Is Smi.
   __ SmiUntag(R0);
   __ scvtfdx(V1, R0);
-  __ ldr(R0, Address(SP, 1 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
   __ fmuld(V0, V0, V1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, R0, R1);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
+  __ StoreDFieldToOffset(V0, R0, target::Double::value_offset());
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::DoubleFromInteger(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ BranchIfNotSmi(R0, normal_ir_body);
   // Is Smi.
   __ SmiUntag(R0);
   __ scvtfdx(V0, R0);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, R0, R1);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
+  __ StoreDFieldToOffset(V0, R0, target::Double::value_offset());
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_getIsNaN(Assembler* assembler,
-                                   Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
   __ fcmpd(V0, V0);
-  __ LoadObject(TMP, Bool::False());
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(TMP, CastHandle<Object>(FalseObject()));
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, VC);
   __ ret();
 }
 
-void Intrinsifier::Double_getIsInfinite(Assembler* assembler,
-                                        Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadFieldFromOffset(R0, R0, Double::value_offset());
+void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
+                                           Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadFieldFromOffset(R0, R0, target::Double::value_offset());
   // Mask off the sign.
   __ AndImmediate(R0, R0, 0x7FFFFFFFFFFFFFFFLL);
   // Compare with +infinity.
   __ CompareImmediate(R0, 0x7FF0000000000000LL);
-  __ LoadObject(R0, Bool::False());
-  __ LoadObject(TMP, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  __ LoadObject(TMP, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, EQ);
   __ ret();
 }
 
-void Intrinsifier::Double_getIsNegative(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
+                                           Label* normal_ir_body) {
   const Register false_reg = R0;
   const Register true_reg = R2;
   Label is_false, is_true, is_zero;
 
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
   __ fcmpdz(V0);
-  __ LoadObject(true_reg, Bool::True());
-  __ LoadObject(false_reg, Bool::False());
+  __ LoadObject(true_reg, CastHandle<Object>(TrueObject()));
+  __ LoadObject(false_reg, CastHandle<Object>(FalseObject()));
   __ b(&is_false, VS);  // NaN -> false.
   __ b(&is_zero, EQ);   // Check for negative zero.
   __ b(&is_false, CS);  // >= 0 -> false.
@@ -1452,10 +1463,10 @@
   __ ret();
 }
 
-void Intrinsifier::DoubleToInteger(Assembler* assembler,
-                                   Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R0, Double::value_offset());
+void AsmIntrinsifier::DoubleToInteger(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ LoadDFieldFromOffset(V0, R0, target::Double::value_offset());
 
   // Explicit NaN check, since ARM gives an FPU exception if you try to
   // convert NaN to an int.
@@ -1472,15 +1483,15 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_hashCode(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
+                                      Label* normal_ir_body) {
   // TODO(dartbug.com/31174): Convert this to a graph intrinsic.
 
   // Load double value and check that it isn't NaN, since ARM gives an
   // FPU exception if you try to convert NaN to an int.
   Label double_hash;
-  __ ldr(R1, Address(SP, 0 * kWordSize));
-  __ LoadDFieldFromOffset(V0, R1, Double::value_offset());
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));
+  __ LoadDFieldFromOffset(V0, R1, target::Double::value_offset());
   __ fcmpd(V0, V0);
   __ b(&double_hash, VS);
 
@@ -1515,17 +1526,16 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
   Label is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Argument is double and is in R0.
-  __ LoadDFieldFromOffset(V1, R0, Double::value_offset());
+  __ LoadDFieldFromOffset(V1, R0, target::Double::value_offset());
   __ Bind(&double_op);
   __ fsqrtd(V0, V1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, R0, R1);
-  __ StoreDFieldToOffset(V0, R0, Double::value_offset());
+  __ StoreDFieldToOffset(V0, R0, target::Double::value_offset());
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(R0);
@@ -1537,26 +1547,20 @@
 //    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
 //    _state[kSTATE_LO] = state & _MASK_32;
 //    _state[kSTATE_HI] = state >> 32;
-void Intrinsifier::Random_nextState(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  ASSERT(!math_lib.IsNull());
-  const Class& random_class =
-      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
-  ASSERT(!random_class.IsNull());
-  const Field& state_field = Field::ZoneHandle(
-      random_class.LookupInstanceFieldAllowPrivate(Symbols::_state()));
-  ASSERT(!state_field.IsNull());
-  const int64_t a_int_value = Intrinsifier::kRandomAValue;
+void AsmIntrinsifier::Random_nextState(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  const Field& state_field = LookupMathRandomStateFieldOffset();
+  const int64_t a_int_value = AsmIntrinsifier::kRandomAValue;
 
   // Receiver.
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   // Field '_state'.
-  __ ldr(R1, FieldAddress(R0, state_field.Offset()));
+  __ ldr(R1, FieldAddress(R0, LookupFieldOffsetInBytes(state_field)));
 
   // Addresses of _state[0].
   const int64_t disp =
-      Instance::DataOffsetFor(kTypedDataUint32ArrayCid) - kHeapObjectTag;
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid) -
+      kHeapObjectTag;
 
   __ LoadImmediate(R0, a_int_value);
   __ LoadFromOffset(R2, R1, disp);
@@ -1565,17 +1569,18 @@
   __ mul(R2, R0, R2);
   __ add(R2, R2, Operand(R3));
   __ StoreToOffset(R2, R1, disp);
-  ASSERT(Smi::RawValue(0) == 0);
+  ASSERT(target::ToRawSmi(0) == 0);
   __ eor(R0, R0, Operand(R0));
   __ ret();
 }
 
-void Intrinsifier::ObjectEquals(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
+void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
+                                   Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));
   __ cmp(R0, Operand(R1));
-  __ LoadObject(R0, Bool::False());
-  __ LoadObject(TMP, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  __ LoadObject(TMP, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, EQ);
   __ ret();
 }
@@ -1626,10 +1631,10 @@
 }
 
 // Return type quickly for simple types (not parameterized and not signature).
-void Intrinsifier::ObjectRuntimeType(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label use_declaration_type, not_double, not_integer;
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
   __ CompareImmediate(R1, kClosureCid);
@@ -1642,49 +1647,51 @@
   __ b(&not_double, NE);
 
   __ LoadIsolate(R0);
-  __ LoadFromOffset(R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(R0, R0, ObjectStore::double_type_offset());
+  __ LoadFromOffset(R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(R0, R0, target::ObjectStore::double_type_offset());
   __ ret();
 
   __ Bind(&not_double);
   JumpIfNotInteger(assembler, R1, R0, &not_integer);
   __ LoadIsolate(R0);
-  __ LoadFromOffset(R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(R0, R0, ObjectStore::int_type_offset());
+  __ LoadFromOffset(R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(R0, R0, target::ObjectStore::int_type_offset());
   __ ret();
 
   __ Bind(&not_integer);
   JumpIfNotString(assembler, R1, R0, &use_declaration_type);
   __ LoadIsolate(R0);
-  __ LoadFromOffset(R0, R0, Isolate::object_store_offset());
-  __ LoadFromOffset(R0, R0, ObjectStore::string_type_offset());
+  __ LoadFromOffset(R0, R0, target::Isolate::object_store_offset());
+  __ LoadFromOffset(R0, R0, target::ObjectStore::string_type_offset());
   __ ret();
 
   __ Bind(&use_declaration_type);
   __ LoadClassById(R2, R1);  // Overwrites R1.
-  __ ldr(R3, FieldAddress(R2, Class::num_type_arguments_offset()), kHalfword);
+  __ ldr(R3,
+         FieldAddress(R2, target::Class::num_type_arguments_offset_in_bytes()),
+         kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
-  __ ldr(R0, FieldAddress(R2, Class::declaration_type_offset()));
-  __ CompareObject(R0, Object::null_object());
+  __ ldr(R0, FieldAddress(R2, target::Class::declaration_type_offset()));
+  __ CompareObject(R0, NullObject());
   __ b(normal_ir_body, EQ);
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label different_cids, equal, not_equal, not_integer;
-  __ ldr(R0, Address(SP, 0 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R1, R0);
 
   // Check if left hand size is a closure. Closures are handled in the runtime.
   __ CompareImmediate(R1, kClosureCid);
   __ b(normal_ir_body, EQ);
 
-  __ ldr(R0, Address(SP, 1 * kWordSize));
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(R2, R0);
 
   // Check whether class ids match. If class ids don't match objects can still
@@ -1697,12 +1704,14 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(R3, R1);  // Overwrites R1.
-  __ ldr(R3, FieldAddress(R3, Class::num_type_arguments_offset()), kHalfword);
+  __ ldr(R3,
+         FieldAddress(R3, target::Class::num_type_arguments_offset_in_bytes()),
+         kHalfword);
   __ CompareImmediate(R3, 0);
   __ b(normal_ir_body, NE);
 
   __ Bind(&equal);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // Class ids are different. Check if we are comparing runtime types of
@@ -1723,16 +1732,16 @@
 
   // Neither strings nor integers and have different class ids.
   __ Bind(&not_equal);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::String_getHashCode(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
+void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::String::hash_offset()), kUnsignedWord);
   __ adds(R0, R0, Operand(R0));  // Smi tag the hash code, setting Z flag.
   __ b(normal_ir_body, EQ);
   __ ret();
@@ -1740,28 +1749,30 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Type_getHashCode(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, Type::hash_offset()));
+void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::Type::hash_offset()));
   __ cbz(normal_ir_body, R0);
   __ ret();
   // Hash not yet computed.
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Object_getHash(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
+void AsmIntrinsifier::Object_getHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::String::hash_offset()), kUnsignedWord);
   __ SmiTag(R0);
   __ ret();
 }
 
-void Intrinsifier::Object_setHash(Assembler* assembler, Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // Object.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Value.
+void AsmIntrinsifier::Object_setHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // Object.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Value.
   __ SmiUntag(R1);
-  __ str(R1, FieldAddress(R0, String::hash_offset()), kUnsignedWord);
+  __ str(R1, FieldAddress(R0, target::String::hash_offset()), kUnsignedWord);
   __ ret();
 }
 
@@ -1771,9 +1782,10 @@
                                             Label* return_true,
                                             Label* return_false) {
   __ SmiUntag(R1);
-  __ ldr(R8, FieldAddress(R0, String::length_offset()));  // this.length
+  __ ldr(R8, FieldAddress(R0, target::String::length_offset()));  // this.length
   __ SmiUntag(R8);
-  __ ldr(R9, FieldAddress(R2, String::length_offset()));  // other.length
+  __ ldr(R9,
+         FieldAddress(R2, target::String::length_offset()));  // other.length
   __ SmiUntag(R9);
 
   // if (other.length == 0) return true;
@@ -1790,19 +1802,19 @@
   __ b(return_false, GT);
 
   if (receiver_cid == kOneByteStringCid) {
-    __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R0, target::OneByteString::data_offset() - kHeapObjectTag);
     __ add(R0, R0, Operand(R1));
   } else {
     ASSERT(receiver_cid == kTwoByteStringCid);
-    __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R0, target::TwoByteString::data_offset() - kHeapObjectTag);
     __ add(R0, R0, Operand(R1));
     __ add(R0, R0, Operand(R1));
   }
   if (other_cid == kOneByteStringCid) {
-    __ AddImmediate(R2, OneByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R2, target::OneByteString::data_offset() - kHeapObjectTag);
   } else {
     ASSERT(other_cid == kTwoByteStringCid);
-    __ AddImmediate(R2, TwoByteString::data_offset() - kHeapObjectTag);
+    __ AddImmediate(R2, target::TwoByteString::data_offset() - kHeapObjectTag);
   }
 
   // i = 0
@@ -1834,12 +1846,12 @@
 // bool _substringMatches(int start, String other)
 // This intrinsic handles a OneByteString or TwoByteString receiver with a
 // OneByteString other.
-void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   Label return_true, return_false, try_two_byte;
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // this
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // start
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // other
+  __ ldr(R0, Address(SP, 2 * target::kWordSize));  // this
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // start
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // other
 
   __ BranchIfNotSmi(R1, normal_ir_body);
 
@@ -1862,37 +1874,38 @@
                                          &return_false);
 
   __ Bind(&return_true);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&return_false);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseCharAt(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Label try_two_byte_string;
 
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // String.
-  __ BranchIfNotSmi(R1, normal_ir_body);   // Index is not a Smi.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // String.
+  __ BranchIfNotSmi(R1, normal_ir_body);           // Index is not a Smi.
   // Range check.
-  __ ldr(R2, FieldAddress(R0, String::length_offset()));
+  __ ldr(R2, FieldAddress(R0, target::String::length_offset()));
   __ cmp(R1, Operand(R2));
   __ b(normal_ir_body, CS);  // Runtime throws exception.
 
   __ CompareClassId(R0, kOneByteStringCid);
   __ b(&try_two_byte_string, NE);
   __ SmiUntag(R1);
-  __ AddImmediate(R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R0, target::OneByteString::data_offset() - kHeapObjectTag);
   __ ldr(R1, Address(R0, R1), kUnsignedByte);
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
+  __ CompareImmediate(R1, target::Symbols::kNumberOfOneCharCodeSymbols);
   __ b(normal_ir_body, GE);
-  __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset()));
-  __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(R0, Address(THR, target::Thread::predefined_symbols_address_offset()));
+  __ AddImmediate(
+      R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
   __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled));
   __ ret();
 
@@ -1900,40 +1913,41 @@
   __ CompareClassId(R0, kTwoByteStringCid);
   __ b(normal_ir_body, NE);
   ASSERT(kSmiTagShift == 1);
-  __ AddImmediate(R0, TwoByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R0, target::TwoByteString::data_offset() - kHeapObjectTag);
   __ ldr(R1, Address(R0, R1), kUnsignedHalfword);
-  __ CompareImmediate(R1, Symbols::kNumberOfOneCharCodeSymbols);
+  __ CompareImmediate(R1, target::Symbols::kNumberOfOneCharCodeSymbols);
   __ b(normal_ir_body, GE);
-  __ ldr(R0, Address(THR, Thread::predefined_symbols_address_offset()));
-  __ AddImmediate(R0, Symbols::kNullCharCodeSymbolOffset * kWordSize);
+  __ ldr(R0, Address(THR, target::Thread::predefined_symbols_address_offset()));
+  __ AddImmediate(
+      R0, target::Symbols::kNullCharCodeSymbolOffset * target::kWordSize);
   __ ldr(R0, Address(R0, R1, UXTX, Address::Scaled));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseIsEmpty(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R0, FieldAddress(R0, String::length_offset()));
-  __ cmp(R0, Operand(Smi::RawValue(0)));
-  __ LoadObject(R0, Bool::True());
-  __ LoadObject(TMP, Bool::False());
+void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R0, FieldAddress(R0, target::String::length_offset()));
+  __ cmp(R0, Operand(target::ToRawSmi(0)));
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+  __ LoadObject(TMP, CastHandle<Object>(FalseObject()));
   __ csel(R0, TMP, R0, NE);
   __ ret();
 }
 
-void Intrinsifier::OneByteString_getHashCode(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label compute_hash;
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // OneByteString object.
-  __ ldr(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // OneByteString object.
+  __ ldr(R0, FieldAddress(R1, target::String::hash_offset()), kUnsignedWord);
   __ adds(R0, R0, Operand(R0));  // Smi tag the hash code, setting Z flag.
   __ b(&compute_hash, EQ);
   __ ret();  // Return if already computed.
 
   __ Bind(&compute_hash);
-  __ ldr(R2, FieldAddress(R1, String::length_offset()));
+  __ ldr(R2, FieldAddress(R1, target::String::length_offset()));
   __ SmiUntag(R2);
 
   Label done;
@@ -1942,7 +1956,8 @@
   __ b(&done, EQ);
 
   __ mov(R3, ZR);
-  __ AddImmediate(R6, R1, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R6, R1,
+                  target::OneByteString::data_offset() - kHeapObjectTag);
   // R1: Instance of OneByteString.
   // R2: String length, untagged integer.
   // R3: Loop counter, untagged integer.
@@ -1973,12 +1988,13 @@
   __ eorw(R0, R0, Operand(R0, LSR, 11));
   __ addw(R0, R0, Operand(R0, LSL, 15));
   // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
-  __ AndImmediate(R0, R0, (static_cast<intptr_t>(1) << String::kHashBits) - 1);
+  __ AndImmediate(R0, R0,
+                  (static_cast<intptr_t>(1) << target::String::kHashBits) - 1);
   __ CompareRegisters(R0, ZR);
   // return hash_ == 0 ? 1 : hash_;
   __ Bind(&done);
   __ csinc(R0, R0, ZR, NE);  // R0 <- (R0 != 0) ? R0 : (ZR + 1).
-  __ str(R0, FieldAddress(R1, String::hash_offset()), kUnsignedWord);
+  __ str(R0, FieldAddress(R1, target::String::hash_offset()), kUnsignedWord);
   __ SmiTag(R0);
   __ ret();
 }
@@ -2003,12 +2019,14 @@
   // length <- (length != 0) ? length : (ZR + 1).
   __ csinc(length_reg, length_reg, ZR, NE);
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawString) + kObjectAlignment - 1;
+      target::String::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
   __ AddImmediate(length_reg, fixed_size_plus_alignment_padding);
-  __ andi(length_reg, length_reg, Immediate(~(kObjectAlignment - 1)));
+  __ andi(length_reg, length_reg,
+          Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));
 
   const intptr_t cid = kOneByteStringCid;
-  __ ldr(R0, Address(THR, Thread::top_offset()));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
 
   // length_reg: allocation size.
   __ adds(R1, R0, Operand(length_reg));
@@ -2018,13 +2036,13 @@
   // R0: potential new object start.
   // R1: potential next object start.
   // R2: allocation size.
-  __ ldr(R7, Address(THR, Thread::end_offset()));
+  __ ldr(R7, Address(THR, target::Thread::end_offset()));
   __ cmp(R1, Operand(R7));
   __ b(&fail, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ str(R1, Address(THR, Thread::top_offset()));
+  __ str(R1, Address(THR, target::Thread::top_offset()));
   __ AddImmediate(R0, kHeapObjectTag);
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2));
 
@@ -2033,26 +2051,26 @@
   // R1: new object end address.
   // R2: allocation size.
   {
-    const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
+    const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
 
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);
     __ LslImmediate(R2, R2, shift);
     __ csel(R2, R2, ZR, LS);
 
     // Get the class index and insert it into the tags.
     // R2: size and bit tags.
     // This also clears the hash, which is in the high word of the tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
     __ LoadImmediate(TMP, tags);
     __ orr(R2, R2, Operand(TMP));
-    __ str(R2, FieldAddress(R0, String::tags_offset()));  // Store tags.
+    __ str(R2, FieldAddress(R0, target::Object::tags_offset()));  // Store tags.
   }
 
   // Set the length field using the saved length (R6).
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, String::length_offset()),
-                              R6);
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::String::length_offset()), R6);
   __ b(ok);
 
   __ Bind(&fail);
@@ -2063,11 +2081,11 @@
 // Arg1: Start index as Smi.
 // Arg2: End index as Smi.
 // The indexes must be valid.
-void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
-                                                    Label* normal_ir_body) {
-  const intptr_t kStringOffset = 2 * kWordSize;
-  const intptr_t kStartIndexOffset = 1 * kWordSize;
-  const intptr_t kEndIndexOffset = 0 * kWordSize;
+void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
+                                                       Label* normal_ir_body) {
+  const intptr_t kStringOffset = 2 * target::kWordSize;
+  const intptr_t kStartIndexOffset = 1 * target::kWordSize;
+  const intptr_t kEndIndexOffset = 0 * target::kWordSize;
   Label ok;
 
   __ ldr(R2, Address(SP, kEndIndexOffset));
@@ -2085,7 +2103,7 @@
   __ SmiUntag(R1);
   __ add(R3, R3, Operand(R1));
   // Calculate start address and untag (- 1).
-  __ AddImmediate(R3, OneByteString::data_offset() - 1);
+  __ AddImmediate(R3, target::OneByteString::data_offset() - 1);
 
   // R3: Start address to copy from (untagged).
   // R1: Untagged start index.
@@ -2109,7 +2127,8 @@
   __ AddImmediate(R6, 1);
   __ sub(R2, R2, Operand(1));
   __ cmp(R2, Operand(0));
-  __ str(R1, FieldAddress(R7, OneByteString::data_offset()), kUnsignedByte);
+  __ str(R1, FieldAddress(R7, target::OneByteString::data_offset()),
+         kUnsignedByte);
   __ AddImmediate(R7, 1);
   __ b(&loop, GT);
 
@@ -2118,23 +2137,24 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteStringSetAt(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Value.
-  __ ldr(R1, Address(SP, 1 * kWordSize));  // Index.
-  __ ldr(R0, Address(SP, 2 * kWordSize));  // OneByteString.
+void AsmIntrinsifier::OneByteStringSetAt(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // Value.
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));  // Index.
+  __ ldr(R0, Address(SP, 2 * target::kWordSize));  // OneByteString.
   __ SmiUntag(R1);
   __ SmiUntag(R2);
-  __ AddImmediate(R3, R0, OneByteString::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R3, R0,
+                  target::OneByteString::data_offset() - kHeapObjectTag);
   __ str(R2, Address(R3, R1), kUnsignedByte);
   __ ret();
 }
 
-void Intrinsifier::OneByteString_allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
   Label ok;
 
-  __ ldr(R2, Address(SP, 0 * kWordSize));  // Length.
+  __ ldr(R2, Address(SP, 0 * target::kWordSize));  // Length.
   TryAllocateOnebyteString(assembler, &ok, normal_ir_body);
 
   __ Bind(&ok);
@@ -2148,8 +2168,8 @@
                            Label* normal_ir_body,
                            intptr_t string_cid) {
   Label is_true, is_false, loop;
-  __ ldr(R0, Address(SP, 1 * kWordSize));  // This.
-  __ ldr(R1, Address(SP, 0 * kWordSize));  // Other.
+  __ ldr(R0, Address(SP, 1 * target::kWordSize));  // This.
+  __ ldr(R1, Address(SP, 0 * target::kWordSize));  // Other.
 
   // Are identical?
   __ cmp(R0, Operand(R1));
@@ -2161,8 +2181,8 @@
   __ b(normal_ir_body, NE);
 
   // Have same length?
-  __ ldr(R2, FieldAddress(R0, String::length_offset()));
-  __ ldr(R3, FieldAddress(R1, String::length_offset()));
+  __ ldr(R2, FieldAddress(R0, target::String::length_offset()));
+  __ ldr(R3, FieldAddress(R1, target::String::length_offset()));
   __ cmp(R2, Operand(R3));
   __ b(&is_false, NE);
 
@@ -2171,8 +2191,8 @@
   ASSERT((string_cid == kOneByteStringCid) ||
          (string_cid == kTwoByteStringCid));
   const intptr_t offset = (string_cid == kOneByteStringCid)
-                              ? OneByteString::data_offset()
-                              : TwoByteString::data_offset();
+                              ? target::OneByteString::data_offset()
+                              : target::TwoByteString::data_offset();
   __ AddImmediate(R0, offset - kHeapObjectTag);
   __ AddImmediate(R1, offset - kHeapObjectTag);
   __ SmiUntag(R2);
@@ -2198,33 +2218,33 @@
   __ b(&loop);
 
   __ Bind(&is_true);
-  __ LoadObject(R0, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&is_false);
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kOneByteStringCid);
 }
 
-void Intrinsifier::TwoByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kTwoByteStringCid);
 }
 
-void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
-                                                Label* normal_ir_body,
-                                                bool sticky) {
+void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                                   Label* normal_ir_body,
+                                                   bool sticky) {
   if (FLAG_interpret_irregexp) return;
 
-  static const intptr_t kRegExpParamOffset = 2 * kWordSize;
-  static const intptr_t kStringParamOffset = 1 * kWordSize;
+  static const intptr_t kRegExpParamOffset = 2 * target::kWordSize;
+  static const intptr_t kStringParamOffset = 1 * target::kWordSize;
   // start_index smi is located at offset 0.
 
   // Incoming registers:
@@ -2238,84 +2258,87 @@
   __ ldr(R1, Address(SP, kStringParamOffset));
   __ LoadClassId(R1, R1);
   __ AddImmediate(R1, -kOneByteStringCid);
-  __ add(R1, R2, Operand(R1, LSL, kWordSizeLog2));
-  __ ldr(R0,
-         FieldAddress(R1, RegExp::function_offset(kOneByteStringCid, sticky)));
+  __ add(R1, R2, Operand(R1, LSL, target::kWordSizeLog2));
+  __ ldr(R0, FieldAddress(R1, target::RegExp::function_offset(kOneByteStringCid,
+                                                              sticky)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in R0, the argument descriptor in R4, and IC-Data in R5.
   __ eor(R5, R5, Operand(R5));
 
   // Tail-call the function.
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
   __ br(R1);
 }
 
 // On stack: user tag (+0).
-void Intrinsifier::UserTag_makeCurrent(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
+                                          Label* normal_ir_body) {
   // R1: Isolate.
   __ LoadIsolate(R1);
   // R0: Current user tag.
-  __ ldr(R0, Address(R1, Isolate::current_tag_offset()));
+  __ ldr(R0, Address(R1, target::Isolate::current_tag_offset()));
   // R2: UserTag.
-  __ ldr(R2, Address(SP, +0 * kWordSize));
-  // Set Isolate::current_tag_.
-  __ str(R2, Address(R1, Isolate::current_tag_offset()));
+  __ ldr(R2, Address(SP, +0 * target::kWordSize));
+  // Set target::Isolate::current_tag_.
+  __ str(R2, Address(R1, target::Isolate::current_tag_offset()));
   // R2: UserTag's tag.
-  __ ldr(R2, FieldAddress(R2, UserTag::tag_offset()));
-  // Set Isolate::user_tag_.
-  __ str(R2, Address(R1, Isolate::user_tag_offset()));
+  __ ldr(R2, FieldAddress(R2, target::UserTag::tag_offset()));
+  // Set target::Isolate::user_tag_.
+  __ str(R2, Address(R1, target::Isolate::user_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::UserTag_defaultTag(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
+                                         Label* normal_ir_body) {
   __ LoadIsolate(R0);
-  __ ldr(R0, Address(R0, Isolate::default_tag_offset()));
+  __ ldr(R0, Address(R0, target::Isolate::default_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
+                                             Label* normal_ir_body) {
   __ LoadIsolate(R0);
-  __ ldr(R0, Address(R0, Isolate::current_tag_offset()));
+  __ ldr(R0, Address(R0, target::Isolate::current_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
+                                                   Label* normal_ir_body) {
 #if !defined(SUPPORT_TIMELINE)
-  __ LoadObject(R0, Bool::False());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
   __ ret();
 #else
   // Load TimelineStream*.
-  __ ldr(R0, Address(THR, Thread::dart_stream_offset()));
+  __ ldr(R0, Address(THR, target::Thread::dart_stream_offset()));
   // Load uintptr_t from TimelineStream*.
-  __ ldr(R0, Address(R0, TimelineStream::enabled_offset()));
+  __ ldr(R0, Address(R0, target::TimelineStream::enabled_offset()));
   __ cmp(R0, Operand(0));
-  __ LoadObject(R0, Bool::False());
-  __ LoadObject(TMP, Bool::True());
+  __ LoadObject(R0, CastHandle<Object>(FalseObject()));
+  __ LoadObject(TMP, CastHandle<Object>(TrueObject()));
   __ csel(R0, TMP, R0, NE);
   __ ret();
 #endif
 }
 
-void Intrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
-                                              Label* normal_ir_body) {
-  __ LoadObject(R0, Object::null_object());
-  __ str(R0, Address(THR, Thread::async_stack_trace_offset()));
+void AsmIntrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  __ LoadObject(R0, NullObject());
+  __ str(R0, Address(THR, target::Thread::async_stack_trace_offset()));
   __ ret();
 }
 
-void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
-                                            Label* normal_ir_body) {
-  __ ldr(R0, Address(THR, Thread::async_stack_trace_offset()));
-  __ LoadObject(R0, Object::null_object());
+void AsmIntrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ ldr(R0, Address(THR, target::Thread::async_stack_trace_offset()));
+  __ LoadObject(R0, NullObject());
   __ ret();
 }
 
+#undef __
+
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/intrinsifier_dbc.cc b/runtime/vm/compiler/asm_intrinsifier_dbc.cc
similarity index 73%
rename from runtime/vm/compiler/intrinsifier_dbc.cc
rename to runtime/vm/compiler/asm_intrinsifier_dbc.cc
index b09a15f..cfb1130 100644
--- a/runtime/vm/compiler/intrinsifier_dbc.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_dbc.cc
@@ -5,28 +5,21 @@
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_DBC.
 #if defined(TARGET_ARCH_DBC)
 
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
+#include "vm/compiler/assembler/assembler.h"
 #include "vm/compiler/intrinsifier.h"
 
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/regexp_assembler.h"
-#include "vm/simulator.h"
-#include "vm/symbols.h"
-
 namespace dart {
+namespace compiler {
 
 DECLARE_FLAG(bool, interpret_irregexp);
 
-intptr_t Intrinsifier::ParameterSlotFromSp() {
-  return -1;
-}
-
 #define DEFINE_FUNCTION(class_name, test_function_name, enum_name, fp)         \
-  void Intrinsifier::enum_name(Assembler* assembler, Label* normal_ir_body) {  \
+  void AsmIntrinsifier::enum_name(Assembler* assembler,                        \
+                                  Label* normal_ir_body) {                     \
     if (Simulator::IsSupportedIntrinsic(Simulator::k##enum_name##Intrinsic)) { \
       assembler->Intrinsic(Simulator::k##enum_name##Intrinsic);                \
     }                                                                          \
@@ -37,6 +30,7 @@
 GRAPH_INTRINSICS_LIST(DEFINE_FUNCTION)
 #undef DEFINE_FUNCTION
 
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/compiler/intrinsifier_ia32.cc b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
similarity index 67%
rename from runtime/vm/compiler/intrinsifier_ia32.cc
rename to runtime/vm/compiler/asm_intrinsifier_ia32.cc
index 4229e6e..392d129 100644
--- a/runtime/vm/compiler/intrinsifier_ia32.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_ia32.cc
@@ -1,4 +1,4 @@
-// Copyright (c) 2013, 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.
 //
@@ -11,19 +11,14 @@
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_IA32.
 #if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
 
-#include "vm/compiler/intrinsifier.h"
+#define SHOULD_NOT_INCLUDE_RUNTIME
 
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/object.h"
-#include "vm/object_store.h"
-#include "vm/os.h"
-#include "vm/regexp_assembler.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
 
 namespace dart {
+namespace compiler {
 
 // When entering intrinsics code:
 // ECX: IC Data
@@ -36,59 +31,60 @@
 
 #define __ assembler->
 
-intptr_t Intrinsifier::ParameterSlotFromSp() {
+intptr_t AsmIntrinsifier::ParameterSlotFromSp() {
   return 0;
 }
 
-void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
   COMPILE_ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
 
   assembler->Comment("IntrinsicCallPrologue");
   assembler->movl(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
 }
 
-void Intrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   assembler->Comment("IntrinsicCallEpilogue");
   assembler->movl(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
 }
 
-// Allocate a GrowableObjectArray using the backing array specified.
+// Allocate a GrowableObjectArray:: using the backing array specified.
 // On stack: type argument (+2), data (+1), return-address (+0).
-void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
   // This snippet of inlined code uses the following registers:
   // EAX, EBX
   // and the newly allocated object is returned in EAX.
-  const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
+  const intptr_t kTypeArgumentsOffset = 2 * target::kWordSize;
 
-  const intptr_t kArrayOffset = 1 * kWordSize;
+  const intptr_t kArrayOffset = 1 * target::kWordSize;
 
   // Try allocating in new space.
-  const Class& cls = Class::Handle(
-      Isolate::Current()->object_store()->growable_object_array_class());
+  const Class& cls = GrowableObjectArrayClass();
   __ TryAllocate(cls, normal_ir_body, Assembler::kNearJump, EAX, EBX);
 
   // Store backing array object in growable array object.
   __ movl(EBX, Address(ESP, kArrayOffset));  // data argument.
   // EAX is new, no barrier needed.
   __ StoreIntoObjectNoBarrier(
-      EAX, FieldAddress(EAX, GrowableObjectArray::data_offset()), EBX);
+      EAX, FieldAddress(EAX, target::GrowableObjectArray::data_offset()), EBX);
 
   // EAX: new growable array object start as a tagged pointer.
   // Store the type argument field in the growable array object.
   __ movl(EBX, Address(ESP, kTypeArgumentsOffset));  // type argument.
   __ StoreIntoObjectNoBarrier(
-      EAX, FieldAddress(EAX, GrowableObjectArray::type_arguments_offset()),
+      EAX,
+      FieldAddress(EAX, target::GrowableObjectArray::type_arguments_offset()),
       EBX);
 
-  __ ZeroInitSmiField(FieldAddress(EAX, GrowableObjectArray::length_offset()));
+  __ ZeroInitSmiField(
+      FieldAddress(EAX, target::GrowableObjectArray::length_offset()));
   __ ret();  // returns the newly allocated object in EAX.
 
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
-  const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
+#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_factor)                     \
+  const intptr_t kArrayLengthStackOffset = 1 * target::kWordSize;              \
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, EDI, normal_ir_body, false));    \
   __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */     \
   /* Check that length is a positive Smi. */                                   \
@@ -110,10 +106,11 @@
     scale_factor = TIMES_8;                                                    \
   }                                                                            \
   const intptr_t fixed_size_plus_alignment_padding =                           \
-      sizeof(Raw##type_name) + kObjectAlignment - 1;                           \
+      target::TypedData::InstanceSize() +                                      \
+      target::ObjectAlignment::kObjectAlignment - 1;                           \
   __ leal(EDI, Address(EDI, scale_factor, fixed_size_plus_alignment_padding)); \
-  __ andl(EDI, Immediate(-kObjectAlignment));                                  \
-  __ movl(EAX, Address(THR, Thread::top_offset()));                            \
+  __ andl(EDI, Immediate(-target::ObjectAlignment::kObjectAlignment));         \
+  __ movl(EAX, Address(THR, target::Thread::top_offset()));                    \
   __ movl(EBX, EAX);                                                           \
                                                                                \
   /* EDI: allocation size. */                                                  \
@@ -124,12 +121,12 @@
   /* EAX: potential new object start. */                                       \
   /* EBX: potential next object start. */                                      \
   /* EDI: allocation size. */                                                  \
-  __ cmpl(EBX, Address(THR, Thread::end_offset()));                            \
+  __ cmpl(EBX, Address(THR, target::Thread::end_offset()));                    \
   __ j(ABOVE_EQUAL, normal_ir_body);                                           \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ movl(Address(THR, Thread::top_offset()), EBX);                            \
+  __ movl(Address(THR, target::Thread::top_offset()), EBX);                    \
   __ addl(EAX, Immediate(kHeapObjectTag));                                     \
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EDI, ECX));             \
                                                                                \
@@ -139,9 +136,10 @@
   /* EDI: allocation size. */                                                  \
   {                                                                            \
     Label size_tag_overflow, done;                                             \
-    __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag));                  \
+    __ cmpl(EDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));            \
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);                     \
-    __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));    \
+    __ shll(EDI, Immediate(target::RawObject::kTagBitsSizeTagPos -             \
+                           target::ObjectAlignment::kObjectAlignmentLog2));    \
     __ jmp(&done, Assembler::kNearJump);                                       \
                                                                                \
     __ Bind(&size_tag_overflow);                                               \
@@ -149,18 +147,18 @@
     __ Bind(&done);                                                            \
                                                                                \
     /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags = 0;                                                         \
-    tags = RawObject::ClassIdTag::update(cid, tags);                           \
-    tags = RawObject::NewBit::update(true, tags);                              \
+    uint32_t tags =                                                            \
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
     __ orl(EDI, Immediate(tags));                                              \
-    __ movl(FieldAddress(EAX, type_name::tags_offset()), EDI); /* Tags. */     \
+    __ movl(FieldAddress(EAX, target::Object::tags_offset()),                  \
+            EDI); /* Tags. */                                                  \
   }                                                                            \
   /* Set the length field. */                                                  \
   /* EAX: new object start as a tagged pointer. */                             \
   /* EBX: new object end address. */                                           \
   __ movl(EDI, Address(ESP, kArrayLengthStackOffset)); /* Array length. */     \
   __ StoreIntoObjectNoBarrier(                                                 \
-      EAX, FieldAddress(EAX, type_name::length_offset()), EDI);                \
+      EAX, FieldAddress(EAX, target::TypedData::length_offset()), EDI);        \
   /* Initialize all array elements to 0. */                                    \
   /* EAX: new object start as a tagged pointer. */                             \
   /* EBX: new object end address. */                                           \
@@ -168,13 +166,13 @@
   /* ECX: scratch register. */                                                 \
   /* data area to be initialized. */                                           \
   __ xorl(ECX, ECX); /* Zero. */                                               \
-  __ leal(EDI, FieldAddress(EAX, sizeof(Raw##type_name)));                     \
+  __ leal(EDI, FieldAddress(EAX, target::TypedData::InstanceSize()));          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpl(EDI, EBX);                                                           \
   __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);                              \
   __ movl(Address(EDI, 0), ECX);                                               \
-  __ addl(EDI, Immediate(kWordSize));                                          \
+  __ addl(EDI, Immediate(target::kWordSize));                                  \
   __ jmp(&init_loop, Assembler::kNearJump);                                    \
   __ Bind(&done);                                                              \
                                                                                \
@@ -199,12 +197,12 @@
 }
 
 #define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler,         \
-                                                 Label* normal_ir_body) {      \
-    intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);     \
-    intptr_t max_len = TypedData::MaxNewSpaceElements(kTypedData##clazz##Cid); \
+  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
+                                                    Label* normal_ir_body) {   \
+    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
+    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
     ScaleFactor scale = GetScaleFactor(size);                                  \
-    TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
+    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, scale);            \
   }
 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
 #undef TYPED_DATA_ALLOCATOR
@@ -212,41 +210,41 @@
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in EAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   __ orl(EBX, EAX);
   __ testl(EBX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, not_smi, Assembler::kNearJump);
 }
 
-void Intrinsifier::Integer_addFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_addFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ addl(EAX, Address(ESP, +2 * kWordSize));
+  __ addl(EAX, Address(ESP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
   Integer_addFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_subFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_subFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ subl(EAX, Address(ESP, +2 * kWordSize));
+  __ subl(EAX, Address(ESP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   __ movl(EBX, EAX);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));
   __ subl(EAX, EBX);
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in EAX.
@@ -254,19 +252,19 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mulFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mulFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
   __ SmiUntag(EAX);
-  __ imull(EAX, Address(ESP, +2 * kWordSize));
+  __ imull(EAX, Address(ESP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
   Integer_mulFromInteger(assembler, normal_ir_body);
 }
 
@@ -318,11 +316,11 @@
 //      res = res + right;
 //    }
 //  }
-void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_moduloFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label subtract;
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   // EAX: Tagged left (dividend).
   // EBX: Tagged right (divisor).
   // Check if modulo by zero -> exception thrown in main function.
@@ -352,15 +350,16 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_truncDivide(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
+                                          Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // EAX: right argument (divisor)
   __ cmpl(EAX, Immediate(0));
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
   __ movl(EBX, EAX);
   __ SmiUntag(EBX);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Left argument (dividend).
+  __ movl(EAX,
+          Address(ESP, +2 * target::kWordSize));  // Left argument (dividend).
   __ SmiUntag(EAX);
   __ pushl(EDX);  // Preserve EDX in case of 'fall_through'.
   __ cdq();
@@ -375,8 +374,9 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_negate(Assembler* assembler, Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+void AsmIntrinsifier::Integer_negate(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);  // Non-smi value.
   __ negl(EAX);
@@ -386,60 +386,63 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   __ andl(EAX, EBX);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAnd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
+                                               Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   __ orl(EAX, EBX);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOr(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_bitOrFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   __ xorl(EAX, EBX);
   // Result is in EAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXor(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitXorFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
   Label overflow;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift value is in EAX. Compare with tagged Smi.
-  __ cmpl(EAX, Immediate(Smi::RawValue(Smi::kBits)));
+  __ cmpl(EAX, Immediate(target::ToRawSmi(target::Smi::kBits)));
   __ j(ABOVE_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ SmiUntag(EAX);
-  __ movl(ECX, EAX);                           // Shift amount must be in ECX.
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Value.
+  __ movl(ECX, EAX);  // Shift amount must be in ECX.
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Value.
 
   // Overflow test - all the shifted-out bits must be same as the sign bit.
   __ movl(EBX, EAX);
@@ -464,14 +467,14 @@
   __ xorl(EDI, EDI);
   __ shldl(EDI, EAX, ECX);
   // Result in EDI (high) and EBX (low).
-  const Class& mint_class =
-      Class::Handle(Isolate::Current()->object_store()->mint_class());
+  const Class& mint_class = MintClass();
   __ TryAllocate(mint_class, normal_ir_body, Assembler::kNearJump,
                  EAX,   // Result register.
                  ECX);  // temp
   // EBX and EDI are not objects but integer values.
-  __ movl(FieldAddress(EAX, Mint::value_offset()), EBX);
-  __ movl(FieldAddress(EAX, Mint::value_offset() + kWordSize), EDI);
+  __ movl(FieldAddress(EAX, target::Mint::value_offset()), EBX);
+  __ movl(FieldAddress(EAX, target::Mint::value_offset() + target::kWordSize),
+          EDI);
   __ ret();
   __ Bind(normal_ir_body);
 }
@@ -494,8 +497,8 @@
   __ CompareClassId(reg, kMintCid, tmp);
   __ j(NOT_EQUAL, not_smi_or_mint);
   // Mint.
-  __ pushl(FieldAddress(reg, Mint::value_offset() + kWordSize));
-  __ pushl(FieldAddress(reg, Mint::value_offset()));
+  __ pushl(FieldAddress(reg, target::Mint::value_offset() + target::kWordSize));
+  __ pushl(FieldAddress(reg, target::Mint::value_offset()));
   __ Bind(&done);
 }
 
@@ -505,13 +508,13 @@
   Label try_mint_smi, is_true, is_false, drop_two_fall_through, fall_through;
   TestBothArgumentsSmis(assembler, &try_mint_smi);
   // EAX contains the right argument.
-  __ cmpl(Address(ESP, +2 * kWordSize), EAX);
+  __ cmpl(Address(ESP, +2 * target::kWordSize), EAX);
   __ j(true_condition, &is_true, Assembler::kNearJump);
   __ Bind(&is_false);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // 64-bit comparison
@@ -537,7 +540,7 @@
   // Note that EDX and ECX must be preserved in case we fall through to main
   // method.
   // EAX contains the right argument.
-  __ movl(EBX, Address(ESP, +2 * kWordSize));  // Left argument.
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));  // Left argument.
   // Push left as 64 bit integer.
   Push64SmiOrMint(assembler, EBX, EDI, normal_ir_body);
   // Push right as 64 bit integer.
@@ -559,65 +562,66 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LESS);
 }
 
-void Intrinsifier::Integer_lessThan(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Integer_greaterThanFromInt(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_greaterThan(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
+                                          Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GREATER);
 }
 
-void Intrinsifier::Integer_lessEqualThan(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
+                                            Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LESS_EQUAL);
 }
 
-void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterEqualThan(Assembler* assembler,
+                                               Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GREATER_EQUAL);
 }
 
 // This is called for Smi and Mint receivers. The right argument
 // can be Smi, Mint or double.
-void Intrinsifier::Integer_equalToInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   Label true_label, check_for_mint;
   // For integer receiver '===' check first.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ cmpl(EAX, Address(ESP, +2 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ cmpl(EAX, Address(ESP, +2 * target::kWordSize));
   __ j(EQUAL, &true_label, Assembler::kNearJump);
-  __ movl(EBX, Address(ESP, +2 * kWordSize));
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));
   __ orl(EAX, EBX);
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // At least one of the arguments was not Smi.
   Label receiver_not_smi;
   __ Bind(&check_for_mint);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Receiver.
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Receiver.
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &receiver_not_smi);
 
   // Left (receiver) is Smi, return false if right is not Double.
   // Note that an instance of Mint never contains a value that can be
   // represented by Smi.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Right argument.
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Right argument.
   __ CompareClassId(EAX, kDoubleCid, EDI);
   __ j(EQUAL, normal_ir_body);
-  __ LoadObject(EAX, Bool::False());  // Smi == Mint -> false.
+  __ LoadObject(EAX,
+                CastHandle<Object>(FalseObject()));  // Smi == Mint -> false.
   __ ret();
 
   __ Bind(&receiver_not_smi);
@@ -625,21 +629,22 @@
   __ CompareClassId(EAX, kMintCid, EDI);
   __ j(NOT_EQUAL, normal_ir_body);
   // Receiver is Mint, return false if right is Smi.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Right argument.
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Right argument.
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equal(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
   Label shift_count_ok;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Can destroy ECX since we are not falling through.
@@ -655,9 +660,9 @@
   __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
   __ movl(EAX, count_limit);
   __ Bind(&shift_count_ok);
-  __ movl(ECX, EAX);                           // Shift amount must be in ECX.
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Value.
-  __ SmiUntag(EAX);                            // Value.
+  __ movl(ECX, EAX);  // Shift amount must be in ECX.
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Value.
+  __ SmiUntag(EAX);                                    // Value.
   __ sarl(EAX, ECX);
   __ SmiTag(EAX);
   __ ret();
@@ -665,16 +670,18 @@
 }
 
 // Argument is Smi (receiver).
-void Intrinsifier::Smi_bitNegate(Assembler* assembler, Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Receiver.
+void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Receiver.
   __ notl(EAX);
   __ andl(EAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
   __ ret();
 }
 
-void Intrinsifier::Smi_bitLength(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
+                                    Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Receiver.
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Receiver.
   // XOR with sign bit to complement bits if value is negative.
   __ movl(ECX, EAX);
   __ sarl(ECX, Immediate(31));  // All 0 or all 1.
@@ -687,12 +694,12 @@
   __ ret();
 }
 
-void Intrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
@@ -700,18 +707,20 @@
   __ pushl(THR);
   ASSERT(THR == ESI);
 
-  __ movl(EDI, Address(ESP, 5 * kWordSize));  // x_digits
-  __ movl(ECX, Address(ESP, 3 * kWordSize));  // n is Smi
+  __ movl(EDI, Address(ESP, 5 * target::kWordSize));  // x_digits
+  __ movl(ECX, Address(ESP, 3 * target::kWordSize));  // n is Smi
   __ SmiUntag(ECX);
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // r_digits
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
   __ movl(ESI, ECX);
   __ sarl(ESI, Immediate(5));  // ESI = n ~/ _DIGIT_BITS.
-  __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset()));
-  __ movl(ESI, Address(ESP, 4 * kWordSize));  // x_used > 0, Smi.
+  __ leal(EBX,
+          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
+  __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // x_used > 0, Smi.
   __ SmiUntag(ESI);
   __ decl(ESI);
   __ xorl(EAX, EAX);  // EAX = 0.
-  __ movl(EDX, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset()));
+  __ movl(EDX,
+          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, kBytesPerBigIntDigit), EAX);
   Label last;
@@ -720,8 +729,9 @@
   Label loop;
   __ Bind(&loop);
   __ movl(EAX, EDX);
-  __ movl(EDX, FieldAddress(EDI, ESI, TIMES_4,
-                            TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ movl(EDX, FieldAddress(
+                   EDI, ESI, TIMES_4,
+                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
   __ shldl(EAX, EDX, ECX);
   __ movl(Address(EBX, ESI, TIMES_4, 0), EAX);
   __ decl(ESI);
@@ -732,11 +742,11 @@
 
   // Restore THR and return.
   __ popl(THR);
-  __ LoadObject(EAX, Object::null_object());
+  __ LoadObject(EAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _rsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
@@ -744,20 +754,22 @@
   __ pushl(THR);
   ASSERT(THR == ESI);
 
-  __ movl(EDI, Address(ESP, 5 * kWordSize));  // x_digits
-  __ movl(ECX, Address(ESP, 3 * kWordSize));  // n is Smi
+  __ movl(EDI, Address(ESP, 5 * target::kWordSize));  // x_digits
+  __ movl(ECX, Address(ESP, 3 * target::kWordSize));  // n is Smi
   __ SmiUntag(ECX);
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // r_digits
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
   __ movl(EDX, ECX);
-  __ sarl(EDX, Immediate(5));                 // EDX = n ~/ _DIGIT_BITS.
-  __ movl(ESI, Address(ESP, 4 * kWordSize));  // x_used > 0, Smi.
+  __ sarl(EDX, Immediate(5));                         // EDX = n ~/ _DIGIT_BITS.
+  __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // x_used > 0, Smi.
   __ SmiUntag(ESI);
   __ decl(ESI);
   // EDI = &x_digits[x_used - 1].
-  __ leal(EDI, FieldAddress(EDI, ESI, TIMES_4, TypedData::data_offset()));
+  __ leal(EDI,
+          FieldAddress(EDI, ESI, TIMES_4, target::TypedData::data_offset()));
   __ subl(ESI, EDX);
   // EBX = &r_digits[x_used - 1 - (n ~/ 32)].
-  __ leal(EBX, FieldAddress(EBX, ESI, TIMES_4, TypedData::data_offset()));
+  __ leal(EBX,
+          FieldAddress(EBX, ESI, TIMES_4, target::TypedData::data_offset()));
   __ negl(ESI);
   __ movl(EDX, Address(EDI, ESI, TIMES_4, 0));
   Label last;
@@ -777,11 +789,12 @@
 
   // Restore THR and return.
   __ popl(THR);
-  __ LoadObject(EAX, Object::null_object());
+  __ LoadObject(EAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
@@ -790,13 +803,13 @@
   __ pushl(THR);
   ASSERT(THR == ESI);
 
-  __ movl(EDI, Address(ESP, 6 * kWordSize));  // digits
-  __ movl(EAX, Address(ESP, 5 * kWordSize));  // used is Smi
-  __ SmiUntag(EAX);                           // used > 0.
-  __ movl(ESI, Address(ESP, 4 * kWordSize));  // a_digits
-  __ movl(ECX, Address(ESP, 3 * kWordSize));  // a_used is Smi
-  __ SmiUntag(ECX);                           // a_used > 0.
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // r_digits
+  __ movl(EDI, Address(ESP, 6 * target::kWordSize));  // digits
+  __ movl(EAX, Address(ESP, 5 * target::kWordSize));  // used is Smi
+  __ SmiUntag(EAX);                                   // used > 0.
+  __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // a_digits
+  __ movl(ECX, Address(ESP, 3 * target::kWordSize));  // a_used is Smi
+  __ SmiUntag(ECX);                                   // a_used > 0.
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
@@ -807,9 +820,12 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
-  __ adcl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset()));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ adcl(EAX,
+          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -822,9 +838,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
   __ adcl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -832,15 +850,17 @@
   __ Bind(&last_carry);
   __ movl(EAX, Immediate(0));
   __ adcl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
 
   // Restore THR and return.
   __ popl(THR);
-  __ LoadObject(EAX, Object::null_object());
+  __ LoadObject(EAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absSub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absSub(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
@@ -849,13 +869,13 @@
   __ pushl(THR);
   ASSERT(THR == ESI);
 
-  __ movl(EDI, Address(ESP, 6 * kWordSize));  // digits
-  __ movl(EAX, Address(ESP, 5 * kWordSize));  // used is Smi
-  __ SmiUntag(EAX);                           // used > 0.
-  __ movl(ESI, Address(ESP, 4 * kWordSize));  // a_digits
-  __ movl(ECX, Address(ESP, 3 * kWordSize));  // a_used is Smi
-  __ SmiUntag(ECX);                           // a_used > 0.
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // r_digits
+  __ movl(EDI, Address(ESP, 6 * target::kWordSize));  // digits
+  __ movl(EAX, Address(ESP, 5 * target::kWordSize));  // used is Smi
+  __ SmiUntag(EAX);                                   // used > 0.
+  __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // a_digits
+  __ movl(ECX, Address(ESP, 3 * target::kWordSize));  // a_used is Smi
+  __ SmiUntag(ECX);                                   // a_used > 0.
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // r_digits
 
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subl(EAX, ECX);
@@ -866,9 +886,12 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop a_used times, ECX = a_used, ECX > 0.
-  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
-  __ sbbl(EAX, FieldAddress(ESI, EDX, TIMES_4, TypedData::data_offset()));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ sbbl(EAX,
+          FieldAddress(ESI, EDX, TIMES_4, target::TypedData::data_offset()));
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -881,9 +904,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop used - a_used times, ECX = used - a_used, ECX > 0.
-  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, TypedData::data_offset()));
+  __ movl(EAX,
+          FieldAddress(EDI, EDX, TIMES_4, target::TypedData::data_offset()));
   __ sbbl(EAX, Immediate(0));
-  __ movl(FieldAddress(EBX, EDX, TIMES_4, TypedData::data_offset()), EAX);
+  __ movl(FieldAddress(EBX, EDX, TIMES_4, target::TypedData::data_offset()),
+          EAX);
   __ incl(EDX);  // Does not affect carry flag.
   __ decl(ECX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -891,11 +916,12 @@
   __ Bind(&done);
   // Restore THR and return.
   __ popl(THR);
-  __ LoadObject(EAX, Object::null_object());
+  __ LoadObject(EAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_mulAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulAdd(Uint32List x_digits, int xi,
   //                    Uint32List m_digits, int i,
@@ -925,14 +951,15 @@
 
   Label no_op;
   // EBX = x, no_op if x == 0
-  __ movl(ECX, Address(ESP, 7 * kWordSize));  // x_digits
-  __ movl(EAX, Address(ESP, 6 * kWordSize));  // xi is Smi
-  __ movl(EBX, FieldAddress(ECX, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(ECX, Address(ESP, 7 * target::kWordSize));  // x_digits
+  __ movl(EAX, Address(ESP, 6 * target::kWordSize));  // xi is Smi
+  __ movl(EBX,
+          FieldAddress(ECX, EAX, TIMES_2, target::TypedData::data_offset()));
   __ testl(EBX, EBX);
   __ j(ZERO, &no_op, Assembler::kNearJump);
 
   // EDX = SmiUntag(n), no_op if n == 0
-  __ movl(EDX, Address(ESP, 1 * kWordSize));
+  __ movl(EDX, Address(ESP, 1 * target::kWordSize));
   __ SmiUntag(EDX);
   __ j(ZERO, &no_op, Assembler::kNearJump);
 
@@ -941,18 +968,20 @@
   ASSERT(THR == ESI);
 
   // EDI = mip = &m_digits[i >> 1]
-  __ movl(EDI, Address(ESP, 6 * kWordSize));  // m_digits
-  __ movl(EAX, Address(ESP, 5 * kWordSize));  // i is Smi
-  __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(EDI, Address(ESP, 6 * target::kWordSize));  // m_digits
+  __ movl(EAX, Address(ESP, 5 * target::kWordSize));  // i is Smi
+  __ leal(EDI,
+          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // ESI = ajp = &a_digits[j >> 1]
-  __ movl(ESI, Address(ESP, 4 * kWordSize));  // a_digits
-  __ movl(EAX, Address(ESP, 3 * kWordSize));  // j is Smi
-  __ leal(ESI, FieldAddress(ESI, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(ESI, Address(ESP, 4 * target::kWordSize));  // a_digits
+  __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // j is Smi
+  __ leal(ESI,
+          FieldAddress(ESI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // Save n
   __ pushl(EDX);
-  Address n_addr = Address(ESP, 0 * kWordSize);
+  Address n_addr = Address(ESP, 0 * target::kWordSize);
 
   // ECX = c = 0
   __ xorl(ECX, ECX);
@@ -1010,11 +1039,12 @@
   __ popl(THR);
 
   __ Bind(&no_op);
-  __ movl(EAX, Immediate(Smi::RawValue(1)));  // One digit processed.
+  __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_sqrAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _sqrAdd(Uint32List x_digits, int i,
   //                    Uint32List a_digits, int used) {
@@ -1042,9 +1072,10 @@
   // }
 
   // EDI = xip = &x_digits[i >> 1]
-  __ movl(EDI, Address(ESP, 4 * kWordSize));  // x_digits
-  __ movl(EAX, Address(ESP, 3 * kWordSize));  // i is Smi
-  __ leal(EDI, FieldAddress(EDI, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(EDI, Address(ESP, 4 * target::kWordSize));  // x_digits
+  __ movl(EAX, Address(ESP, 3 * target::kWordSize));  // i is Smi
+  __ leal(EDI,
+          FieldAddress(EDI, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -1058,8 +1089,9 @@
   ASSERT(THR == ESI);
 
   // ESI = ajp = &a_digits[i]
-  __ movl(ESI, Address(ESP, 3 * kWordSize));  // a_digits
-  __ leal(ESI, FieldAddress(ESI, EAX, TIMES_4, TypedData::data_offset()));
+  __ movl(ESI, Address(ESP, 3 * target::kWordSize));  // a_digits
+  __ leal(ESI,
+          FieldAddress(ESI, EAX, TIMES_4, target::TypedData::data_offset()));
 
   // EDX:EAX = t = x*x + *ajp
   __ movl(EAX, EBX);
@@ -1072,8 +1104,8 @@
   __ addl(ESI, Immediate(kBytesPerBigIntDigit));
 
   // int n = used - i - 1
-  __ movl(EAX, Address(ESP, 2 * kWordSize));  // used is Smi
-  __ subl(EAX, Address(ESP, 4 * kWordSize));  // i is Smi
+  __ movl(EAX, Address(ESP, 2 * target::kWordSize));  // used is Smi
+  __ subl(EAX, Address(ESP, 4 * target::kWordSize));  // i is Smi
   __ SmiUntag(EAX);
   __ decl(EAX);
   __ pushl(EAX);  // Save n on stack.
@@ -1082,9 +1114,9 @@
   __ pushl(Immediate(0));  // push high32(c) == 0
   __ pushl(EDX);           // push low32(c) == high32(t)
 
-  Address n_addr = Address(ESP, 2 * kWordSize);
-  Address ch_addr = Address(ESP, 1 * kWordSize);
-  Address cl_addr = Address(ESP, 0 * kWordSize);
+  Address n_addr = Address(ESP, 2 * target::kWordSize);
+  Address ch_addr = Address(ESP, 1 * target::kWordSize);
+  Address cl_addr = Address(ESP, 0 * target::kWordSize);
 
   Label loop, done;
   __ Bind(&loop);
@@ -1096,7 +1128,7 @@
   // n:   ESP[2]
 
   // while (--n >= 0)
-  __ decl(Address(ESP, 2 * kWordSize));  // --n
+  __ decl(Address(ESP, 2 * target::kWordSize));  // --n
   __ j(NEGATIVE, &done, Assembler::kNearJump);
 
   // uint32_t xi = *xip++
@@ -1142,12 +1174,12 @@
   __ Drop(3);
   __ popl(THR);
   __ Bind(&x_zero);
-  __ movl(EAX, Immediate(Smi::RawValue(1)));  // One digit processed.
+  __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
+                                                   Label* normal_ir_body) {
   // Pseudo code:
   // static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
   //   uint32_t yt = args[_YT];  // _YT == 1.
@@ -1165,16 +1197,17 @@
   // }
 
   // EDI = args
-  __ movl(EDI, Address(ESP, 3 * kWordSize));  // args
+  __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
 
   // ECX = yt = args[1]
-  __ movl(ECX,
-          FieldAddress(EDI, TypedData::data_offset() + kBytesPerBigIntDigit));
+  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+                                     kBytesPerBigIntDigit));
 
   // EBX = dp = &digits[i >> 1]
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // digits
-  __ movl(EAX, Address(ESP, 1 * kWordSize));  // i is Smi
-  __ leal(EBX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
+  __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
+  __ leal(EBX,
+          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EDX = dh = dp[0]
   __ movl(EDX, Address(EBX, 0));
@@ -1195,16 +1228,16 @@
 
   __ Bind(&return_qd);
   // args[2] = qd
-  __ movl(
-      FieldAddress(EDI, TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
-      EAX);
+  __ movl(FieldAddress(
+              EDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+          EAX);
 
-  __ movl(EAX, Immediate(Smi::RawValue(1)));  // One digit processed.
+  __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
 }
 
-void Intrinsifier::Montgomery_mulMod(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
+                                        Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulMod(Uint32List args, Uint32List digits, int i) {
   //   uint32_t rho = args[_RHO];  // _RHO == 2.
@@ -1215,26 +1248,27 @@
   // }
 
   // EDI = args
-  __ movl(EDI, Address(ESP, 3 * kWordSize));  // args
+  __ movl(EDI, Address(ESP, 3 * target::kWordSize));  // args
 
   // ECX = rho = args[2]
-  __ movl(ECX, FieldAddress(
-                   EDI, TypedData::data_offset() + 2 * kBytesPerBigIntDigit));
+  __ movl(ECX, FieldAddress(EDI, target::TypedData::data_offset() +
+                                     2 * kBytesPerBigIntDigit));
 
   // EAX = digits[i >> 1]
-  __ movl(EBX, Address(ESP, 2 * kWordSize));  // digits
-  __ movl(EAX, Address(ESP, 1 * kWordSize));  // i is Smi
-  __ movl(EAX, FieldAddress(EBX, EAX, TIMES_2, TypedData::data_offset()));
+  __ movl(EBX, Address(ESP, 2 * target::kWordSize));  // digits
+  __ movl(EAX, Address(ESP, 1 * target::kWordSize));  // i is Smi
+  __ movl(EAX,
+          FieldAddress(EBX, EAX, TIMES_2, target::TypedData::data_offset()));
 
   // EDX:EAX = t = rho*d
   __ mull(ECX);
 
   // args[4] = t mod DIGIT_BASE = low32(t)
-  __ movl(
-      FieldAddress(EDI, TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
-      EAX);
+  __ movl(FieldAddress(
+              EDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+          EAX);
 
-  __ movl(EAX, Immediate(Smi::RawValue(1)));  // One digit processed.
+  __ movl(EAX, Immediate(target::ToRawSmi(1)));  // One digit processed.
   __ ret();
 }
 
@@ -1244,7 +1278,7 @@
 static void TestLastArgumentIsDouble(Assembler* assembler,
                                      Label* is_smi,
                                      Label* not_double_smi) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(ZERO, is_smi, Assembler::kNearJump);  // Jump if Smi.
   __ CompareClassId(EAX, kDoubleCid, EBX);
@@ -1262,19 +1296,19 @@
   Label is_false, is_true, is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in EAX.
-  __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(EAX, target::Double::value_offset()));
   __ Bind(&double_op);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Left argument.
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Left argument.
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   __ comisd(XMM0, XMM1);
   __ j(PARITY_EVEN, &is_false, Assembler::kNearJump);  // NaN -> false;
   __ j(true_condition, &is_true, Assembler::kNearJump);
   // Fall through false.
   __ Bind(&is_false);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(EAX);
@@ -1284,31 +1318,32 @@
 }
 
 // arg0 is Double, arg1 is unknown.
-void Intrinsifier::Double_greaterThan(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
+                                         Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, ABOVE);
 }
 
 // arg0 is Double, arg1 is unknown.
-void Intrinsifier::Double_greaterEqualThan(Assembler* assembler,
-                                           Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
+                                              Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, ABOVE_EQUAL);
 }
 
 // arg0 is Double, arg1 is unknown.
-void Intrinsifier::Double_lessThan(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
+                                      Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, BELOW);
 }
 
 // arg0 is Double, arg1 is unknown.
-void Intrinsifier::Double_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_equal(Assembler* assembler,
+                                   Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, EQUAL);
 }
 
 // arg0 is Double, arg1 is unknown.
-void Intrinsifier::Double_lessEqualThan(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
+                                           Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, BELOW_EQUAL);
 }
 
@@ -1320,10 +1355,10 @@
   Label is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in EAX.
-  __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(EAX, target::Double::value_offset()));
   __ Bind(&double_op);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Left argument.
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Left argument.
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   switch (kind) {
     case Token::kADD:
       __ addsd(XMM0, XMM1);
@@ -1340,12 +1375,11 @@
     default:
       UNREACHABLE();
   }
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kNearJump,
                  EAX,  // Result register.
                  EBX);
-  __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(EAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(EAX);
@@ -1354,116 +1388,115 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
 }
 
-void Intrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
 }
 
-void Intrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
 }
 
-void Intrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kDIV);
 }
 
 // Left is double, right is integer (Mint or Smi)
-void Intrinsifier::Double_mulFromInteger(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
+                                            Label* normal_ir_body) {
   // Only smis allowed.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);
   // Is Smi.
   __ SmiUntag(EAX);
   __ cvtsi2sd(XMM1, EAX);
-  __ movl(EAX, Address(ESP, +2 * kWordSize));
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   __ mulsd(XMM0, XMM1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kNearJump,
                  EAX,  // Result register.
                  EBX);
-  __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(EAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::DoubleFromInteger(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ testl(EAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);
   // Is Smi.
   __ SmiUntag(EAX);
   __ cvtsi2sd(XMM0, EAX);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kNearJump,
                  EAX,  // Result register.
                  EBX);
-  __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(EAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_getIsNaN(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
+                                      Label* normal_ir_body) {
   Label is_true;
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   __ comisd(XMM0, XMM0);
   __ j(PARITY_EVEN, &is_true, Assembler::kNearJump);  // NaN -> true;
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
-void Intrinsifier::Double_getIsInfinite(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
+                                           Label* normal_ir_body) {
   Label not_inf;
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ movl(EBX, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ movl(EBX, FieldAddress(EAX, target::Double::value_offset()));
 
   // If the low word isn't zero, then it isn't infinity.
   __ cmpl(EBX, Immediate(0));
   __ j(NOT_EQUAL, &not_inf, Assembler::kNearJump);
   // Check the high word.
-  __ movl(EBX, FieldAddress(EAX, Double::value_offset() + kWordSize));
+  __ movl(EBX, FieldAddress(
+                   EAX, target::Double::value_offset() + target::kWordSize));
   // Mask off sign bit.
   __ andl(EBX, Immediate(0x7FFFFFFF));
   // Compare with +infinity.
   __ cmpl(EBX, Immediate(0x7FF00000));
   __ j(NOT_EQUAL, &not_inf, Assembler::kNearJump);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&not_inf);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
 }
 
-void Intrinsifier::Double_getIsNegative(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
+                                           Label* normal_ir_body) {
   Label is_false, is_true, is_zero;
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   __ xorpd(XMM1, XMM1);  // 0.0 -> XMM1.
   __ comisd(XMM0, XMM1);
   __ j(PARITY_EVEN, &is_false, Assembler::kNearJump);  // NaN -> false.
   __ j(EQUAL, &is_zero, Assembler::kNearJump);  // Check for negative zero.
   __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump);  // >= 0 -> false.
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
   __ Bind(&is_false);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_zero);
   // Check for negative zero (get the sign bit).
@@ -1473,10 +1506,10 @@
   __ jmp(&is_false, Assembler::kNearJump);
 }
 
-void Intrinsifier::DoubleToInteger(Assembler* assembler,
-                                   Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(EAX, Double::value_offset()));
+void AsmIntrinsifier::DoubleToInteger(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(EAX, target::Double::value_offset()));
   __ cvttsd2si(EAX, XMM0);
   // Overflow is signalled with minint.
   // Check for overflow and that it fits into Smi.
@@ -1487,14 +1520,14 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_hashCode(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
+                                      Label* normal_ir_body) {
   // TODO(dartbug.com/31174): Convert this to a graph intrinsic.
 
   // Convert double value to signed 32-bit int in EAX and
   // back to a double in XMM1.
-  __ movl(ECX, Address(ESP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(ECX, Double::value_offset()));
+  __ movl(ECX, Address(ESP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(ECX, target::Double::value_offset()));
   __ cvttsd2si(EAX, XMM0);
   __ cvtsi2sd(XMM1, EAX);
 
@@ -1514,8 +1547,8 @@
 
   // Convert the double bits to a hash code that fits in a Smi.
   __ Bind(&double_hash);
-  __ movl(EAX, FieldAddress(ECX, Double::value_offset()));
-  __ movl(ECX, FieldAddress(ECX, Double::value_offset() + 4));
+  __ movl(EAX, FieldAddress(ECX, target::Double::value_offset()));
+  __ movl(ECX, FieldAddress(ECX, target::Double::value_offset() + 4));
   __ xorl(EAX, ECX);
   __ andl(EAX, Immediate(kSmiMax));
   __ SmiTag(EAX);
@@ -1526,19 +1559,18 @@
 }
 
 // Argument type is not known
-void Intrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
   Label is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Argument is double and is in EAX.
-  __ movsd(XMM1, FieldAddress(EAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(EAX, target::Double::value_offset()));
   __ Bind(&double_op);
   __ sqrtsd(XMM0, XMM1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kNearJump,
                  EAX,  // Result register.
                  EBX);
-  __ movsd(FieldAddress(EAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(EAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(EAX);
@@ -1550,28 +1582,24 @@
 //    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
 //    _state[kSTATE_LO] = state & _MASK_32;
 //    _state[kSTATE_HI] = state >> 32;
-void Intrinsifier::Random_nextState(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  ASSERT(!math_lib.IsNull());
-  const Class& random_class =
-      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
-  ASSERT(!random_class.IsNull());
-  const Field& state_field = Field::ZoneHandle(
-      random_class.LookupInstanceFieldAllowPrivate(Symbols::_state()));
-  ASSERT(!state_field.IsNull());
-  const int64_t a_int_value = Intrinsifier::kRandomAValue;
+void AsmIntrinsifier::Random_nextState(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  const Field& state_field = LookupMathRandomStateFieldOffset();
+  const int64_t a_int_value = AsmIntrinsifier::kRandomAValue;
+
   // 'a_int_value' is a mask.
   ASSERT(Utils::IsUint(32, a_int_value));
   int32_t a_int32_value = static_cast<int32_t>(a_int_value);
 
   // Receiver.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   // Field '_state'.
-  __ movl(EBX, FieldAddress(EAX, state_field.Offset()));
+  __ movl(EBX, FieldAddress(EAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
-  const intptr_t scale = Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
-  const intptr_t offset = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
+  const intptr_t scale =
+      target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
+  const intptr_t offset =
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
   Address addr_0 = FieldAddress(EBX, 0 * scale + offset);
   Address addr_1 = FieldAddress(EBX, 1 * scale + offset);
   __ movl(EAX, Immediate(a_int32_value));
@@ -1581,21 +1609,22 @@
   __ adcl(EDX, Immediate(0));
   __ movl(addr_1, EDX);
   __ movl(addr_0, EAX);
-  ASSERT(Smi::RawValue(0) == 0);
+  ASSERT(target::ToRawSmi(0) == 0);
   __ xorl(EAX, EAX);
   __ ret();
 }
 
 // Identity comparison.
-void Intrinsifier::ObjectEquals(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
+                                   Label* normal_ir_body) {
   Label is_true;
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
-  __ cmpl(EAX, Address(ESP, +2 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
+  __ cmpl(EAX, Address(ESP, +2 * target::kWordSize));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
@@ -1634,10 +1663,10 @@
 }
 
 // Return type quickly for simple types (not parameterized and not signature).
-void Intrinsifier::ObjectRuntimeType(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label use_declaration_type, not_double, not_integer;
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(EDI, EAX);
 
   __ cmpl(EDI, Immediate(kClosureCid));
@@ -1651,8 +1680,8 @@
   __ j(NOT_EQUAL, &not_double);
 
   __ LoadIsolate(EAX);
-  __ movl(EAX, Address(EAX, Isolate::object_store_offset()));
-  __ movl(EAX, Address(EAX, ObjectStore::double_type_offset()));
+  __ movl(EAX, Address(EAX, target::Isolate::object_store_offset()));
+  __ movl(EAX, Address(EAX, target::ObjectStore::double_type_offset()));
   __ ret();
 
   __ Bind(&not_double);
@@ -1661,8 +1690,8 @@
   JumpIfNotInteger(assembler, EAX, &not_integer);
 
   __ LoadIsolate(EAX);
-  __ movl(EAX, Address(EAX, Isolate::object_store_offset()));
-  __ movl(EAX, Address(EAX, ObjectStore::int_type_offset()));
+  __ movl(EAX, Address(EAX, target::Isolate::object_store_offset()));
+  __ movl(EAX, Address(EAX, target::ObjectStore::int_type_offset()));
   __ ret();
 
   __ Bind(&not_integer);
@@ -1672,36 +1701,37 @@
   JumpIfNotString(assembler, EAX, &use_declaration_type);
 
   __ LoadIsolate(EAX);
-  __ movl(EAX, Address(EAX, Isolate::object_store_offset()));
-  __ movl(EAX, Address(EAX, ObjectStore::string_type_offset()));
+  __ movl(EAX, Address(EAX, target::Isolate::object_store_offset()));
+  __ movl(EAX, Address(EAX, target::ObjectStore::string_type_offset()));
   __ ret();
 
   // Object is neither double, nor integer, nor string.
   __ Bind(&use_declaration_type);
   __ LoadClassById(EBX, EDI);
-  __ movzxw(EDI, FieldAddress(EBX, Class::num_type_arguments_offset()));
+  __ movzxw(EDI, FieldAddress(
+                     EBX, target::Class::num_type_arguments_offset_in_bytes()));
   __ cmpl(EDI, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
-  __ movl(EAX, FieldAddress(EBX, Class::declaration_type_offset()));
-  __ CompareObject(EAX, Object::null_object());
+  __ movl(EAX, FieldAddress(EBX, target::Class::declaration_type_offset()));
+  __ CompareObject(EAX, NullObject());
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);  // Not yet set.
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label different_cids, equal, not_equal, not_integer;
 
-  __ movl(EAX, Address(ESP, +1 * kWordSize));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(EDI, EAX);
 
   // Check if left hand size is a closure. Closures are handled in the runtime.
   __ cmpl(EDI, Immediate(kClosureCid));
   __ j(EQUAL, normal_ir_body);
 
-  __ movl(EAX, Address(ESP, +2 * kWordSize));
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));
   __ LoadClassIdMayBeSmi(EBX, EAX);
 
   // Check whether class ids match. If class ids don't match objects can still
@@ -1714,12 +1744,13 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(EBX, EDI);
-  __ movzxw(EBX, FieldAddress(EBX, Class::num_type_arguments_offset()));
+  __ movzxw(EBX, FieldAddress(
+                     EBX, target::Class::num_type_arguments_offset_in_bytes()));
   __ cmpl(EBX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ Bind(&equal);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // Class ids are different. Check if we are comparing runtime types of
@@ -1748,16 +1779,16 @@
   // Fall-through to the not equal case.
 
   __ Bind(&not_equal);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::String_getHashCode(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // String object.
-  __ movl(EAX, FieldAddress(EAX, String::hash_offset()));
+void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // String object.
+  __ movl(EAX, FieldAddress(EAX, target::String::hash_offset()));
   __ cmpl(EAX, Immediate(0));
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
   __ ret();
@@ -1765,10 +1796,10 @@
   // Hash not yet computed.
 }
 
-void Intrinsifier::Type_getHashCode(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // Type object.
-  __ movl(EAX, FieldAddress(EAX, Type::hash_offset()));
+void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // Type object.
+  __ movl(EAX, FieldAddress(EAX, target::Type::hash_offset()));
   __ testl(EAX, EAX);
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
   __ ret();
@@ -1777,85 +1808,89 @@
 }
 
 // bool _substringMatches(int start, String other)
-void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   // For precompilation, not implemented on IA32.
 }
 
-void Intrinsifier::Object_getHash(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Object_getHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
   UNREACHABLE();
 }
 
-void Intrinsifier::Object_setHash(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Object_setHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
   UNREACHABLE();
 }
 
-void Intrinsifier::StringBaseCharAt(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Label try_two_byte_string;
-  __ movl(EBX, Address(ESP, +1 * kWordSize));  // Index.
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // String.
+  __ movl(EBX, Address(ESP, +1 * target::kWordSize));  // Index.
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // String.
   __ testl(EBX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);  // Non-smi index.
   // Range check.
-  __ cmpl(EBX, FieldAddress(EAX, String::length_offset()));
+  __ cmpl(EBX, FieldAddress(EAX, target::String::length_offset()));
   // Runtime throws exception.
   __ j(ABOVE_EQUAL, normal_ir_body, Assembler::kNearJump);
   __ CompareClassId(EAX, kOneByteStringCid, EDI);
   __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
   __ SmiUntag(EBX);
-  __ movzxb(EBX, FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()));
-  __ cmpl(EBX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
+  __ movzxb(EBX, FieldAddress(EAX, EBX, TIMES_1,
+                              target::OneByteString::data_offset()));
+  __ cmpl(EBX, Immediate(target::Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, normal_ir_body);
-  __ movl(EAX,
-          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  __ movl(EAX, Immediate(SymbolsPredefinedAddress()));
   __ movl(EAX, Address(EAX, EBX, TIMES_4,
-                       Symbols::kNullCharCodeSymbolOffset * kWordSize));
+                       target::Symbols::kNullCharCodeSymbolOffset *
+                           target::kWordSize));
   __ ret();
 
   __ Bind(&try_two_byte_string);
   __ CompareClassId(EAX, kTwoByteStringCid, EDI);
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
   ASSERT(kSmiTagShift == 1);
-  __ movzxw(EBX, FieldAddress(EAX, EBX, TIMES_1, TwoByteString::data_offset()));
-  __ cmpl(EBX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
+  __ movzxw(EBX, FieldAddress(EAX, EBX, TIMES_1,
+                              target::TwoByteString::data_offset()));
+  __ cmpl(EBX, Immediate(target::Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, normal_ir_body);
-  __ movl(EAX,
-          Immediate(reinterpret_cast<uword>(Symbols::PredefinedAddress())));
+  __ movl(EAX, Immediate(SymbolsPredefinedAddress()));
   __ movl(EAX, Address(EAX, EBX, TIMES_4,
-                       Symbols::kNullCharCodeSymbolOffset * kWordSize));
+                       target::Symbols::kNullCharCodeSymbolOffset *
+                           target::kWordSize));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseIsEmpty(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label is_true;
   // Get length.
-  __ movl(EAX, Address(ESP, +1 * kWordSize));  // String object.
-  __ movl(EAX, FieldAddress(EAX, String::length_offset()));
-  __ cmpl(EAX, Immediate(Smi::RawValue(0)));
+  __ movl(EAX, Address(ESP, +1 * target::kWordSize));  // String object.
+  __ movl(EAX, FieldAddress(EAX, target::String::length_offset()));
+  __ cmpl(EAX, Immediate(target::ToRawSmi(0)));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
-void Intrinsifier::OneByteString_getHashCode(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label compute_hash;
-  __ movl(EBX, Address(ESP, +1 * kWordSize));  // OneByteString object.
-  __ movl(EAX, FieldAddress(EBX, String::hash_offset()));
+  __ movl(EBX, Address(ESP, +1 * target::kWordSize));  // OneByteString object.
+  __ movl(EAX, FieldAddress(EBX, target::String::hash_offset()));
   __ cmpl(EAX, Immediate(0));
   __ j(EQUAL, &compute_hash, Assembler::kNearJump);
   __ ret();
 
   __ Bind(&compute_hash);
   // Hash not yet computed, use algorithm of class StringHasher.
-  __ movl(ECX, FieldAddress(EBX, String::length_offset()));
+  __ movl(ECX, FieldAddress(EBX, target::String::length_offset()));
   __ SmiUntag(ECX);
   __ xorl(EAX, EAX);
   __ xorl(EDI, EDI);
@@ -1872,7 +1907,8 @@
   // hash_ += hash_ << 10;
   // hash_ ^= hash_ >> 6;
   // Get one characters (ch).
-  __ movzxb(EDX, FieldAddress(EBX, EDI, TIMES_1, OneByteString::data_offset()));
+  __ movzxb(EDX, FieldAddress(EBX, EDI, TIMES_1,
+                              target::OneByteString::data_offset()));
   // EDX: ch and temporary.
   __ addl(EAX, EDX);
   __ movl(EDX, EAX);
@@ -1900,8 +1936,9 @@
   __ shll(EDX, Immediate(15));
   __ addl(EAX, EDX);
   // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
-  __ andl(EAX,
-          Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+  __ andl(
+      EAX,
+      Immediate(((static_cast<intptr_t>(1) << target::String::kHashBits) - 1)));
 
   // return hash_ == 0 ? 1 : hash_;
   __ cmpl(EAX, Immediate(0));
@@ -1909,7 +1946,7 @@
   __ incl(EAX);
   __ Bind(&set_hash_code);
   __ SmiTag(EAX);
-  __ StoreIntoSmiField(FieldAddress(EBX, String::hash_offset()), EAX);
+  __ StoreIntoSmiField(FieldAddress(EBX, target::String::hash_offset()), EAX);
   __ ret();
 }
 
@@ -1929,13 +1966,14 @@
   __ pushl(EDI);  // Preserve length.
   __ SmiUntag(EDI);
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawString) + kObjectAlignment - 1;
+      target::String::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
   __ leal(EDI, Address(EDI, TIMES_1,
                        fixed_size_plus_alignment_padding));  // EDI is untagged.
-  __ andl(EDI, Immediate(-kObjectAlignment));
+  __ andl(EDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
   const intptr_t cid = kOneByteStringCid;
-  __ movl(EAX, Address(THR, Thread::top_offset()));
+  __ movl(EAX, Address(THR, target::Thread::top_offset()));
   __ movl(EBX, EAX);
 
   // EDI: allocation size.
@@ -1946,12 +1984,12 @@
   // EAX: potential new object start.
   // EBX: potential next object start.
   // EDI: allocation size.
-  __ cmpl(EBX, Address(THR, Thread::end_offset()));
+  __ cmpl(EBX, Address(THR, target::Thread::end_offset()));
   __ j(ABOVE_EQUAL, &pop_and_fail);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movl(Address(THR, Thread::top_offset()), EBX);
+  __ movl(Address(THR, target::Thread::top_offset()), EBX);
   __ addl(EAX, Immediate(kHeapObjectTag));
 
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EDI, ECX));
@@ -1962,9 +2000,10 @@
   // EDI: allocation size.
   {
     Label size_tag_overflow, done;
-    __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
+    __ cmpl(EDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+    __ shll(EDI, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
     __ Bind(&size_tag_overflow);
@@ -1972,19 +2011,18 @@
     __ Bind(&done);
 
     // Get the class index and insert it into the tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
     __ orl(EDI, Immediate(tags));
-    __ movl(FieldAddress(EAX, String::tags_offset()), EDI);  // Tags.
+    __ movl(FieldAddress(EAX, target::Object::tags_offset()), EDI);  // Tags.
   }
 
   // Set the length field.
   __ popl(EDI);
-  __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, String::length_offset()),
-                              EDI);
+  __ StoreIntoObjectNoBarrier(
+      EAX, FieldAddress(EAX, target::String::length_offset()), EDI);
   // Clear hash.
-  __ ZeroInitSmiField(FieldAddress(EAX, String::hash_offset()));
+  __ ZeroInitSmiField(FieldAddress(EAX, target::String::hash_offset()));
   __ jmp(ok, Assembler::kNearJump);
 
   __ Bind(&pop_and_fail);
@@ -1996,11 +2034,11 @@
 // Arg1: Start index as Smi.
 // Arg2: End index as Smi.
 // The indexes must be valid.
-void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
-                                                    Label* normal_ir_body) {
-  const intptr_t kStringOffset = 3 * kWordSize;
-  const intptr_t kStartIndexOffset = 2 * kWordSize;
-  const intptr_t kEndIndexOffset = 1 * kWordSize;
+void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
+                                                       Label* normal_ir_body) {
+  const intptr_t kStringOffset = 3 * target::kWordSize;
+  const intptr_t kStartIndexOffset = 2 * target::kWordSize;
+  const intptr_t kEndIndexOffset = 1 * target::kWordSize;
   Label ok;
   __ movl(EAX, Address(ESP, +kStartIndexOffset));
   __ movl(EDI, Address(ESP, +kEndIndexOffset));
@@ -2016,7 +2054,8 @@
   __ movl(EDI, Address(ESP, +kStringOffset));
   __ movl(EBX, Address(ESP, +kStartIndexOffset));
   __ SmiUntag(EBX);
-  __ leal(EDI, FieldAddress(EDI, EBX, TIMES_1, OneByteString::data_offset()));
+  __ leal(EDI, FieldAddress(EDI, EBX, TIMES_1,
+                            target::OneByteString::data_offset()));
   // EDI: Start address to copy from (untagged).
   // EBX: Untagged start index.
   __ movl(ECX, Address(ESP, +kEndIndexOffset));
@@ -2032,7 +2071,8 @@
   __ jmp(&check, Assembler::kNearJump);
   __ Bind(&loop);
   __ movzxb(EBX, Address(EDI, EDX, TIMES_1, 0));
-  __ movb(FieldAddress(EAX, EDX, TIMES_1, OneByteString::data_offset()), BL);
+  __ movb(FieldAddress(EAX, EDX, TIMES_1, target::OneByteString::data_offset()),
+          BL);
   __ incl(EDX);
   __ Bind(&check);
   __ cmpl(EDX, ECX);
@@ -2041,20 +2081,21 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteStringSetAt(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ movl(ECX, Address(ESP, +1 * kWordSize));  // Value.
-  __ movl(EBX, Address(ESP, +2 * kWordSize));  // Index.
-  __ movl(EAX, Address(ESP, +3 * kWordSize));  // OneByteString.
+void AsmIntrinsifier::OneByteStringSetAt(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ movl(ECX, Address(ESP, +1 * target::kWordSize));  // Value.
+  __ movl(EBX, Address(ESP, +2 * target::kWordSize));  // Index.
+  __ movl(EAX, Address(ESP, +3 * target::kWordSize));  // OneByteString.
   __ SmiUntag(EBX);
   __ SmiUntag(ECX);
-  __ movb(FieldAddress(EAX, EBX, TIMES_1, OneByteString::data_offset()), CL);
+  __ movb(FieldAddress(EAX, EBX, TIMES_1, target::OneByteString::data_offset()),
+          CL);
   __ ret();
 }
 
-void Intrinsifier::OneByteString_allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  __ movl(EDI, Address(ESP, +1 * kWordSize));  // Length.
+void AsmIntrinsifier::OneByteString_allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ movl(EDI, Address(ESP, +1 * target::kWordSize));  // Length.
   Label ok;
   TryAllocateOnebyteString(assembler, &ok, normal_ir_body, EDI);
   // EDI: Start address to copy from (untagged).
@@ -2070,8 +2111,8 @@
                            Label* normal_ir_body,
                            intptr_t string_cid) {
   Label is_true, is_false, loop;
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // This.
-  __ movl(EBX, Address(ESP, +1 * kWordSize));  // Other.
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // This.
+  __ movl(EBX, Address(ESP, +1 * target::kWordSize));  // Other.
 
   // Are identical?
   __ cmpl(EAX, EBX);
@@ -2084,8 +2125,8 @@
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   // Have same length?
-  __ movl(EDI, FieldAddress(EAX, String::length_offset()));
-  __ cmpl(EDI, FieldAddress(EBX, String::length_offset()));
+  __ movl(EDI, FieldAddress(EAX, target::String::length_offset()));
+  __ cmpl(EDI, FieldAddress(EBX, target::String::length_offset()));
   __ j(NOT_EQUAL, &is_false, Assembler::kNearJump);
 
   // Check contents, no fall-through possible.
@@ -2096,15 +2137,15 @@
   __ cmpl(EDI, Immediate(0));
   __ j(LESS, &is_true, Assembler::kNearJump);
   if (string_cid == kOneByteStringCid) {
-    __ movzxb(ECX,
-              FieldAddress(EAX, EDI, TIMES_1, OneByteString::data_offset()));
-    __ movzxb(EDX,
-              FieldAddress(EBX, EDI, TIMES_1, OneByteString::data_offset()));
+    __ movzxb(ECX, FieldAddress(EAX, EDI, TIMES_1,
+                                target::OneByteString::data_offset()));
+    __ movzxb(EDX, FieldAddress(EBX, EDI, TIMES_1,
+                                target::OneByteString::data_offset()));
   } else if (string_cid == kTwoByteStringCid) {
-    __ movzxw(ECX,
-              FieldAddress(EAX, EDI, TIMES_2, TwoByteString::data_offset()));
-    __ movzxw(EDX,
-              FieldAddress(EBX, EDI, TIMES_2, TwoByteString::data_offset()));
+    __ movzxw(ECX, FieldAddress(EAX, EDI, TIMES_2,
+                                target::TwoByteString::data_offset()));
+    __ movzxw(EDX, FieldAddress(EBX, EDI, TIMES_2,
+                                target::TwoByteString::data_offset()));
   } else {
     UNIMPLEMENTED();
   }
@@ -2113,33 +2154,33 @@
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&is_true);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&is_false);
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kOneByteStringCid);
 }
 
-void Intrinsifier::TwoByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kTwoByteStringCid);
 }
 
-void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
-                                                Label* normal_ir_body,
-                                                bool sticky) {
+void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                                   Label* normal_ir_body,
+                                                   bool sticky) {
   if (FLAG_interpret_irregexp) return;
 
-  static const intptr_t kRegExpParamOffset = 3 * kWordSize;
-  static const intptr_t kStringParamOffset = 2 * kWordSize;
+  static const intptr_t kRegExpParamOffset = 3 * target::kWordSize;
+  static const intptr_t kStringParamOffset = 2 * target::kWordSize;
   // start_index smi is located at offset 1.
 
   // Incoming registers:
@@ -2153,90 +2194,91 @@
   __ movl(EDI, Address(ESP, kStringParamOffset));
   __ LoadClassId(EDI, EDI);
   __ SubImmediate(EDI, Immediate(kOneByteStringCid));
-  __ movl(EAX,
-          FieldAddress(EBX, EDI, TIMES_4,
-                       RegExp::function_offset(kOneByteStringCid, sticky)));
+  __ movl(EAX, FieldAddress(
+                   EBX, EDI, TIMES_4,
+                   target::RegExp::function_offset(kOneByteStringCid, sticky)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in EAX, the argument descriptor in EDX, and IC-Data in ECX.
   __ xorl(ECX, ECX);
 
   // Tail-call the function.
-  __ movl(EDI, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(EDI, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EDI);
 }
 
 // On stack: user tag (+1), return-address (+0).
-void Intrinsifier::UserTag_makeCurrent(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
+                                          Label* normal_ir_body) {
   // RDI: Isolate.
   __ LoadIsolate(EDI);
   // EAX: Current user tag.
-  __ movl(EAX, Address(EDI, Isolate::current_tag_offset()));
+  __ movl(EAX, Address(EDI, target::Isolate::current_tag_offset()));
   // EAX: UserTag.
-  __ movl(EBX, Address(ESP, +1 * kWordSize));
-  // Set Isolate::current_tag_.
-  __ movl(Address(EDI, Isolate::current_tag_offset()), EBX);
+  __ movl(EBX, Address(ESP, +1 * target::kWordSize));
+  // Set target::Isolate::current_tag_.
+  __ movl(Address(EDI, target::Isolate::current_tag_offset()), EBX);
   // EAX: UserTag's tag.
-  __ movl(EBX, FieldAddress(EBX, UserTag::tag_offset()));
-  // Set Isolate::user_tag_.
-  __ movl(Address(EDI, Isolate::user_tag_offset()), EBX);
+  __ movl(EBX, FieldAddress(EBX, target::UserTag::tag_offset()));
+  // Set target::Isolate::user_tag_.
+  __ movl(Address(EDI, target::Isolate::user_tag_offset()), EBX);
   __ ret();
 }
 
-void Intrinsifier::UserTag_defaultTag(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
+                                         Label* normal_ir_body) {
   __ LoadIsolate(EAX);
-  __ movl(EAX, Address(EAX, Isolate::default_tag_offset()));
+  __ movl(EAX, Address(EAX, target::Isolate::default_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
+                                             Label* normal_ir_body) {
   __ LoadIsolate(EAX);
-  __ movl(EAX, Address(EAX, Isolate::current_tag_offset()));
+  __ movl(EAX, Address(EAX, target::Isolate::current_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
+                                                   Label* normal_ir_body) {
 #if !defined(SUPPORT_TIMELINE)
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
 #else
   Label true_label;
   // Load TimelineStream*.
-  __ movl(EAX, Address(THR, Thread::dart_stream_offset()));
+  __ movl(EAX, Address(THR, target::Thread::dart_stream_offset()));
   // Load uintptr_t from TimelineStream*.
-  __ movl(EAX, Address(EAX, TimelineStream::enabled_offset()));
+  __ movl(EAX, Address(EAX, target::TimelineStream::enabled_offset()));
   __ cmpl(EAX, Immediate(0));
   __ j(NOT_ZERO, &true_label, Assembler::kNearJump);
   // Not enabled.
-  __ LoadObject(EAX, Bool::False());
+  __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
   __ ret();
   // Enabled.
   __ Bind(&true_label);
-  __ LoadObject(EAX, Bool::True());
+  __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
   __ ret();
 #endif
 }
 
-void Intrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
-                                              Label* normal_ir_body) {
-  __ LoadObject(EAX, Object::null_object());
-  __ movl(Address(THR, Thread::async_stack_trace_offset()), EAX);
+void AsmIntrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  __ LoadObject(EAX, NullObject());
+  __ movl(Address(THR, target::Thread::async_stack_trace_offset()), EAX);
   __ ret();
 }
 
-void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
-                                            Label* normal_ir_body) {
-  __ movl(Address(THR, Thread::async_stack_trace_offset()), EAX);
-  __ LoadObject(EAX, Object::null_object());
+void AsmIntrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ movl(Address(THR, target::Thread::async_stack_trace_offset()), EAX);
+  __ LoadObject(EAX, NullObject());
   __ ret();
 }
 
 #undef __
 
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/intrinsifier_x64.cc b/runtime/vm/compiler/asm_intrinsifier_x64.cc
similarity index 67%
rename from runtime/vm/compiler/intrinsifier_x64.cc
rename to runtime/vm/compiler/asm_intrinsifier_x64.cc
index e313634..1c34df5 100644
--- a/runtime/vm/compiler/intrinsifier_x64.cc
+++ b/runtime/vm/compiler/asm_intrinsifier_x64.cc
@@ -1,22 +1,18 @@
-// Copyright (c) 2013, 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.
 
 #include "vm/globals.h"  // Needed here to get TARGET_ARCH_X64.
 #if defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
 
-#include "vm/compiler/intrinsifier.h"
+#define SHOULD_NOT_INCLUDE_RUNTIME
 
+#include "vm/class_id.h"
+#include "vm/compiler/asm_intrinsifier.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/regexp_assembler.h"
-#include "vm/symbols.h"
-#include "vm/timeline.h"
 
 namespace dart {
+namespace compiler {
 
 // When entering intrinsics code:
 // R10: Arguments descriptor
@@ -28,7 +24,7 @@
 
 #define __ assembler->
 
-intptr_t Intrinsifier::ParameterSlotFromSp() {
+intptr_t AsmIntrinsifier::ParameterSlotFromSp() {
   return 0;
 }
 
@@ -36,7 +32,7 @@
   return ((1 << reg) & CallingConventions::kCalleeSaveCpuRegisters) != 0;
 }
 
-void Intrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
   ASSERT(IsABIPreservedRegister(CODE_REG));
   ASSERT(!IsABIPreservedRegister(ARGS_DESC_REG));
   ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
@@ -47,49 +43,50 @@
   assembler->movq(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
 }
 
-void Intrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+void AsmIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
   assembler->Comment("IntrinsicCallEpilogue");
   assembler->movq(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
 }
 
 // Allocate a GrowableObjectArray using the backing array specified.
 // On stack: type argument (+2), data (+1), return-address (+0).
-void Intrinsifier::GrowableArray_Allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::GrowableArray_Allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
   // This snippet of inlined code uses the following registers:
   // RAX, RCX, R13
   // and the newly allocated object is returned in RAX.
-  const intptr_t kTypeArgumentsOffset = 2 * kWordSize;
-  const intptr_t kArrayOffset = 1 * kWordSize;
+  const intptr_t kTypeArgumentsOffset = 2 * target::kWordSize;
+  const intptr_t kArrayOffset = 1 * target::kWordSize;
 
   // Try allocating in new space.
-  const Class& cls = Class::Handle(
-      Isolate::Current()->object_store()->growable_object_array_class());
+  const Class& cls = GrowableObjectArrayClass();
   __ TryAllocate(cls, normal_ir_body, Assembler::kFarJump, RAX, R13);
 
   // Store backing array object in growable array object.
   __ movq(RCX, Address(RSP, kArrayOffset));  // data argument.
   // RAX is new, no barrier needed.
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, GrowableObjectArray::data_offset()), RCX);
+      RAX, FieldAddress(RAX, target::GrowableObjectArray::data_offset()), RCX);
 
   // RAX: new growable array object start as a tagged pointer.
   // Store the type argument field in the growable array object.
   __ movq(RCX, Address(RSP, kTypeArgumentsOffset));  // type argument.
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, GrowableObjectArray::type_arguments_offset()),
+      RAX,
+      FieldAddress(RAX, target::GrowableObjectArray::type_arguments_offset()),
       RCX);
 
   // Set the length field in the growable array object to 0.
-  __ ZeroInitSmiField(FieldAddress(RAX, GrowableObjectArray::length_offset()));
+  __ ZeroInitSmiField(
+      FieldAddress(RAX, target::GrowableObjectArray::length_offset()));
   __ ret();  // returns the newly allocated object in RAX.
 
   __ Bind(normal_ir_body);
 }
 
-#define TYPED_ARRAY_ALLOCATION(type_name, cid, max_len, scale_factor)          \
+#define TYPED_ARRAY_ALLOCATION(cid, max_len, scale_factor)                     \
   Label fall_through;                                                          \
-  const intptr_t kArrayLengthStackOffset = 1 * kWordSize;                      \
+  const intptr_t kArrayLengthStackOffset = 1 * target::kWordSize;              \
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(cid, normal_ir_body, false));         \
   __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */     \
   /* Check that length is a positive Smi. */                                   \
@@ -111,10 +108,11 @@
     scale_factor = TIMES_8;                                                    \
   }                                                                            \
   const intptr_t fixed_size_plus_alignment_padding =                           \
-      sizeof(Raw##type_name) + kObjectAlignment - 1;                           \
+      target::TypedData::InstanceSize() +                                      \
+      target::ObjectAlignment::kObjectAlignment - 1;                           \
   __ leaq(RDI, Address(RDI, scale_factor, fixed_size_plus_alignment_padding)); \
-  __ andq(RDI, Immediate(-kObjectAlignment));                                  \
-  __ movq(RAX, Address(THR, Thread::top_offset()));                            \
+  __ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));         \
+  __ movq(RAX, Address(THR, target::Thread::top_offset()));                    \
   __ movq(RCX, RAX);                                                           \
                                                                                \
   /* RDI: allocation size. */                                                  \
@@ -125,12 +123,12 @@
   /* RAX: potential new object start. */                                       \
   /* RCX: potential next object start. */                                      \
   /* RDI: allocation size. */                                                  \
-  __ cmpq(RCX, Address(THR, Thread::end_offset()));                            \
+  __ cmpq(RCX, Address(THR, target::Thread::end_offset()));                    \
   __ j(ABOVE_EQUAL, normal_ir_body);                                           \
                                                                                \
   /* Successfully allocated the object(s), now update top to point to */       \
   /* next object start and initialize the object. */                           \
-  __ movq(Address(THR, Thread::top_offset()), RCX);                            \
+  __ movq(Address(THR, target::Thread::top_offset()), RCX);                    \
   __ addq(RAX, Immediate(kHeapObjectTag));                                     \
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI));                  \
   /* Initialize the tags. */                                                   \
@@ -140,9 +138,10 @@
   /* R13: scratch register. */                                                 \
   {                                                                            \
     Label size_tag_overflow, done;                                             \
-    __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag));                  \
+    __ cmpq(RDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));            \
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);                     \
-    __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));    \
+    __ shlq(RDI, Immediate(target::RawObject::kTagBitsSizeTagPos -             \
+                           target::ObjectAlignment::kObjectAlignmentLog2));    \
     __ jmp(&done, Assembler::kNearJump);                                       \
                                                                                \
     __ Bind(&size_tag_overflow);                                               \
@@ -150,18 +149,18 @@
     __ Bind(&done);                                                            \
                                                                                \
     /* Get the class index and insert it into the tags. */                     \
-    uint32_t tags = 0;                                                         \
-    tags = RawObject::ClassIdTag::update(cid, tags);                           \
-    tags = RawObject::NewBit::update(true, tags);                              \
+    uint32_t tags =                                                            \
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);        \
     __ orq(RDI, Immediate(tags));                                              \
-    __ movq(FieldAddress(RAX, type_name::tags_offset()), RDI); /* Tags. */     \
+    __ movq(FieldAddress(RAX, target::Object::tags_offset()),                  \
+            RDI); /* Tags. */                                                  \
   }                                                                            \
   /* Set the length field. */                                                  \
   /* RAX: new object start as a tagged pointer. */                             \
   /* RCX: new object end address. */                                           \
   __ movq(RDI, Address(RSP, kArrayLengthStackOffset)); /* Array length. */     \
   __ StoreIntoObjectNoBarrier(                                                 \
-      RAX, FieldAddress(RAX, type_name::length_offset()), RDI);                \
+      RAX, FieldAddress(RAX, target::TypedData::length_offset()), RDI);        \
   /* Initialize all array elements to 0. */                                    \
   /* RAX: new object start as a tagged pointer. */                             \
   /* RCX: new object end address. */                                           \
@@ -169,13 +168,13 @@
   /* RBX: scratch register. */                                                 \
   /* data area to be initialized. */                                           \
   __ xorq(RBX, RBX); /* Zero. */                                               \
-  __ leaq(RDI, FieldAddress(RAX, sizeof(Raw##type_name)));                     \
+  __ leaq(RDI, FieldAddress(RAX, target::TypedData::InstanceSize()));          \
   Label done, init_loop;                                                       \
   __ Bind(&init_loop);                                                         \
   __ cmpq(RDI, RCX);                                                           \
   __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);                              \
   __ movq(Address(RDI, 0), RBX);                                               \
-  __ addq(RDI, Immediate(kWordSize));                                          \
+  __ addq(RDI, Immediate(target::kWordSize));                                  \
   __ jmp(&init_loop, Assembler::kNearJump);                                    \
   __ Bind(&done);                                                              \
                                                                                \
@@ -200,12 +199,12 @@
 }
 
 #define TYPED_DATA_ALLOCATOR(clazz)                                            \
-  void Intrinsifier::TypedData_##clazz##_factory(Assembler* assembler,         \
-                                                 Label* normal_ir_body) {      \
-    intptr_t size = TypedData::ElementSizeInBytes(kTypedData##clazz##Cid);     \
-    intptr_t max_len = TypedData::MaxNewSpaceElements(kTypedData##clazz##Cid); \
+  void AsmIntrinsifier::TypedData_##clazz##_factory(Assembler* assembler,      \
+                                                    Label* normal_ir_body) {   \
+    intptr_t size = TypedDataElementSizeInBytes(kTypedData##clazz##Cid);       \
+    intptr_t max_len = TypedDataMaxNewSpaceElements(kTypedData##clazz##Cid);   \
     ScaleFactor scale = GetScaleFactor(size);                                  \
-    TYPED_ARRAY_ALLOCATION(TypedData, kTypedData##clazz##Cid, max_len, scale); \
+    TYPED_ARRAY_ALLOCATION(kTypedData##clazz##Cid, max_len, scale);            \
   }
 CLASS_LIST_TYPED_DATA(TYPED_DATA_ALLOCATOR)
 #undef TYPED_DATA_ALLOCATOR
@@ -213,44 +212,44 @@
 // Tests if two top most arguments are smis, jumps to label not_smi if not.
 // Topmost argument is in RAX.
 static void TestBothArgumentsSmis(Assembler* assembler, Label* not_smi) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
-  __ movq(RCX, Address(RSP, +2 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
+  __ movq(RCX, Address(RSP, +2 * target::kWordSize));
   __ orq(RCX, RAX);
   __ testq(RCX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, not_smi);
 }
 
-void Intrinsifier::Integer_addFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_addFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX contains right argument.
-  __ addq(RAX, Address(RSP, +2 * kWordSize));
+  __ addq(RAX, Address(RSP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_add(Assembler* assembler, Label* normal_ir_body) {
   Integer_addFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_subFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_subFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX contains right argument, which is the actual minuend of subtraction.
-  __ subq(RAX, Address(RSP, +2 * kWordSize));
+  __ subq(RAX, Address(RSP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sub(Assembler* assembler, Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX contains right argument, which is the actual subtrahend of subtraction.
   __ movq(RCX, RAX);
-  __ movq(RAX, Address(RSP, +2 * kWordSize));
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));
   __ subq(RAX, RCX);
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in RAX.
@@ -258,20 +257,20 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mulFromInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mulFromInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX is the right argument.
   ASSERT(kSmiTag == 0);  // Adjust code below if not the case.
   __ SmiUntag(RAX);
-  __ imulq(RAX, Address(RSP, +2 * kWordSize));
+  __ imulq(RAX, Address(RSP, +2 * target::kWordSize));
   __ j(OVERFLOW, normal_ir_body, Assembler::kNearJump);
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_mul(Assembler* assembler, Label* normal_ir_body) {
   Integer_mulFromInteger(assembler, normal_ir_body);
 }
 
@@ -347,11 +346,11 @@
 //      res = res + right;
 //    }
 //  }
-void Intrinsifier::Integer_moduloFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_moduloFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label negative_result;
   TestBothArgumentsSmis(assembler, normal_ir_body);
-  __ movq(RCX, Address(RSP, +2 * kWordSize));
+  __ movq(RCX, Address(RSP, +2 * target::kWordSize));
   // RAX: Tagged left (dividend).
   // RCX: Tagged right (divisor).
   __ cmpq(RCX, Immediate(0));
@@ -381,15 +380,16 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_truncDivide(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_truncDivide(Assembler* assembler,
+                                          Label* normal_ir_body) {
   Label not_32bit;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX: right argument (divisor)
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);
   __ movq(RCX, RAX);
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left argument (dividend).
+  __ movq(RAX,
+          Address(RSP, +2 * target::kWordSize));  // Left argument (dividend).
 
   // Check if both operands fit into 32bits as idiv with 64bit operands
   // requires twice as many cycles and has much higher latency. We are checking
@@ -428,8 +428,9 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_negate(Assembler* assembler, Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+void AsmIntrinsifier::Integer_negate(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body, Assembler::kNearJump);  // Non-smi value.
   __ negq(RAX);
@@ -439,60 +440,63 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAndFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX is the right argument.
-  __ andq(RAX, Address(RSP, +2 * kWordSize));
+  __ andq(RAX, Address(RSP, +2 * target::kWordSize));
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitAnd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitAnd(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOrFromInteger(Assembler* assembler,
+                                               Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX is the right argument.
-  __ orq(RAX, Address(RSP, +2 * kWordSize));
+  __ orq(RAX, Address(RSP, +2 * target::kWordSize));
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitOr(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitOr(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_bitOrFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXorFromInteger(Assembler* assembler,
+                                                Label* normal_ir_body) {
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX is the right argument.
-  __ xorq(RAX, Address(RSP, +2 * kWordSize));
+  __ xorq(RAX, Address(RSP, +2 * target::kWordSize));
   // Result is in RAX.
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_bitXor(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_bitXor(Assembler* assembler,
+                                     Label* normal_ir_body) {
   Integer_bitXorFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_shl(Assembler* assembler, Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
   ASSERT(kSmiTag == 0);
   Label overflow;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // Shift value is in RAX. Compare with tagged Smi.
-  __ cmpq(RAX, Immediate(Smi::RawValue(Smi::kBits)));
+  __ cmpq(RAX, Immediate(target::ToRawSmi(target::Smi::kBits)));
   __ j(ABOVE_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ SmiUntag(RAX);
-  __ movq(RCX, RAX);                           // Shift amount must be in RCX.
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
+  __ movq(RCX, RAX);  // Shift amount must be in RCX.
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Value.
 
   // Overflow test - all the shifted-out bits must be same as the sign bit.
   __ movq(RDI, RAX);
@@ -518,78 +522,78 @@
   Label true_label;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   // RAX contains the right argument.
-  __ cmpq(Address(RSP, +2 * kWordSize), RAX);
+  __ cmpq(Address(RSP, +2 * target::kWordSize), RAX);
   __ j(true_condition, &true_label, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_lessThan(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  CompareIntegers(assembler, normal_ir_body, LESS);
-}
-
-void Intrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
-                                              Label* normal_ir_body) {
-  CompareIntegers(assembler, normal_ir_body, LESS);
-}
-
-void Intrinsifier::Integer_greaterThan(Assembler* assembler,
+void AsmIntrinsifier::Integer_lessThan(Assembler* assembler,
                                        Label* normal_ir_body) {
+  CompareIntegers(assembler, normal_ir_body, LESS);
+}
+
+void AsmIntrinsifier::Integer_greaterThanFromInt(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  CompareIntegers(assembler, normal_ir_body, LESS);
+}
+
+void AsmIntrinsifier::Integer_greaterThan(Assembler* assembler,
+                                          Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GREATER);
 }
 
-void Intrinsifier::Integer_lessEqualThan(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_lessEqualThan(Assembler* assembler,
+                                            Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, LESS_EQUAL);
 }
 
-void Intrinsifier::Integer_greaterEqualThan(Assembler* assembler,
-                                            Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_greaterEqualThan(Assembler* assembler,
+                                               Label* normal_ir_body) {
   CompareIntegers(assembler, normal_ir_body, GREATER_EQUAL);
 }
 
 // This is called for Smi and Mint receivers. The right argument
 // can be Smi, Mint or double.
-void Intrinsifier::Integer_equalToInteger(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equalToInteger(Assembler* assembler,
+                                             Label* normal_ir_body) {
   Label true_label, check_for_mint;
   const intptr_t kReceiverOffset = 2;
   const intptr_t kArgumentOffset = 1;
 
   // For integer receiver '===' check first.
-  __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
-  __ movq(RCX, Address(RSP, +kReceiverOffset * kWordSize));
+  __ movq(RAX, Address(RSP, +kArgumentOffset * target::kWordSize));
+  __ movq(RCX, Address(RSP, +kReceiverOffset * target::kWordSize));
   __ cmpq(RAX, RCX);
   __ j(EQUAL, &true_label, Assembler::kNearJump);
   __ orq(RAX, RCX);
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &check_for_mint, Assembler::kNearJump);
   // Both arguments are smi, '===' is good enough.
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&true_label);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // At least one of the arguments was not Smi.
   Label receiver_not_smi;
   __ Bind(&check_for_mint);
-  __ movq(RAX, Address(RSP, +kReceiverOffset * kWordSize));
+  __ movq(RAX, Address(RSP, +kReceiverOffset * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, &receiver_not_smi);
 
   // Left (receiver) is Smi, return false if right is not Double.
   // Note that an instance of Mint never contains a value that can be
   // represented by Smi.
-  __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
+  __ movq(RAX, Address(RSP, +kArgumentOffset * target::kWordSize));
   __ CompareClassId(RAX, kDoubleCid);
   __ j(EQUAL, normal_ir_body);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(&receiver_not_smi);
@@ -597,22 +601,23 @@
   __ CompareClassId(RAX, kMintCid);
   __ j(NOT_EQUAL, normal_ir_body);
   // Receiver is Mint, return false if right is Smi.
-  __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
+  __ movq(RAX, Address(RSP, +kArgumentOffset * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);
   // Smi == Mint -> false.
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   // TODO(srdjan): Implement Mint == Mint comparison.
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Integer_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_equal(Assembler* assembler,
+                                    Label* normal_ir_body) {
   Integer_equalToInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Integer_sar(Assembler* assembler, Label* normal_ir_body) {
   Label shift_count_ok;
   TestBothArgumentsSmis(assembler, normal_ir_body);
   const Immediate& count_limit = Immediate(0x3F);
@@ -627,9 +632,9 @@
   __ j(LESS_EQUAL, &shift_count_ok, Assembler::kNearJump);
   __ movq(RAX, count_limit);
   __ Bind(&shift_count_ok);
-  __ movq(RCX, RAX);                           // Shift amount must be in RCX.
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Value.
-  __ SmiUntag(RAX);                            // Value.
+  __ movq(RCX, RAX);  // Shift amount must be in RCX.
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Value.
+  __ SmiUntag(RAX);                                    // Value.
   __ sarq(RAX, RCX);
   __ SmiTag(RAX);
   __ ret();
@@ -637,16 +642,18 @@
 }
 
 // Argument is Smi (receiver).
-void Intrinsifier::Smi_bitNegate(Assembler* assembler, Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
+void AsmIntrinsifier::Smi_bitNegate(Assembler* assembler,
+                                    Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Index.
   __ notq(RAX);
   __ andq(RAX, Immediate(~kSmiTagMask));  // Remove inverted smi-tag.
   __ ret();
 }
 
-void Intrinsifier::Smi_bitLength(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitLength(Assembler* assembler,
+                                    Label* normal_ir_body) {
   ASSERT(kSmiTagShift == 1);
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // Index.
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Index.
   // XOR with sign bit to complement bits if value is negative.
   __ movq(RCX, RAX);
   __ sarq(RCX, Immediate(63));  // All 0 or all 1.
@@ -659,27 +666,29 @@
   __ ret();
 }
 
-void Intrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Smi_bitAndFromSmi(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Integer_bitAndFromInteger(assembler, normal_ir_body);
 }
 
-void Intrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_lsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _lsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
-  __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
-  __ movq(R8, Address(RSP, 3 * kWordSize));   // x_used is Smi
+  __ movq(RDI, Address(RSP, 4 * target::kWordSize));  // x_digits
+  __ movq(R8, Address(RSP, 3 * target::kWordSize));   // x_used is Smi
   __ subq(R8, Immediate(2));  // x_used > 0, Smi. R8 = x_used - 1, round up.
   __ sarq(R8, Immediate(2));  // R8 + 1 = number of digit pairs to read.
-  __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ movq(RCX, Address(RSP, 2 * target::kWordSize));  // n is Smi
   __ SmiUntag(RCX);
-  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
   __ movq(RSI, RCX);
   __ sarq(RSI, Immediate(6));  // RSI = n ~/ (2*_DIGIT_BITS).
-  __ leaq(RBX, FieldAddress(RBX, RSI, TIMES_8, TypedData::data_offset()));
+  __ leaq(RBX,
+          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
   __ xorq(RAX, RAX);  // RAX = 0.
-  __ movq(RDX, FieldAddress(RDI, R8, TIMES_8, TypedData::data_offset()));
+  __ movq(RDX,
+          FieldAddress(RDI, R8, TIMES_8, target::TypedData::data_offset()));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 2 * kBytesPerBigIntDigit), RAX);
   Label last;
@@ -688,9 +697,9 @@
   Label loop;
   __ Bind(&loop);
   __ movq(RAX, RDX);
-  __ movq(RDX,
-          FieldAddress(RDI, R8, TIMES_8,
-                       TypedData::data_offset() - 2 * kBytesPerBigIntDigit));
+  __ movq(RDX, FieldAddress(RDI, R8, TIMES_8,
+                            target::TypedData::data_offset() -
+                                2 * kBytesPerBigIntDigit));
   __ shldq(RAX, RDX, RCX);
   __ movq(Address(RBX, R8, TIMES_8, 0), RAX);
   __ decq(R8);
@@ -698,26 +707,28 @@
   __ Bind(&last);
   __ shldq(RDX, R8, RCX);  // R8 == 0.
   __ movq(Address(RBX, 0), RDX);
-  __ LoadObject(RAX, Object::null_object());
+  __ LoadObject(RAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_rsh(Assembler* assembler, Label* normal_ir_body) {
   // static void _rsh(Uint32List x_digits, int x_used, int n,
   //                  Uint32List r_digits)
 
-  __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
-  __ movq(RCX, Address(RSP, 2 * kWordSize));  // n is Smi
+  __ movq(RDI, Address(RSP, 4 * target::kWordSize));  // x_digits
+  __ movq(RCX, Address(RSP, 2 * target::kWordSize));  // n is Smi
   __ SmiUntag(RCX);
-  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
   __ movq(RDX, RCX);
-  __ sarq(RDX, Immediate(6));                 // RDX = n ~/ (2*_DIGIT_BITS).
-  __ movq(RSI, Address(RSP, 3 * kWordSize));  // x_used is Smi
+  __ sarq(RDX, Immediate(6));  // RDX = n ~/ (2*_DIGIT_BITS).
+  __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // x_used is Smi
   __ subq(RSI, Immediate(2));  // x_used > 0, Smi. RSI = x_used - 1, round up.
   __ sarq(RSI, Immediate(2));
-  __ leaq(RDI, FieldAddress(RDI, RSI, TIMES_8, TypedData::data_offset()));
+  __ leaq(RDI,
+          FieldAddress(RDI, RSI, TIMES_8, target::TypedData::data_offset()));
   __ subq(RSI, RDX);  // RSI + 1 = number of digit pairs to read.
-  __ leaq(RBX, FieldAddress(RBX, RSI, TIMES_8, TypedData::data_offset()));
+  __ leaq(RBX,
+          FieldAddress(RBX, RSI, TIMES_8, target::TypedData::data_offset()));
   __ negq(RSI);
   __ movq(RDX, Address(RDI, RSI, TIMES_8, 0));
   Label last;
@@ -734,24 +745,25 @@
   __ Bind(&last);
   __ shrdq(RDX, RSI, RCX);  // RSI == 0.
   __ movq(Address(RBX, 0), RDX);
-  __ LoadObject(RAX, Object::null_object());
+  __ LoadObject(RAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absAdd(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
-  __ movq(RDI, Address(RSP, 5 * kWordSize));  // digits
-  __ movq(R8, Address(RSP, 4 * kWordSize));   // used is Smi
+  __ movq(RDI, Address(RSP, 5 * target::kWordSize));  // digits
+  __ movq(R8, Address(RSP, 4 * target::kWordSize));   // used is Smi
   __ addq(R8, Immediate(2));  // used > 0, Smi. R8 = used + 1, round up.
   __ sarq(R8, Immediate(2));  // R8 = number of digit pairs to process.
-  __ movq(RSI, Address(RSP, 3 * kWordSize));  // a_digits
-  __ movq(RCX, Address(RSP, 2 * kWordSize));  // a_used is Smi
+  __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // a_digits
+  __ movq(RCX, Address(RSP, 2 * target::kWordSize));  // a_used is Smi
   __ addq(RCX, Immediate(2));  // a_used > 0, Smi. R8 = a_used + 1, round up.
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
-  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
@@ -761,9 +773,12 @@
   Label add_loop;
   __ Bind(&add_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX, FieldAddress(RDI, RDX, TIMES_8, TypedData::data_offset()));
-  __ adcq(RAX, FieldAddress(RSI, RDX, TIMES_8, TypedData::data_offset()));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()), RAX);
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ adcq(RAX,
+          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &add_loop, Assembler::kNearJump);
@@ -775,9 +790,11 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX, FieldAddress(RDI, RDX, TIMES_8, TypedData::data_offset()));
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
   __ adcq(RAX, Immediate(0));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()), RAX);
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
@@ -785,28 +802,29 @@
   __ Bind(&last_carry);
   Label done;
   __ j(NOT_CARRY, &done);
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()),
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
           Immediate(1));
 
   __ Bind(&done);
-  __ LoadObject(RAX, Object::null_object());
+  __ LoadObject(RAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_absSub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_absSub(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // static void _absSub(Uint32List digits, int used,
   //                     Uint32List a_digits, int a_used,
   //                     Uint32List r_digits)
 
-  __ movq(RDI, Address(RSP, 5 * kWordSize));  // digits
-  __ movq(R8, Address(RSP, 4 * kWordSize));   // used is Smi
+  __ movq(RDI, Address(RSP, 5 * target::kWordSize));  // digits
+  __ movq(R8, Address(RSP, 4 * target::kWordSize));   // used is Smi
   __ addq(R8, Immediate(2));  // used > 0, Smi. R8 = used + 1, round up.
   __ sarq(R8, Immediate(2));  // R8 = number of digit pairs to process.
-  __ movq(RSI, Address(RSP, 3 * kWordSize));  // a_digits
-  __ movq(RCX, Address(RSP, 2 * kWordSize));  // a_used is Smi
+  __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // a_digits
+  __ movq(RCX, Address(RSP, 2 * target::kWordSize));  // a_used is Smi
   __ addq(RCX, Immediate(2));  // a_used > 0, Smi. R8 = a_used + 1, round up.
   __ sarq(RCX, Immediate(2));  // R8 = number of digit pairs to process.
-  __ movq(RBX, Address(RSP, 1 * kWordSize));  // r_digits
+  __ movq(RBX, Address(RSP, 1 * target::kWordSize));  // r_digits
 
   // Precompute 'used - a_used' now so that carry flag is not lost later.
   __ subq(R8, RCX);
@@ -816,9 +834,12 @@
   Label sub_loop;
   __ Bind(&sub_loop);
   // Loop (a_used+1)/2 times, RCX > 0.
-  __ movq(RAX, FieldAddress(RDI, RDX, TIMES_8, TypedData::data_offset()));
-  __ sbbq(RAX, FieldAddress(RSI, RDX, TIMES_8, TypedData::data_offset()));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()), RAX);
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ sbbq(RAX,
+          FieldAddress(RSI, RDX, TIMES_8, target::TypedData::data_offset()));
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(RCX);  // Does not affect carry flag.
   __ j(NOT_ZERO, &sub_loop, Assembler::kNearJump);
@@ -830,19 +851,22 @@
   Label carry_loop;
   __ Bind(&carry_loop);
   // Loop (used+1)/2 - (a_used+1)/2 times, R8 > 0.
-  __ movq(RAX, FieldAddress(RDI, RDX, TIMES_8, TypedData::data_offset()));
+  __ movq(RAX,
+          FieldAddress(RDI, RDX, TIMES_8, target::TypedData::data_offset()));
   __ sbbq(RAX, Immediate(0));
-  __ movq(FieldAddress(RBX, RDX, TIMES_8, TypedData::data_offset()), RAX);
+  __ movq(FieldAddress(RBX, RDX, TIMES_8, target::TypedData::data_offset()),
+          RAX);
   __ incq(RDX);  // Does not affect carry flag.
   __ decq(R8);   // Does not affect carry flag.
   __ j(NOT_ZERO, &carry_loop, Assembler::kNearJump);
 
   __ Bind(&done);
-  __ LoadObject(RAX, Object::null_object());
+  __ LoadObject(RAX, NullObject());
   __ ret();
 }
 
-void Intrinsifier::Bigint_mulAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_mulAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulAdd(Uint32List x_digits, int xi,
   //                    Uint32List m_digits, int i,
@@ -873,27 +897,30 @@
 
   Label done;
   // RBX = x, done if x == 0
-  __ movq(RCX, Address(RSP, 7 * kWordSize));  // x_digits
-  __ movq(RAX, Address(RSP, 6 * kWordSize));  // xi is Smi
-  __ movq(RBX, FieldAddress(RCX, RAX, TIMES_2, TypedData::data_offset()));
+  __ movq(RCX, Address(RSP, 7 * target::kWordSize));  // x_digits
+  __ movq(RAX, Address(RSP, 6 * target::kWordSize));  // xi is Smi
+  __ movq(RBX,
+          FieldAddress(RCX, RAX, TIMES_2, target::TypedData::data_offset()));
   __ testq(RBX, RBX);
   __ j(ZERO, &done, Assembler::kNearJump);
 
   // R8 = (SmiUntag(n) + 1)/2, no_op if n == 0
-  __ movq(R8, Address(RSP, 1 * kWordSize));
+  __ movq(R8, Address(RSP, 1 * target::kWordSize));
   __ addq(R8, Immediate(2));
   __ sarq(R8, Immediate(2));  // R8 = number of digit pairs to process.
   __ j(ZERO, &done, Assembler::kNearJump);
 
   // RDI = mip = &m_digits[i >> 1]
-  __ movq(RDI, Address(RSP, 5 * kWordSize));  // m_digits
-  __ movq(RAX, Address(RSP, 4 * kWordSize));  // i is Smi
-  __ leaq(RDI, FieldAddress(RDI, RAX, TIMES_2, TypedData::data_offset()));
+  __ movq(RDI, Address(RSP, 5 * target::kWordSize));  // m_digits
+  __ movq(RAX, Address(RSP, 4 * target::kWordSize));  // i is Smi
+  __ leaq(RDI,
+          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RSI = ajp = &a_digits[j >> 1]
-  __ movq(RSI, Address(RSP, 3 * kWordSize));  // a_digits
-  __ movq(RAX, Address(RSP, 2 * kWordSize));  // j is Smi
-  __ leaq(RSI, FieldAddress(RSI, RAX, TIMES_2, TypedData::data_offset()));
+  __ movq(RSI, Address(RSP, 3 * target::kWordSize));  // a_digits
+  __ movq(RAX, Address(RSP, 2 * target::kWordSize));  // j is Smi
+  __ leaq(RSI,
+          FieldAddress(RSI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RCX = c = 0
   __ xorq(RCX, RCX);
@@ -945,11 +972,12 @@
   __ j(CARRY, &propagate_carry_loop, Assembler::kNearJump);
 
   __ Bind(&done);
-  __ movq(RAX, Immediate(Smi::RawValue(2)));  // Two digits processed.
+  __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_sqrAdd(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_sqrAdd(Assembler* assembler,
+                                    Label* normal_ir_body) {
   // Pseudo code:
   // static int _sqrAdd(Uint32List x_digits, int i,
   //                    Uint32List a_digits, int used) {
@@ -977,9 +1005,10 @@
   // }
 
   // RDI = xip = &x_digits[i >> 1]
-  __ movq(RDI, Address(RSP, 4 * kWordSize));  // x_digits
-  __ movq(RAX, Address(RSP, 3 * kWordSize));  // i is Smi
-  __ leaq(RDI, FieldAddress(RDI, RAX, TIMES_2, TypedData::data_offset()));
+  __ movq(RDI, Address(RSP, 4 * target::kWordSize));  // x_digits
+  __ movq(RAX, Address(RSP, 3 * target::kWordSize));  // i is Smi
+  __ leaq(RDI,
+          FieldAddress(RDI, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RBX = x = *xip++, return if x == 0
   Label x_zero;
@@ -989,8 +1018,9 @@
   __ addq(RDI, Immediate(2 * kBytesPerBigIntDigit));
 
   // RSI = ajp = &a_digits[i]
-  __ movq(RSI, Address(RSP, 2 * kWordSize));  // a_digits
-  __ leaq(RSI, FieldAddress(RSI, RAX, TIMES_4, TypedData::data_offset()));
+  __ movq(RSI, Address(RSP, 2 * target::kWordSize));  // a_digits
+  __ leaq(RSI,
+          FieldAddress(RSI, RAX, TIMES_4, target::TypedData::data_offset()));
 
   // RDX:RAX = t = x*x + *ajp
   __ movq(RAX, RBX);
@@ -1003,8 +1033,8 @@
   __ addq(RSI, Immediate(2 * kBytesPerBigIntDigit));
 
   // int n = (used - i + 1)/2 - 1
-  __ movq(R8, Address(RSP, 1 * kWordSize));  // used is Smi
-  __ subq(R8, Address(RSP, 3 * kWordSize));  // i is Smi
+  __ movq(R8, Address(RSP, 1 * target::kWordSize));  // used is Smi
+  __ subq(R8, Address(RSP, 3 * target::kWordSize));  // i is Smi
   __ addq(R8, Immediate(2));
   __ sarq(R8, Immediate(2));
   __ decq(R8);  // R8 = number of digit pairs to process.
@@ -1064,12 +1094,12 @@
   __ movq(Address(RSI, 2 * kBytesPerBigIntDigit), R13);
 
   __ Bind(&x_zero);
-  __ movq(RAX, Immediate(Smi::RawValue(2)));  // Two digits processed.
+  __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Bigint_estimateQuotientDigit(Assembler* assembler,
+                                                   Label* normal_ir_body) {
   // Pseudo code:
   // static int _estQuotientDigit(Uint32List args, Uint32List digits, int i) {
   //   uint64_t yt = args[_YT_LO .. _YT];  // _YT_LO == 0, _YT == 1.
@@ -1087,16 +1117,17 @@
   // }
 
   // RDI = args
-  __ movq(RDI, Address(RSP, 3 * kWordSize));  // args
+  __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
 
   // RCX = yt = args[0..1]
-  __ movq(RCX, FieldAddress(RDI, TypedData::data_offset()));
+  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset()));
 
   // RBX = dp = &digits[(i >> 1) - 1]
-  __ movq(RBX, Address(RSP, 2 * kWordSize));  // digits
-  __ movq(RAX, Address(RSP, 1 * kWordSize));  // i is Smi and odd.
-  __ leaq(RBX, FieldAddress(RBX, RAX, TIMES_2,
-                            TypedData::data_offset() - kBytesPerBigIntDigit));
+  __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
+  __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi and odd.
+  __ leaq(RBX, FieldAddress(
+                   RBX, RAX, TIMES_2,
+                   target::TypedData::data_offset() - kBytesPerBigIntDigit));
 
   // RDX = dh = dp[0]
   __ movq(RDX, Address(RBX, 0));
@@ -1117,16 +1148,16 @@
 
   __ Bind(&return_qd);
   // args[2..3] = qd
-  __ movq(
-      FieldAddress(RDI, TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
-      RAX);
+  __ movq(FieldAddress(
+              RDI, target::TypedData::data_offset() + 2 * kBytesPerBigIntDigit),
+          RAX);
 
-  __ movq(RAX, Immediate(Smi::RawValue(2)));  // Two digits processed.
+  __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
 }
 
-void Intrinsifier::Montgomery_mulMod(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::Montgomery_mulMod(Assembler* assembler,
+                                        Label* normal_ir_body) {
   // Pseudo code:
   // static int _mulMod(Uint32List args, Uint32List digits, int i) {
   //   uint64_t rho = args[_RHO .. _RHO_HI];  // _RHO == 2, _RHO_HI == 3.
@@ -1137,26 +1168,27 @@
   // }
 
   // RDI = args
-  __ movq(RDI, Address(RSP, 3 * kWordSize));  // args
+  __ movq(RDI, Address(RSP, 3 * target::kWordSize));  // args
 
   // RCX = rho = args[2 .. 3]
-  __ movq(RCX, FieldAddress(
-                   RDI, TypedData::data_offset() + 2 * kBytesPerBigIntDigit));
+  __ movq(RCX, FieldAddress(RDI, target::TypedData::data_offset() +
+                                     2 * kBytesPerBigIntDigit));
 
   // RAX = digits[i >> 1 .. (i >> 1) + 1]
-  __ movq(RBX, Address(RSP, 2 * kWordSize));  // digits
-  __ movq(RAX, Address(RSP, 1 * kWordSize));  // i is Smi
-  __ movq(RAX, FieldAddress(RBX, RAX, TIMES_2, TypedData::data_offset()));
+  __ movq(RBX, Address(RSP, 2 * target::kWordSize));  // digits
+  __ movq(RAX, Address(RSP, 1 * target::kWordSize));  // i is Smi
+  __ movq(RAX,
+          FieldAddress(RBX, RAX, TIMES_2, target::TypedData::data_offset()));
 
   // RDX:RAX = t = rho*d
   __ mulq(RCX);
 
   // args[4 .. 5] = t mod DIGIT_BASE^2 = low64(t)
-  __ movq(
-      FieldAddress(RDI, TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
-      RAX);
+  __ movq(FieldAddress(
+              RDI, target::TypedData::data_offset() + 4 * kBytesPerBigIntDigit),
+          RAX);
 
-  __ movq(RAX, Immediate(Smi::RawValue(2)));  // Two digits processed.
+  __ movq(RAX, Immediate(target::ToRawSmi(2)));  // Two digits processed.
   __ ret();
 }
 
@@ -1166,7 +1198,7 @@
 static void TestLastArgumentIsDouble(Assembler* assembler,
                                      Label* is_smi,
                                      Label* not_double_smi) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(ZERO, is_smi);  // Jump if Smi.
   __ CompareClassId(RAX, kDoubleCid);
@@ -1184,19 +1216,19 @@
   Label is_false, is_true, is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in RAX.
-  __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(RAX, target::Double::value_offset()));
   __ Bind(&double_op);
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left argument.
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Left argument.
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   __ comisd(XMM0, XMM1);
   __ j(PARITY_EVEN, &is_false, Assembler::kNearJump);  // NaN -> false;
   __ j(true_condition, &is_true, Assembler::kNearJump);
   // Fall through false.
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(RAX);
@@ -1205,27 +1237,28 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_greaterThan(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterThan(Assembler* assembler,
+                                         Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, ABOVE);
 }
 
-void Intrinsifier::Double_greaterEqualThan(Assembler* assembler,
-                                           Label* normal_ir_body) {
+void AsmIntrinsifier::Double_greaterEqualThan(Assembler* assembler,
+                                              Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, ABOVE_EQUAL);
 }
 
-void Intrinsifier::Double_lessThan(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessThan(Assembler* assembler,
+                                      Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, BELOW);
 }
 
-void Intrinsifier::Double_equal(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_equal(Assembler* assembler,
+                                   Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, EQUAL);
 }
 
-void Intrinsifier::Double_lessEqualThan(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_lessEqualThan(Assembler* assembler,
+                                           Label* normal_ir_body) {
   CompareDoubles(assembler, normal_ir_body, BELOW_EQUAL);
 }
 
@@ -1237,10 +1270,10 @@
   Label is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Both arguments are double, right operand is in RAX.
-  __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(RAX, target::Double::value_offset()));
   __ Bind(&double_op);
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left argument.
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Left argument.
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   switch (kind) {
     case Token::kADD:
       __ addsd(XMM0, XMM1);
@@ -1257,12 +1290,11 @@
     default:
       UNREACHABLE();
   }
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump,
                  RAX,  // Result register.
                  R13);
-  __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(RAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(RAX);
@@ -1271,112 +1303,110 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_add(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kADD);
 }
 
-void Intrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mul(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kMUL);
 }
 
-void Intrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_sub(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kSUB);
 }
 
-void Intrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::Double_div(Assembler* assembler, Label* normal_ir_body) {
   DoubleArithmeticOperations(assembler, normal_ir_body, Token::kDIV);
 }
 
-void Intrinsifier::Double_mulFromInteger(Assembler* assembler,
-                                         Label* normal_ir_body) {
+void AsmIntrinsifier::Double_mulFromInteger(Assembler* assembler,
+                                            Label* normal_ir_body) {
   // Only smis allowed.
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);
   // Is Smi.
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM1, RAX);
-  __ movq(RAX, Address(RSP, +2 * kWordSize));
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   __ mulsd(XMM0, XMM1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump,
                  RAX,  // Result register.
                  R13);
-  __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(RAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(normal_ir_body);
 }
 
 // Left is double, right is integer (Mint or Smi)
-void Intrinsifier::DoubleFromInteger(Assembler* assembler,
-                                     Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+void AsmIntrinsifier::DoubleFromInteger(Assembler* assembler,
+                                        Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ testq(RAX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);
   // Is Smi.
   __ SmiUntag(RAX);
   __ cvtsi2sdq(XMM0, RAX);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump,
                  RAX,  // Result register.
                  R13);
-  __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(RAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_getIsNaN(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNaN(Assembler* assembler,
+                                      Label* normal_ir_body) {
   Label is_true;
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   __ comisd(XMM0, XMM0);
   __ j(PARITY_EVEN, &is_true, Assembler::kNearJump);  // NaN -> true;
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
-void Intrinsifier::Double_getIsInfinite(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsInfinite(Assembler* assembler,
+                                           Label* normal_ir_body) {
   Label is_inf, done;
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
-  __ movq(RAX, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
+  __ movq(RAX, FieldAddress(RAX, target::Double::value_offset()));
   // Mask off the sign.
   __ AndImmediate(RAX, Immediate(0x7FFFFFFFFFFFFFFFLL));
   // Compare with +infinity.
   __ CompareImmediate(RAX, Immediate(0x7FF0000000000000LL));
   __ j(EQUAL, &is_inf, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ jmp(&done);
 
   __ Bind(&is_inf);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
 
   __ Bind(&done);
   __ ret();
 }
 
-void Intrinsifier::Double_getIsNegative(Assembler* assembler,
-                                        Label* normal_ir_body) {
+void AsmIntrinsifier::Double_getIsNegative(Assembler* assembler,
+                                           Label* normal_ir_body) {
   Label is_false, is_true, is_zero;
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   __ xorpd(XMM1, XMM1);  // 0.0 -> XMM1.
   __ comisd(XMM0, XMM1);
   __ j(PARITY_EVEN, &is_false, Assembler::kNearJump);  // NaN -> false.
   __ j(EQUAL, &is_zero, Assembler::kNearJump);  // Check for negative zero.
   __ j(ABOVE_EQUAL, &is_false, Assembler::kNearJump);  // >= 0 -> false.
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_zero);
   // Check for negative zero (get the sign bit).
@@ -1386,10 +1416,10 @@
   __ jmp(&is_false, Assembler::kNearJump);
 }
 
-void Intrinsifier::DoubleToInteger(Assembler* assembler,
-                                   Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(RAX, Double::value_offset()));
+void AsmIntrinsifier::DoubleToInteger(Assembler* assembler,
+                                      Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(RAX, target::Double::value_offset()));
   __ cvttsd2siq(RAX, XMM0);
   // Overflow is signalled with minint.
   // Check for overflow and that it fits into Smi.
@@ -1401,14 +1431,14 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::Double_hashCode(Assembler* assembler,
-                                   Label* normal_ir_body) {
+void AsmIntrinsifier::Double_hashCode(Assembler* assembler,
+                                      Label* normal_ir_body) {
   // TODO(dartbug.com/31174): Convert this to a graph intrinsic.
 
   // Convert double value to signed 64-bit int in RAX and
   // back to a double in XMM1.
-  __ movq(RCX, Address(RSP, +1 * kWordSize));
-  __ movsd(XMM0, FieldAddress(RCX, Double::value_offset()));
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));
+  __ movsd(XMM0, FieldAddress(RCX, target::Double::value_offset()));
   __ cvttsd2siq(RAX, XMM0);
   __ cvtsi2sdq(XMM1, RAX);
 
@@ -1428,7 +1458,7 @@
 
   // Convert the double bits to a hash code that fits in a Smi.
   __ Bind(&double_hash);
-  __ movq(RAX, FieldAddress(RCX, Double::value_offset()));
+  __ movq(RAX, FieldAddress(RCX, target::Double::value_offset()));
   __ movq(RCX, RAX);
   __ shrq(RCX, Immediate(32));
   __ xorq(RAX, RCX);
@@ -1440,19 +1470,18 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::MathSqrt(Assembler* assembler, Label* normal_ir_body) {
   Label is_smi, double_op;
   TestLastArgumentIsDouble(assembler, &is_smi, normal_ir_body);
   // Argument is double and is in RAX.
-  __ movsd(XMM1, FieldAddress(RAX, Double::value_offset()));
+  __ movsd(XMM1, FieldAddress(RAX, target::Double::value_offset()));
   __ Bind(&double_op);
   __ sqrtsd(XMM0, XMM1);
-  const Class& double_class =
-      Class::Handle(Isolate::Current()->object_store()->double_class());
+  const Class& double_class = DoubleClass();
   __ TryAllocate(double_class, normal_ir_body, Assembler::kFarJump,
                  RAX,  // Result register.
                  R13);
-  __ movsd(FieldAddress(RAX, Double::value_offset()), XMM0);
+  __ movsd(FieldAddress(RAX, target::Double::value_offset()), XMM0);
   __ ret();
   __ Bind(&is_smi);
   __ SmiUntag(RAX);
@@ -1464,25 +1493,20 @@
 //    var state = ((_A * (_state[kSTATE_LO])) + _state[kSTATE_HI]) & _MASK_64;
 //    _state[kSTATE_LO] = state & _MASK_32;
 //    _state[kSTATE_HI] = state >> 32;
-void Intrinsifier::Random_nextState(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  const Library& math_lib = Library::Handle(Library::MathLibrary());
-  ASSERT(!math_lib.IsNull());
-  const Class& random_class =
-      Class::Handle(math_lib.LookupClassAllowPrivate(Symbols::_Random()));
-  ASSERT(!random_class.IsNull());
-  const Field& state_field = Field::ZoneHandle(
-      random_class.LookupInstanceFieldAllowPrivate(Symbols::_state()));
-  ASSERT(!state_field.IsNull());
-  const int64_t a_int_value = Intrinsifier::kRandomAValue;
+void AsmIntrinsifier::Random_nextState(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  const Field& state_field = LookupMathRandomStateFieldOffset();
+  const int64_t a_int_value = AsmIntrinsifier::kRandomAValue;
 
   // Receiver.
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   // Field '_state'.
-  __ movq(RBX, FieldAddress(RAX, state_field.Offset()));
+  __ movq(RBX, FieldAddress(RAX, LookupFieldOffsetInBytes(state_field)));
   // Addresses of _state[0] and _state[1].
-  const intptr_t scale = Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
-  const intptr_t offset = Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
+  const intptr_t scale =
+      target::Instance::ElementSizeFor(kTypedDataUint32ArrayCid);
+  const intptr_t offset =
+      target::Instance::DataOffsetFor(kTypedDataUint32ArrayCid);
   Address addr_0 = FieldAddress(RBX, 0 * scale + offset);
   Address addr_1 = FieldAddress(RBX, 1 * scale + offset);
   __ movq(RAX, Immediate(a_int_value));
@@ -1493,24 +1517,25 @@
   __ movl(addr_0, RDX);
   __ shrq(RDX, Immediate(32));
   __ movl(addr_1, RDX);
-  ASSERT(Smi::RawValue(0) == 0);
+  ASSERT(target::ToRawSmi(0) == 0);
   __ xorq(RAX, RAX);
   __ ret();
 }
 
 // Identity comparison.
-void Intrinsifier::ObjectEquals(Assembler* assembler, Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectEquals(Assembler* assembler,
+                                   Label* normal_ir_body) {
   Label is_true;
   const intptr_t kReceiverOffset = 2;
   const intptr_t kArgumentOffset = 1;
 
-  __ movq(RAX, Address(RSP, +kArgumentOffset * kWordSize));
-  __ cmpq(RAX, Address(RSP, +kReceiverOffset * kWordSize));
+  __ movq(RAX, Address(RSP, +kArgumentOffset * target::kWordSize));
+  __ cmpq(RAX, Address(RSP, +kReceiverOffset * target::kWordSize));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
@@ -1549,10 +1574,10 @@
 }
 
 // Return type quickly for simple types (not parameterized and not signature).
-void Intrinsifier::ObjectRuntimeType(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectRuntimeType(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label use_declaration_type, not_integer, not_double;
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(RCX, RAX);
 
   // RCX: untagged cid of instance (RAX).
@@ -1567,8 +1592,8 @@
   __ j(NOT_EQUAL, &not_double);
 
   __ LoadIsolate(RAX);
-  __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
-  __ movq(RAX, Address(RAX, ObjectStore::double_type_offset()));
+  __ movq(RAX, Address(RAX, target::Isolate::object_store_offset()));
+  __ movq(RAX, Address(RAX, target::ObjectStore::double_type_offset()));
   __ ret();
 
   __ Bind(&not_double);
@@ -1577,8 +1602,8 @@
   JumpIfNotInteger(assembler, RAX, &not_integer);
 
   __ LoadIsolate(RAX);
-  __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
-  __ movq(RAX, Address(RAX, ObjectStore::int_type_offset()));
+  __ movq(RAX, Address(RAX, target::Isolate::object_store_offset()));
+  __ movq(RAX, Address(RAX, target::ObjectStore::int_type_offset()));
   __ ret();
 
   __ Bind(&not_integer);
@@ -1588,36 +1613,37 @@
   JumpIfNotString(assembler, RAX, &use_declaration_type);
 
   __ LoadIsolate(RAX);
-  __ movq(RAX, Address(RAX, Isolate::object_store_offset()));
-  __ movq(RAX, Address(RAX, ObjectStore::string_type_offset()));
+  __ movq(RAX, Address(RAX, target::Isolate::object_store_offset()));
+  __ movq(RAX, Address(RAX, target::ObjectStore::string_type_offset()));
   __ ret();
 
   // Object is neither double, nor integer, nor string.
   __ Bind(&use_declaration_type);
   __ LoadClassById(RDI, RCX);
-  __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
+  __ movzxw(RCX, FieldAddress(
+                     RDI, target::Class::num_type_arguments_offset_in_bytes()));
   __ cmpq(RCX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
-  __ movq(RAX, FieldAddress(RDI, Class::declaration_type_offset()));
-  __ CompareObject(RAX, Object::null_object());
+  __ movq(RAX, FieldAddress(RDI, target::Class::declaration_type_offset()));
+  __ CompareObject(RAX, NullObject());
   __ j(EQUAL, normal_ir_body, Assembler::kNearJump);  // Not yet set.
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::ObjectHaveSameRuntimeType(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label different_cids, equal, not_equal, not_integer;
 
-  __ movq(RAX, Address(RSP, +1 * kWordSize));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));
   __ LoadClassIdMayBeSmi(RCX, RAX);
 
   // Check if left hand size is a closure. Closures are handled in the runtime.
   __ cmpq(RCX, Immediate(kClosureCid));
   __ j(EQUAL, normal_ir_body);
 
-  __ movq(RAX, Address(RSP, +2 * kWordSize));
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));
   __ LoadClassIdMayBeSmi(RDX, RAX);
 
   // Check whether class ids match. If class ids don't match objects can still
@@ -1630,12 +1656,13 @@
   // Check if there are no type arguments. In this case we can return true.
   // Otherwise fall through into the runtime to handle comparison.
   __ LoadClassById(RDI, RCX);
-  __ movzxw(RCX, FieldAddress(RDI, Class::num_type_arguments_offset()));
+  __ movzxw(RCX, FieldAddress(
+                     RDI, target::Class::num_type_arguments_offset_in_bytes()));
   __ cmpq(RCX, Immediate(0));
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   __ Bind(&equal);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   // Class ids are different. Check if we are comparing runtime types of
@@ -1664,16 +1691,16 @@
   // Fall-through to the not equal case.
 
   __ Bind(&not_equal);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::String_getHashCode(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // String object.
-  __ movl(RAX, FieldAddress(RAX, String::hash_offset()));
+void AsmIntrinsifier::String_getHashCode(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // String object.
+  __ movl(RAX, FieldAddress(RAX, target::String::hash_offset()));
   ASSERT(kSmiTag == 0);
   ASSERT(kSmiTagShift == 1);
   __ addq(RAX, RAX);  // Smi tag RAX, setting Z flag.
@@ -1683,10 +1710,10 @@
   // Hash not yet computed.
 }
 
-void Intrinsifier::Type_getHashCode(Assembler* assembler,
-                                    Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // Type object.
-  __ movq(RAX, FieldAddress(RAX, Type::hash_offset()));
+void AsmIntrinsifier::Type_getHashCode(Assembler* assembler,
+                                       Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Type object.
+  __ movq(RAX, FieldAddress(RAX, target::Type::hash_offset()));
   ASSERT(kSmiTag == 0);
   ASSERT(kSmiTagShift == 1);
   __ testq(RAX, RAX);
@@ -1696,18 +1723,20 @@
   // Hash not yet computed.
 }
 
-void Intrinsifier::Object_getHash(Assembler* assembler, Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // Object.
-  __ movl(RAX, FieldAddress(RAX, String::hash_offset()));
+void AsmIntrinsifier::Object_getHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // Object.
+  __ movl(RAX, FieldAddress(RAX, target::String::hash_offset()));
   __ SmiTag(RAX);
   __ ret();
 }
 
-void Intrinsifier::Object_setHash(Assembler* assembler, Label* normal_ir_body) {
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Object.
-  __ movq(RDX, Address(RSP, +1 * kWordSize));  // Value.
+void AsmIntrinsifier::Object_setHash(Assembler* assembler,
+                                     Label* normal_ir_body) {
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Object.
+  __ movq(RDX, Address(RSP, +1 * target::kWordSize));  // Value.
   __ SmiUntag(RDX);
-  __ movl(FieldAddress(RAX, String::hash_offset()), RDX);
+  __ movl(FieldAddress(RAX, target::String::hash_offset()), RDX);
   __ ret();
 }
 
@@ -1716,8 +1745,8 @@
                                             intptr_t other_cid,
                                             Label* return_true,
                                             Label* return_false) {
-  __ movq(R8, FieldAddress(RAX, String::length_offset()));
-  __ movq(R9, FieldAddress(RCX, String::length_offset()));
+  __ movq(R8, FieldAddress(RAX, target::String::length_offset()));
+  __ movq(R9, FieldAddress(RCX, target::String::length_offset()));
 
   // if (other.length == 0) return true;
   __ testq(R9, R9);
@@ -1733,8 +1762,8 @@
   __ cmpq(R11, R8);
   __ j(GREATER, return_false);
 
-  __ SmiUntag(RBX);            // start
-  __ SmiUntag(R9);             // other.length
+  __ SmiUntag(RBX);                     // start
+  __ SmiUntag(R9);                      // other.length
   __ LoadImmediate(R11, Immediate(0));  // i = 0
 
   // do
@@ -1746,21 +1775,21 @@
   __ movq(R8, R11);
   __ addq(R8, RBX);
   if (receiver_cid == kOneByteStringCid) {
-    __ movzxb(R12,
-              FieldAddress(RAX, R8, TIMES_1, OneByteString::data_offset()));
+    __ movzxb(R12, FieldAddress(RAX, R8, TIMES_1,
+                                target::OneByteString::data_offset()));
   } else {
     ASSERT(receiver_cid == kTwoByteStringCid);
-    __ movzxw(R12,
-              FieldAddress(RAX, R8, TIMES_2, TwoByteString::data_offset()));
+    __ movzxw(R12, FieldAddress(RAX, R8, TIMES_2,
+                                target::TwoByteString::data_offset()));
   }
   // other.codeUnitAt(i)
   if (other_cid == kOneByteStringCid) {
-    __ movzxb(R13,
-              FieldAddress(RCX, R11, TIMES_1, OneByteString::data_offset()));
+    __ movzxb(R13, FieldAddress(RCX, R11, TIMES_1,
+                                target::OneByteString::data_offset()));
   } else {
     ASSERT(other_cid == kTwoByteStringCid);
-    __ movzxw(R13,
-              FieldAddress(RCX, R11, TIMES_2, TwoByteString::data_offset()));
+    __ movzxw(R13, FieldAddress(RCX, R11, TIMES_2,
+                                target::TwoByteString::data_offset()));
   }
   __ cmpq(R12, R13);
   __ j(NOT_EQUAL, return_false);
@@ -1776,12 +1805,12 @@
 // bool _substringMatches(int start, String other)
 // This intrinsic handles a OneByteString or TwoByteString receiver with a
 // OneByteString other.
-void Intrinsifier::StringBaseSubstringMatches(Assembler* assembler,
-                                              Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseSubstringMatches(Assembler* assembler,
+                                                 Label* normal_ir_body) {
   Label return_true, return_false, try_two_byte;
-  __ movq(RAX, Address(RSP, +3 * kWordSize));  // receiver
-  __ movq(RBX, Address(RSP, +2 * kWordSize));  // start
-  __ movq(RCX, Address(RSP, +1 * kWordSize));  // other
+  __ movq(RAX, Address(RSP, +3 * target::kWordSize));  // receiver
+  __ movq(RBX, Address(RSP, +2 * target::kWordSize));  // start
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // other
 
   __ testq(RBX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);  // 'start' is not Smi.
@@ -1805,73 +1834,81 @@
                                          &return_false);
 
   __ Bind(&return_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&return_false);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseCharAt(Assembler* assembler,
-                                    Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseCharAt(Assembler* assembler,
+                                       Label* normal_ir_body) {
   Label try_two_byte_string;
-  __ movq(RCX, Address(RSP, +1 * kWordSize));  // Index.
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // String.
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Index.
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // String.
   __ testq(RCX, Immediate(kSmiTagMask));
   __ j(NOT_ZERO, normal_ir_body);  // Non-smi index.
   // Range check.
-  __ cmpq(RCX, FieldAddress(RAX, String::length_offset()));
+  __ cmpq(RCX, FieldAddress(RAX, target::String::length_offset()));
   // Runtime throws exception.
   __ j(ABOVE_EQUAL, normal_ir_body);
   __ CompareClassId(RAX, kOneByteStringCid);
   __ j(NOT_EQUAL, &try_two_byte_string, Assembler::kNearJump);
   __ SmiUntag(RCX);
-  __ movzxb(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
-  __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
+  __ movzxb(RCX, FieldAddress(RAX, RCX, TIMES_1,
+                              target::OneByteString::data_offset()));
+  __ cmpq(RCX, Immediate(target::Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, normal_ir_body);
-  __ movq(RAX, Address(THR, Thread::predefined_symbols_address_offset()));
+  __ movq(RAX,
+          Address(THR, target::Thread::predefined_symbols_address_offset()));
   __ movq(RAX, Address(RAX, RCX, TIMES_8,
-                       Symbols::kNullCharCodeSymbolOffset * kWordSize));
+                       target::Symbols::kNullCharCodeSymbolOffset *
+                           target::kWordSize));
   __ ret();
 
   __ Bind(&try_two_byte_string);
   __ CompareClassId(RAX, kTwoByteStringCid);
   __ j(NOT_EQUAL, normal_ir_body);
   ASSERT(kSmiTagShift == 1);
-  __ movzxw(RCX, FieldAddress(RAX, RCX, TIMES_1, OneByteString::data_offset()));
-  __ cmpq(RCX, Immediate(Symbols::kNumberOfOneCharCodeSymbols));
+  __ movzxw(RCX, FieldAddress(RAX, RCX, TIMES_1,
+                              target::OneByteString::data_offset()));
+  __ cmpq(RCX, Immediate(target::Symbols::kNumberOfOneCharCodeSymbols));
   __ j(GREATER_EQUAL, normal_ir_body);
-  __ movq(RAX, Address(THR, Thread::predefined_symbols_address_offset()));
+  __ movq(RAX,
+          Address(THR, target::Thread::predefined_symbols_address_offset()));
   __ movq(RAX, Address(RAX, RCX, TIMES_8,
-                       Symbols::kNullCharCodeSymbolOffset * kWordSize));
+                       target::Symbols::kNullCharCodeSymbolOffset *
+                           target::kWordSize));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::StringBaseIsEmpty(Assembler* assembler,
-                                     Label* normal_ir_body) {
+void AsmIntrinsifier::StringBaseIsEmpty(Assembler* assembler,
+                                        Label* normal_ir_body) {
   Label is_true;
   // Get length.
-  __ movq(RAX, Address(RSP, +1 * kWordSize));  // String object.
-  __ movq(RAX, FieldAddress(RAX, String::length_offset()));
-  __ cmpq(RAX, Immediate(Smi::RawValue(0)));
+  __ movq(RAX, Address(RSP, +1 * target::kWordSize));  // String object.
+  __ movq(RAX, FieldAddress(RAX, target::String::length_offset()));
+  __ cmpq(RAX, Immediate(target::ToRawSmi(0)));
   __ j(EQUAL, &is_true, Assembler::kNearJump);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 }
 
-void Intrinsifier::OneByteString_getHashCode(Assembler* assembler,
-                                             Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_getHashCode(Assembler* assembler,
+                                                Label* normal_ir_body) {
   Label compute_hash;
-  __ movq(RBX, Address(RSP, +1 * kWordSize));  // OneByteString object.
-  __ movl(RAX, FieldAddress(RBX, String::hash_offset()));
+  __ movq(
+      RBX,
+      Address(RSP, +1 * target::kWordSize));  // target::OneByteString object.
+  __ movl(RAX, FieldAddress(RBX, target::String::hash_offset()));
   __ cmpq(RAX, Immediate(0));
   __ j(EQUAL, &compute_hash, Assembler::kNearJump);
   __ SmiTag(RAX);
@@ -1879,11 +1916,11 @@
 
   __ Bind(&compute_hash);
   // Hash not yet computed, use algorithm of class StringHasher.
-  __ movq(RCX, FieldAddress(RBX, String::length_offset()));
+  __ movq(RCX, FieldAddress(RBX, target::String::length_offset()));
   __ SmiUntag(RCX);
   __ xorq(RAX, RAX);
   __ xorq(RDI, RDI);
-  // RBX: Instance of OneByteString.
+  // RBX: Instance of target::OneByteString.
   // RCX: String length, untagged integer.
   // RDI: Loop counter, untagged integer.
   // RAX: Hash code, untagged integer.
@@ -1896,7 +1933,8 @@
   // hash_ += hash_ << 10;
   // hash_ ^= hash_ >> 6;
   // Get one characters (ch).
-  __ movzxb(RDX, FieldAddress(RBX, RDI, TIMES_1, OneByteString::data_offset()));
+  __ movzxb(RDX, FieldAddress(RBX, RDI, TIMES_1,
+                              target::OneByteString::data_offset()));
   // RDX: ch and temporary.
   __ addl(RAX, RDX);
   __ movq(RDX, RAX);
@@ -1924,15 +1962,16 @@
   __ shll(RDX, Immediate(15));
   __ addl(RAX, RDX);
   // hash_ = hash_ & ((static_cast<intptr_t>(1) << bits) - 1);
-  __ andl(RAX,
-          Immediate(((static_cast<intptr_t>(1) << String::kHashBits) - 1)));
+  __ andl(
+      RAX,
+      Immediate(((static_cast<intptr_t>(1) << target::String::kHashBits) - 1)));
 
   // return hash_ == 0 ? 1 : hash_;
   __ cmpq(RAX, Immediate(0));
   __ j(NOT_EQUAL, &set_hash_code, Assembler::kNearJump);
   __ incq(RAX);
   __ Bind(&set_hash_code);
-  __ movl(FieldAddress(RBX, String::hash_offset()), RAX);
+  __ movl(FieldAddress(RBX, target::String::hash_offset()), RAX);
   __ SmiTag(RAX);
   __ ret();
 }
@@ -1959,12 +1998,13 @@
   __ addq(RDI, Immediate(1));
   __ Bind(&not_zero_length);
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawString) + kObjectAlignment - 1;
+      target::String::InstanceSize() +
+      target::ObjectAlignment::kObjectAlignment - 1;
   __ addq(RDI, Immediate(fixed_size_plus_alignment_padding));
-  __ andq(RDI, Immediate(-kObjectAlignment));
+  __ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
   const intptr_t cid = kOneByteStringCid;
-  __ movq(RAX, Address(THR, Thread::top_offset()));
+  __ movq(RAX, Address(THR, target::Thread::top_offset()));
 
   // RDI: allocation size.
   __ movq(RCX, RAX);
@@ -1975,12 +2015,12 @@
   // RAX: potential new object start.
   // RCX: potential next object start.
   // RDI: allocation size.
-  __ cmpq(RCX, Address(THR, Thread::end_offset()));
+  __ cmpq(RCX, Address(THR, target::Thread::end_offset()));
   __ j(ABOVE_EQUAL, &pop_and_fail);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movq(Address(THR, Thread::top_offset()), RCX);
+  __ movq(Address(THR, target::Thread::top_offset()), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI));
 
@@ -1989,9 +2029,10 @@
   // RDI: allocation size.
   {
     Label size_tag_overflow, done;
-    __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
+    __ cmpq(RDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+    __ shlq(RDI, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
     __ Bind(&size_tag_overflow);
@@ -2000,17 +2041,16 @@
 
     // Get the class index and insert it into the tags.
     // This also clears the hash, which is in the high bits of the tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
     __ orq(RDI, Immediate(tags));
-    __ movq(FieldAddress(RAX, String::tags_offset()), RDI);  // Tags.
+    __ movq(FieldAddress(RAX, target::Object::tags_offset()), RDI);  // Tags.
   }
 
   // Set the length field.
   __ popq(RDI);
-  __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, String::length_offset()),
-                              RDI);
+  __ StoreIntoObjectNoBarrier(
+      RAX, FieldAddress(RAX, target::String::length_offset()), RDI);
   __ jmp(ok, Assembler::kNearJump);
 
   __ Bind(&pop_and_fail);
@@ -2018,15 +2058,15 @@
   __ jmp(failure);
 }
 
-// Arg0: OneByteString (receiver).
+// Arg0: target::OneByteString (receiver).
 // Arg1: Start index as Smi.
 // Arg2: End index as Smi.
 // The indexes must be valid.
-void Intrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
-                                                    Label* normal_ir_body) {
-  const intptr_t kStringOffset = 3 * kWordSize;
-  const intptr_t kStartIndexOffset = 2 * kWordSize;
-  const intptr_t kEndIndexOffset = 1 * kWordSize;
+void AsmIntrinsifier::OneByteString_substringUnchecked(Assembler* assembler,
+                                                       Label* normal_ir_body) {
+  const intptr_t kStringOffset = 3 * target::kWordSize;
+  const intptr_t kStartIndexOffset = 2 * target::kWordSize;
+  const intptr_t kEndIndexOffset = 1 * target::kWordSize;
   Label ok;
   __ movq(RSI, Address(RSP, +kStartIndexOffset));
   __ movq(RDI, Address(RSP, +kEndIndexOffset));
@@ -2042,7 +2082,8 @@
   __ movq(RSI, Address(RSP, +kStringOffset));
   __ movq(RBX, Address(RSP, +kStartIndexOffset));
   __ SmiUntag(RBX);
-  __ leaq(RSI, FieldAddress(RSI, RBX, TIMES_1, OneByteString::data_offset()));
+  __ leaq(RSI, FieldAddress(RSI, RBX, TIMES_1,
+                            target::OneByteString::data_offset()));
   // RSI: Start address to copy from (untagged).
   // RBX: Untagged start index.
   __ movq(RCX, Address(RSP, +kEndIndexOffset));
@@ -2058,7 +2099,8 @@
   __ jmp(&check, Assembler::kNearJump);
   __ Bind(&loop);
   __ movzxb(RBX, Address(RSI, RDX, TIMES_1, 0));
-  __ movb(FieldAddress(RAX, RDX, TIMES_1, OneByteString::data_offset()), RBX);
+  __ movb(FieldAddress(RAX, RDX, TIMES_1, target::OneByteString::data_offset()),
+          RBX);
   __ incq(RDX);
   __ Bind(&check);
   __ cmpq(RDX, RCX);
@@ -2067,20 +2109,21 @@
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteStringSetAt(Assembler* assembler,
-                                      Label* normal_ir_body) {
-  __ movq(RCX, Address(RSP, +1 * kWordSize));  // Value.
-  __ movq(RBX, Address(RSP, +2 * kWordSize));  // Index.
-  __ movq(RAX, Address(RSP, +3 * kWordSize));  // OneByteString.
+void AsmIntrinsifier::OneByteStringSetAt(Assembler* assembler,
+                                         Label* normal_ir_body) {
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Value.
+  __ movq(RBX, Address(RSP, +2 * target::kWordSize));  // Index.
+  __ movq(RAX, Address(RSP, +3 * target::kWordSize));  // target::OneByteString.
   __ SmiUntag(RBX);
   __ SmiUntag(RCX);
-  __ movb(FieldAddress(RAX, RBX, TIMES_1, OneByteString::data_offset()), RCX);
+  __ movb(FieldAddress(RAX, RBX, TIMES_1, target::OneByteString::data_offset()),
+          RCX);
   __ ret();
 }
 
-void Intrinsifier::OneByteString_allocate(Assembler* assembler,
-                                          Label* normal_ir_body) {
-  __ movq(RDI, Address(RSP, +1 * kWordSize));  // Length.v=
+void AsmIntrinsifier::OneByteString_allocate(Assembler* assembler,
+                                             Label* normal_ir_body) {
+  __ movq(RDI, Address(RSP, +1 * target::kWordSize));  // Length.v=
   Label ok;
   TryAllocateOnebyteString(assembler, &ok, normal_ir_body, RDI);
   // RDI: Start address to copy from (untagged).
@@ -2096,22 +2139,22 @@
                            Label* normal_ir_body,
                            intptr_t string_cid) {
   Label is_true, is_false, loop;
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // This.
-  __ movq(RCX, Address(RSP, +1 * kWordSize));  // Other.
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // This.
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Other.
 
   // Are identical?
   __ cmpq(RAX, RCX);
   __ j(EQUAL, &is_true, Assembler::kNearJump);
 
-  // Is other OneByteString?
+  // Is other target::OneByteString?
   __ testq(RCX, Immediate(kSmiTagMask));
   __ j(ZERO, &is_false);  // Smi
   __ CompareClassId(RCX, string_cid);
   __ j(NOT_EQUAL, normal_ir_body, Assembler::kNearJump);
 
   // Have same length?
-  __ movq(RDI, FieldAddress(RAX, String::length_offset()));
-  __ cmpq(RDI, FieldAddress(RCX, String::length_offset()));
+  __ movq(RDI, FieldAddress(RAX, target::String::length_offset()));
+  __ cmpq(RDI, FieldAddress(RCX, target::String::length_offset()));
   __ j(NOT_EQUAL, &is_false, Assembler::kNearJump);
 
   // Check contents, no fall-through possible.
@@ -2122,15 +2165,15 @@
   __ cmpq(RDI, Immediate(0));
   __ j(LESS, &is_true, Assembler::kNearJump);
   if (string_cid == kOneByteStringCid) {
-    __ movzxb(RBX,
-              FieldAddress(RAX, RDI, TIMES_1, OneByteString::data_offset()));
-    __ movzxb(RDX,
-              FieldAddress(RCX, RDI, TIMES_1, OneByteString::data_offset()));
+    __ movzxb(RBX, FieldAddress(RAX, RDI, TIMES_1,
+                                target::OneByteString::data_offset()));
+    __ movzxb(RDX, FieldAddress(RCX, RDI, TIMES_1,
+                                target::OneByteString::data_offset()));
   } else if (string_cid == kTwoByteStringCid) {
-    __ movzxw(RBX,
-              FieldAddress(RAX, RDI, TIMES_2, TwoByteString::data_offset()));
-    __ movzxw(RDX,
-              FieldAddress(RCX, RDI, TIMES_2, TwoByteString::data_offset()));
+    __ movzxw(RBX, FieldAddress(RAX, RDI, TIMES_2,
+                                target::TwoByteString::data_offset()));
+    __ movzxw(RDX, FieldAddress(RCX, RDI, TIMES_2,
+                                target::TwoByteString::data_offset()));
   } else {
     UNIMPLEMENTED();
   }
@@ -2139,33 +2182,33 @@
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&is_true);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 
   __ Bind(&is_false);
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
 
   __ Bind(normal_ir_body);
 }
 
-void Intrinsifier::OneByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::OneByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kOneByteStringCid);
 }
 
-void Intrinsifier::TwoByteString_equality(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::TwoByteString_equality(Assembler* assembler,
+                                             Label* normal_ir_body) {
   StringEquality(assembler, normal_ir_body, kTwoByteStringCid);
 }
 
-void Intrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
-                                                Label* normal_ir_body,
-                                                bool sticky) {
+void AsmIntrinsifier::IntrinsifyRegExpExecuteMatch(Assembler* assembler,
+                                                   Label* normal_ir_body,
+                                                   bool sticky) {
   if (FLAG_interpret_irregexp) return;
 
-  static const intptr_t kRegExpParamOffset = 3 * kWordSize;
-  static const intptr_t kStringParamOffset = 2 * kWordSize;
+  static const intptr_t kRegExpParamOffset = 3 * target::kWordSize;
+  static const intptr_t kStringParamOffset = 2 * target::kWordSize;
   // start_index smi is located at offset 1.
 
   // Incoming registers:
@@ -2179,91 +2222,92 @@
   __ movq(RDI, Address(RSP, kStringParamOffset));
   __ LoadClassId(RDI, RDI);
   __ SubImmediate(RDI, Immediate(kOneByteStringCid));
-  __ movq(RAX,
-          FieldAddress(RBX, RDI, TIMES_8,
-                       RegExp::function_offset(kOneByteStringCid, sticky)));
+  __ movq(RAX, FieldAddress(
+                   RBX, RDI, TIMES_8,
+                   target::RegExp::function_offset(kOneByteStringCid, sticky)));
 
   // Registers are now set up for the lazy compile stub. It expects the function
   // in RAX, the argument descriptor in R10, and IC-Data in RCX.
   __ xorq(RCX, RCX);
 
   // Tail-call the function.
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RDI, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RDI, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RDI);
 }
 
 // On stack: user tag (+1), return-address (+0).
-void Intrinsifier::UserTag_makeCurrent(Assembler* assembler,
-                                       Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_makeCurrent(Assembler* assembler,
+                                          Label* normal_ir_body) {
   // RBX: Isolate.
   __ LoadIsolate(RBX);
   // RAX: Current user tag.
-  __ movq(RAX, Address(RBX, Isolate::current_tag_offset()));
+  __ movq(RAX, Address(RBX, target::Isolate::current_tag_offset()));
   // R10: UserTag.
-  __ movq(R10, Address(RSP, +1 * kWordSize));
+  __ movq(R10, Address(RSP, +1 * target::kWordSize));
   // Set Isolate::current_tag_.
-  __ movq(Address(RBX, Isolate::current_tag_offset()), R10);
+  __ movq(Address(RBX, target::Isolate::current_tag_offset()), R10);
   // R10: UserTag's tag.
-  __ movq(R10, FieldAddress(R10, UserTag::tag_offset()));
+  __ movq(R10, FieldAddress(R10, target::UserTag::tag_offset()));
   // Set Isolate::user_tag_.
-  __ movq(Address(RBX, Isolate::user_tag_offset()), R10);
+  __ movq(Address(RBX, target::Isolate::user_tag_offset()), R10);
   __ ret();
 }
 
-void Intrinsifier::UserTag_defaultTag(Assembler* assembler,
-                                      Label* normal_ir_body) {
+void AsmIntrinsifier::UserTag_defaultTag(Assembler* assembler,
+                                         Label* normal_ir_body) {
   __ LoadIsolate(RAX);
-  __ movq(RAX, Address(RAX, Isolate::default_tag_offset()));
+  __ movq(RAX, Address(RAX, target::Isolate::default_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Profiler_getCurrentTag(Assembler* assembler,
-                                          Label* normal_ir_body) {
+void AsmIntrinsifier::Profiler_getCurrentTag(Assembler* assembler,
+                                             Label* normal_ir_body) {
   __ LoadIsolate(RAX);
-  __ movq(RAX, Address(RAX, Isolate::current_tag_offset()));
+  __ movq(RAX, Address(RAX, target::Isolate::current_tag_offset()));
   __ ret();
 }
 
-void Intrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
-                                                Label* normal_ir_body) {
+void AsmIntrinsifier::Timeline_isDartStreamEnabled(Assembler* assembler,
+                                                   Label* normal_ir_body) {
 #if !defined(SUPPORT_TIMELINE)
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
 #else
   Label true_label;
   // Load TimelineStream*.
-  __ movq(RAX, Address(THR, Thread::dart_stream_offset()));
+  __ movq(RAX, Address(THR, target::Thread::dart_stream_offset()));
   // Load uintptr_t from TimelineStream*.
-  __ movq(RAX, Address(RAX, TimelineStream::enabled_offset()));
+  __ movq(RAX, Address(RAX, target::TimelineStream::enabled_offset()));
   __ cmpq(RAX, Immediate(0));
   __ j(NOT_ZERO, &true_label, Assembler::kNearJump);
   // Not enabled.
-  __ LoadObject(RAX, Bool::False());
+  __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
   __ ret();
   // Enabled.
   __ Bind(&true_label);
-  __ LoadObject(RAX, Bool::True());
+  __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
   __ ret();
 #endif
 }
 
-void Intrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
-                                              Label* normal_ir_body) {
-  __ LoadObject(RAX, Object::null_object());
-  __ movq(Address(THR, Thread::async_stack_trace_offset()), RAX);
+void AsmIntrinsifier::ClearAsyncThreadStackTrace(Assembler* assembler,
+                                                 Label* normal_ir_body) {
+  __ LoadObject(RAX, NullObject());
+  __ movq(Address(THR, target::Thread::async_stack_trace_offset()), RAX);
   __ ret();
 }
 
-void Intrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
-                                            Label* normal_ir_body) {
-  __ movq(Address(THR, Thread::async_stack_trace_offset()), RAX);
-  __ LoadObject(RAX, Object::null_object());
+void AsmIntrinsifier::SetAsyncThreadStackTrace(Assembler* assembler,
+                                               Label* normal_ir_body) {
+  __ movq(Address(THR, target::Thread::async_stack_trace_offset()), RAX);
+  __ LoadObject(RAX, NullObject());
   __ ret();
 }
 
 #undef __
 
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/assembler/assembler_arm.h b/runtime/vm/compiler/assembler/assembler_arm.h
index 3f8820e..6b79492 100644
--- a/runtime/vm/compiler/assembler/assembler_arm.h
+++ b/runtime/vm/compiler/assembler/assembler_arm.h
@@ -763,6 +763,10 @@
                        ObjectPoolBuilderEntry::Patchability patchable,
                        Condition cond = AL);
   void PushObject(const Object& object);
+  void PushImmediate(int32_t immediate) {
+    LoadImmediate(TMP, immediate);
+    Push(TMP);
+  }
   void CompareObject(Register rn, const Object& object);
 
   enum CanBeSmi {
diff --git a/runtime/vm/compiler/assembler/assembler_arm64.h b/runtime/vm/compiler/assembler/assembler_arm64.h
index ed2c5a5..da5466b 100644
--- a/runtime/vm/compiler/assembler/assembler_arm64.h
+++ b/runtime/vm/compiler/assembler/assembler_arm64.h
@@ -1506,6 +1506,10 @@
     LoadObject(TMP, object);
     Push(TMP);
   }
+  void PushImmediate(int64_t immediate) {
+    LoadImmediate(TMP, immediate);
+    Push(TMP);
+  }
   void CompareObject(Register reg, const Object& object);
 
   void LoadClassId(Register result, Register object);
diff --git a/runtime/vm/compiler/assembler/assembler_x64.h b/runtime/vm/compiler/assembler/assembler_x64.h
index c69bef3..db70602 100644
--- a/runtime/vm/compiler/assembler/assembler_x64.h
+++ b/runtime/vm/compiler/assembler/assembler_x64.h
@@ -474,6 +474,10 @@
   // for proper unwinding of Dart frames (use --generate_gdb_symbols and -O0).
   void movq(Register dst, Register src) { EmitQ(src, dst, 0x89); }
 
+  void movq(XmmRegister dst, Register src) {
+    EmitQ(dst, src, 0x6E, 0x0F, 0x66);
+  }
+
   void movd(XmmRegister dst, Register src) {
     EmitL(dst, src, 0x6E, 0x0F, 0x66);
   }
diff --git a/runtime/vm/compiler/backend/constant_propagator.cc b/runtime/vm/compiler/backend/constant_propagator.cc
index cacf488..56f2a36 100644
--- a/runtime/vm/compiler/backend/constant_propagator.cc
+++ b/runtime/vm/compiler/backend/constant_propagator.cc
@@ -410,6 +410,23 @@
 }
 
 void ConstantPropagator::VisitStaticCall(StaticCallInstr* instr) {
+  const Function& function = instr->function();
+  switch (MethodRecognizer::RecognizeKind(function)) {
+    case MethodRecognizer::kOneByteString_equality:
+    case MethodRecognizer::kTwoByteString_equality: {
+      ASSERT(instr->FirstArgIndex() == 0);
+      // Use pure identity as a fast equality test.
+      if (instr->ArgumentAt(0)->OriginalDefinition() ==
+          instr->ArgumentAt(1)->OriginalDefinition()) {
+        SetValue(instr, Bool::True());
+        return;
+      }
+      break;
+    }
+    default:
+      // TODO(ajcbik): consider more cases
+      break;
+  }
   SetValue(instr, non_constant_);
 }
 
@@ -1358,6 +1375,14 @@
   }
 }
 
+static void RemovePushArguments(StaticCallInstr* call) {
+  for (intptr_t i = 0; i < call->ArgumentCount(); ++i) {
+    PushArgumentInstr* push = call->PushArgumentAt(i);
+    push->ReplaceUsesWith(push->value()->definition());
+    push->RemoveFromGraph();
+  }
+}
+
 void ConstantPropagator::Transform() {
   // We will recompute dominators, block ordering, block ids, block last
   // instructions, previous pointers, predecessors, etc. after eliminating
@@ -1448,6 +1473,9 @@
           value = Instance::Cast(value).CheckAndCanonicalize(T, &error_str);
           ASSERT(!value.IsNull() && (error_str == nullptr));
         }
+        if (auto call = defn->AsStaticCall()) {
+          RemovePushArguments(call);
+        }
         ConstantInstr* constant = graph_->GetConstant(value);
         defn->ReplaceUsesWith(constant);
         i.RemoveCurrentFromGraph();
diff --git a/runtime/vm/compiler/backend/flow_graph.h b/runtime/vm/compiler/backend/flow_graph.h
index 854aa81..0012962 100644
--- a/runtime/vm/compiler/backend/flow_graph.h
+++ b/runtime/vm/compiler/backend/flow_graph.h
@@ -17,6 +17,10 @@
 class LoopHierarchy;
 class VariableLivenessAnalysis;
 
+namespace compiler {
+class GraphIntrinsifier;
+}
+
 class BlockIterator : public ValueObject {
  public:
   explicit BlockIterator(const GrowableArray<BlockEntryInstr*>& block_order)
@@ -410,11 +414,12 @@
 
  private:
   friend class FlowGraphCompiler;  // TODO(ajcbik): restructure
+  friend class FlowGraphChecker;
   friend class IfConverter;
   friend class BranchSimplifier;
   friend class ConstantPropagator;
   friend class DeadCodeElimination;
-  friend class Intrinsifier;
+  friend class compiler::GraphIntrinsifier;
 
   // SSA transformation methods and fields.
   void ComputeDominators(GrowableArray<BitVector*>* dominance_frontier);
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.cc b/runtime/vm/compiler/backend/flow_graph_checker.cc
index 2e05844..a07ed6d 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.cc
+++ b/runtime/vm/compiler/backend/flow_graph_checker.cc
@@ -9,14 +9,13 @@
 
 #include "vm/compiler/backend/flow_graph.h"
 #include "vm/compiler/backend/il.h"
+#include "vm/compiler/backend/loops.h"
 
 namespace dart {
 
-FlowGraphChecker::FlowGraphChecker(FlowGraph* flow_graph)
-    : flow_graph_(flow_graph) {}
-
+// Returns true if block is a predecessor of succ.
 static bool IsPred(BlockEntryInstr* block, BlockEntryInstr* succ) {
-  for (intptr_t i = 0; i < succ->PredecessorCount(); ++i) {
+  for (intptr_t i = 0, n = succ->PredecessorCount(); i < n; ++i) {
     if (succ->PredecessorAt(i) == block) {
       return true;
     }
@@ -24,9 +23,10 @@
   return false;
 }
 
+// Returns true if block is a successor of pred.
 static bool IsSucc(BlockEntryInstr* block, BlockEntryInstr* pred) {
   Instruction* last = pred->last_instruction();
-  for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
+  for (intptr_t i = 0, n = last->SuccessorCount(); i < n; ++i) {
     if (last->SuccessorAt(i) == block) {
       return true;
     }
@@ -34,8 +34,9 @@
   return false;
 }
 
-static bool IsDominated(BlockEntryInstr* block, BlockEntryInstr* dom) {
-  for (intptr_t i = 0; i < dom->dominated_blocks().length(); ++i) {
+// Returns true if dom directly dominates block.
+static bool IsDirectlyDominated(BlockEntryInstr* block, BlockEntryInstr* dom) {
+  for (intptr_t i = 0, n = dom->dominated_blocks().length(); i < n; ++i) {
     if (dom->dominated_blocks()[i] == block) {
       return true;
     }
@@ -43,7 +44,15 @@
   return false;
 }
 
-void FlowGraphChecker::CheckBasicBlocks() {
+// Returns true if instruction forces control flow.
+static bool IsControlFlow(Instruction* instruction) {
+  return instruction->IsBranch() || instruction->IsGoto() ||
+         instruction->IsIndirectGoto() || instruction->IsReturn() ||
+         instruction->IsThrow() || instruction->IsReThrow() ||
+         instruction->IsStop() || instruction->IsTailCall();
+}
+
+void FlowGraphChecker::VisitBlocks() {
   const GrowableArray<BlockEntryInstr*>& preorder = flow_graph_->preorder();
   const GrowableArray<BlockEntryInstr*>& postorder = flow_graph_->postorder();
   const GrowableArray<BlockEntryInstr*>& rev_postorder =
@@ -61,9 +70,9 @@
 
   // Iterate over all basic blocks.
   const intptr_t max_block_id = flow_graph_->max_block_id();
-  for (BlockIterator block_it = flow_graph_->reverse_postorder_iterator();
-       !block_it.Done(); block_it.Advance()) {
-    BlockEntryInstr* block = block_it.Current();
+  for (BlockIterator it = flow_graph_->reverse_postorder_iterator(); !it.Done();
+       it.Advance()) {
+    BlockEntryInstr* block = it.Current();
     ASSERT(block->block_id() <= max_block_id);
     // Make sure ordering is consistent.
     ASSERT(block->preorder_number() <= block_count);
@@ -72,41 +81,127 @@
     ASSERT(postorder[block->postorder_number()] == block);
     // Make sure predecessors and successors agree.
     Instruction* last = block->last_instruction();
-    for (intptr_t i = 0; i < last->SuccessorCount(); ++i) {
+    for (intptr_t i = 0, n = last->SuccessorCount(); i < n; ++i) {
       ASSERT(IsPred(block, last->SuccessorAt(i)));
     }
-    for (intptr_t i = 0; i < block->PredecessorCount(); ++i) {
+    for (intptr_t i = 0, n = block->PredecessorCount(); i < n; ++i) {
       ASSERT(IsSucc(block, block->PredecessorAt(i)));
     }
     // Make sure dominance relations agree.
-    const intptr_t num_dom = block->dominated_blocks().length();
-    for (intptr_t i = 0; i < num_dom; ++i) {
+    for (intptr_t i = 0, n = block->dominated_blocks().length(); i < n; ++i) {
       ASSERT(block->dominated_blocks()[i]->dominator() == block);
     }
     if (block->dominator() != nullptr) {
-      ASSERT(IsDominated(block, block->dominator()));
+      ASSERT(IsDirectlyDominated(block, block->dominator()));
     }
     // Visit all instructions in this block.
-    CheckInstructions(block);
+    VisitInstructions(block);
   }
+
+  // Flow graph built-in verification.
+  // TODO(ajcbik): migrate actual code into checker too?
+  ASSERT(flow_graph_->VerifyUseLists());
 }
 
-void FlowGraphChecker::CheckInstructions(BlockEntryInstr* block) {
+void FlowGraphChecker::VisitInstructions(BlockEntryInstr* block) {
+  // To avoid excessive runtimes, skip the instructions check if there
+  // are many definitions (as happens in e.g. an initialization block).
+  if (flow_graph_->current_ssa_temp_index() > 10000) {
+    return;
+  }
+  // Give all visitors quick access.
+  current_block_ = block;
+  // Visit phis in join.
+  if (auto join_entry = block->AsJoinEntry()) {
+    for (PhiIterator it(join_entry); !it.Done(); it.Advance()) {
+      VisitInstruction(it.Current());
+    }
+  }
+  // Visit regular instructions.
+  Instruction* last = block->last_instruction();
   Instruction* prev = block;
-  for (ForwardInstructionIterator instr_it(block); !instr_it.Done();
-       instr_it.Advance()) {
-    Instruction* instruction = instr_it.Current();
+  ASSERT(prev->previous() == nullptr);
+  for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+    Instruction* instruction = it.Current();
+    // Make sure block lookup agrees (scan in scan).
+    ASSERT(instruction->GetBlock() == block);
     // Make sure linked list agrees.
     ASSERT(prev->next() == instruction);
     ASSERT(instruction->previous() == prev);
     prev = instruction;
+    // Make sure control flow makes sense.
+    ASSERT(IsControlFlow(instruction) == (instruction == last));
+    // Perform instruction specific checks.
+    VisitInstruction(instruction);
   }
+  ASSERT(prev == last);
+  // Make sure loop information, when up-to-date, agrees.
+  if (flow_graph_->loop_hierarchy_ != nullptr) {
+    for (LoopInfo* loop = block->loop_info(); loop != nullptr;
+         loop = loop->outer()) {
+      ASSERT(loop->Contains(block));
+    }
+  }
+}
+
+void FlowGraphChecker::VisitInstruction(Instruction* instruction) {
+  if (auto def = instruction->AsDefinition()) {
+    VisitDefinition(def);
+  }
+  instruction->Accept(this);
+}
+
+void FlowGraphChecker::VisitDefinition(Definition* def) {
+  // Make sure each outgoing use is dominated by this def, or is a
+  // Phi instruction (note that the proper dominance relation on
+  // the input values of Phis are checked by the Phi visitor below).
+  for (Value* use = def->input_use_list(); use != nullptr;
+       use = use->next_use()) {
+    Instruction* use_instr = use->instruction();
+    ASSERT(use_instr != nullptr);
+    ASSERT(use_instr->IsPhi() ||
+           use_instr->IsMaterializeObject() ||  // not in graph
+           use_instr->IsDominatedBy(def));
+  }
+}
+
+void FlowGraphChecker::VisitConstant(ConstantInstr* constant) {
+  // TODO(ajcbik): Is this a property we eventually want (all constants
+  // generated by utility that queries pool and put in the graph entry
+  // when seen first)? The inliner still creates some direct constants.
+  // ASSERT(constant->GetBlock() == flow_graph_->graph_entry());
+}
+
+void FlowGraphChecker::VisitPhi(PhiInstr* phi) {
+  ASSERT(phi->next() == nullptr);
+  ASSERT(phi->previous() == nullptr);
+  // Make sure each incoming input value of a Phi is dominated
+  // on the corresponding incoming edge, as defined by order.
+  ASSERT(phi->InputCount() == current_block_->PredecessorCount());
+  for (intptr_t i = 0, n = phi->InputCount(); i < n; ++i) {
+    Definition* input_def = phi->InputAt(i)->definition();
+    BlockEntryInstr* edge = current_block_->PredecessorAt(i);
+    ASSERT(input_def->IsConstant() ||  // some constants are in initial defs
+           edge->last_instruction()->IsDominatedBy(input_def));
+  }
+}
+
+void FlowGraphChecker::VisitGoto(GotoInstr* jmp) {
+  ASSERT(jmp->SuccessorCount() == 1);
+}
+
+void FlowGraphChecker::VisitIndirectGoto(IndirectGotoInstr* jmp) {
+  ASSERT(jmp->SuccessorCount() >= 1);
+}
+
+void FlowGraphChecker::VisitBranch(BranchInstr* branch) {
+  ASSERT(branch->SuccessorCount() == 2);
 }
 
 // Main entry point of graph checker.
 void FlowGraphChecker::Check() {
   ASSERT(flow_graph_ != nullptr);
-  CheckBasicBlocks();
+  VisitBlocks();
 }
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/flow_graph_checker.h b/runtime/vm/compiler/backend/flow_graph_checker.h
index c7ec997..fba159f 100644
--- a/runtime/vm/compiler/backend/flow_graph_checker.h
+++ b/runtime/vm/compiler/backend/flow_graph_checker.h
@@ -8,11 +8,10 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 #if defined(DEBUG)
 
-namespace dart {
+#include "vm/compiler/backend/flow_graph.h"
+#include "vm/compiler/backend/il.h"
 
-// Forward.
-class FlowGraph;
-class BlockEntryInstr;
+namespace dart {
 
 // Class responsible for performing sanity checks on the flow graph.
 // The intended use is running the checks after each compiler pass
@@ -25,18 +24,35 @@
 // the passes or, worse, unwritten assumptions once agreed upon but
 // so easily forgotten. Since the graph checker runs only in debug
 // mode, it is acceptable to perform slightly elaborate tests.
-class FlowGraphChecker {
+class FlowGraphChecker : public FlowGraphVisitor {
  public:
-  explicit FlowGraphChecker(FlowGraph* flow_graph);
+  // Constructs graph checker. The checker uses some custom-made
+  // visitation to perform additional checks, and uses the
+  // FlowGraphVisitor structure for anything else.
+  explicit FlowGraphChecker(FlowGraph* flow_graph)
+      : FlowGraphVisitor(flow_graph->preorder()),
+        flow_graph_(flow_graph),
+        current_block_(nullptr) {}
 
   // Performs a sanity check on the flow graph.
   void Check();
 
  private:
-  void CheckBasicBlocks();
-  void CheckInstructions(BlockEntryInstr* block);
+  // Custom-made visitors.
+  void VisitBlocks() override;
+  void VisitInstructions(BlockEntryInstr* block);
+  void VisitInstruction(Instruction* instruction);
+  void VisitDefinition(Definition* def);
+
+  // Instruction visitors.
+  void VisitConstant(ConstantInstr* constant) override;
+  void VisitPhi(PhiInstr* phi) override;
+  void VisitGoto(GotoInstr* jmp) override;
+  void VisitIndirectGoto(IndirectGotoInstr* jmp) override;
+  void VisitBranch(BranchInstr* branch) override;
 
   FlowGraph* const flow_graph_;
+  BlockEntryInstr* current_block_;
 };
 
 }  // namespace dart
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.cc b/runtime/vm/compiler/backend/flow_graph_compiler.cc
index 66bedcf..cd503e0 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.cc
@@ -756,6 +756,16 @@
   return info;
 }
 
+CompilerDeoptInfo* FlowGraphCompiler::AddSlowPathDeoptInfo(intptr_t deopt_id,
+                                                           Environment* env) {
+  ASSERT(deopt_id != DeoptId::kNone);
+  CompilerDeoptInfo* info =
+      new (zone()) CompilerDeoptInfo(deopt_id, ICData::kDeoptUnknown, 0, env);
+  info->set_pc_offset(assembler()->CodeSize());
+  deopt_infos_.Add(info);
+  return info;
+}
+
 // This function must be in sync with FlowGraphCompiler::SaveLiveRegisters
 // and FlowGraphCompiler::SlowPathEnvironmentFor.
 // See StackFrame::VisitObjectPointers for the details of how stack map is
@@ -1053,7 +1063,7 @@
 
 void FlowGraphCompiler::FinalizeVarDescriptors(const Code& code) {
 #if defined(PRODUCT)
-  // No debugger: no var descriptors.
+// No debugger: no var descriptors.
 #else
   // TODO(alexmarkov): revise local vars descriptors when compiling bytecode
   if (code.is_optimized() || flow_graph().function().HasBytecode()) {
@@ -1210,7 +1220,7 @@
   EnterIntrinsicMode();
 
   SpecialStatsBegin(CombinedCodeStatistics::kTagIntrinsics);
-  bool complete = Intrinsifier::Intrinsify(parsed_function(), this);
+  bool complete = compiler::Intrinsifier::Intrinsify(parsed_function(), this);
   SpecialStatsEnd(CombinedCodeStatistics::kTagIntrinsics);
 
   ExitIntrinsicMode();
@@ -1418,8 +1428,7 @@
 
 void FlowGraphCompiler::AllocateRegistersLocally(Instruction* instr) {
   ASSERT(!is_optimizing());
-  instr->InitializeLocationSummary(zone(),
-                                   false);  // Not optimizing.
+  instr->InitializeLocationSummary(zone(), false);  // Not optimizing.
 
 // No need to allocate registers based on LocationSummary on DBC as in
 // unoptimized mode it's a stack based bytecode just like IR itself.
@@ -2302,7 +2311,11 @@
       (compiler->CurrentTryIndex() != kInvalidTryIndex)) {
     Environment* env =
         compiler->SlowPathEnvironmentFor(instruction(), num_args_);
-    compiler->RecordCatchEntryMoves(env, try_index_);
+    if (FLAG_precompiled_mode) {
+      compiler->RecordCatchEntryMoves(env, try_index_);
+    } else if (env != nullptr) {
+      compiler->AddSlowPathDeoptInfo(deopt_id, env);
+    }
   }
   if (!use_shared_stub) {
     __ Breakpoint();
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler.h b/runtime/vm/compiler/backend/flow_graph_compiler.h
index f3ee90a..8cfee57 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler.h
+++ b/runtime/vm/compiler/backend/flow_graph_compiler.h
@@ -693,6 +693,7 @@
 #endif  // defined(TARGET_ARCH_DBC)
 
   CompilerDeoptInfo* AddDeoptIndexAtCall(intptr_t deopt_id);
+  CompilerDeoptInfo* AddSlowPathDeoptInfo(intptr_t deopt_id, Environment* env);
 
   void AddSlowPathCode(SlowPathCode* slow_path);
 
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
index 6064ec7..70f614f 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm.cc
@@ -372,8 +372,6 @@
   }
   const Register kClassIdReg = R2;
   __ LoadClassId(kClassIdReg, kInstanceReg);
-  // See ClassFinalizer::CheckSuperTypeAndInterfaces for list of restricted
-  // interfaces.
   // Bool interface can be implemented only by core class Bool.
   if (type.IsBoolType()) {
     __ CompareImmediate(kClassIdReg, kBoolCid);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
index 08be0de..b128224 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_arm64.cc
@@ -358,8 +358,6 @@
   }
   const Register kClassIdReg = R2;
   __ LoadClassId(kClassIdReg, kInstanceReg);
-  // See ClassFinalizer::CheckSuperTypeAndInterfaces for list of restricted
-  // interfaces.
   // Bool interface can be implemented only by core class Bool.
   if (type.IsBoolType()) {
     __ CompareImmediate(kClassIdReg, kBoolCid);
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
index ba4960e..b1c4671 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_ia32.cc
@@ -350,8 +350,6 @@
   }
   const Register kClassIdReg = ECX;
   __ LoadClassId(kClassIdReg, kInstanceReg);
-  // See ClassFinalizer::CheckSuperTypeAndInterfaces for list of restricted
-  // interfaces.
   // Bool interface can be implemented only by core class Bool.
   if (type.IsBoolType()) {
     __ cmpl(kClassIdReg, Immediate(kBoolCid));
diff --git a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
index 1c07f8a..0f087fa 100644
--- a/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
+++ b/runtime/vm/compiler/backend/flow_graph_compiler_x64.cc
@@ -373,8 +373,6 @@
   }
   const Register kClassIdReg = R10;
   __ LoadClassId(kClassIdReg, kInstanceReg);
-  // See ClassFinalizer::CheckSuperTypeAndInterfaces for list of restricted
-  // interfaces.
   // Bool interface can be implemented only by core class Bool.
   if (type.IsBoolType()) {
     __ cmpl(kClassIdReg, Immediate(kBoolCid));
diff --git a/runtime/vm/compiler/backend/il.cc b/runtime/vm/compiler/backend/il.cc
index 029a337..c8b82ed 100644
--- a/runtime/vm/compiler/backend/il.cc
+++ b/runtime/vm/compiler/backend/il.cc
@@ -1074,10 +1074,12 @@
 BlockEntryInstr* Instruction::GetBlock() {
   // TODO(fschneider): Implement a faster way to get the block of an
   // instruction.
-  ASSERT(previous() != NULL);
   Instruction* result = previous();
-  while (!result->IsBlockEntry())
+  ASSERT(result != nullptr);
+  while (!result->IsBlockEntry()) {
     result = result->previous();
+    ASSERT(result != nullptr);
+  }
   return result->AsBlockEntry();
 }
 
@@ -2883,7 +2885,7 @@
     return box_defn->value()->definition();
   }
 
-  if ((representation() == kUnboxedDouble) && value()->BindsToConstant()) {
+  if (representation() == kUnboxedDouble && value()->BindsToConstant()) {
     UnboxedConstantInstr* uc = NULL;
 
     const Object& val = value()->BoundConstant();
@@ -3448,6 +3450,7 @@
     case kUnboxedFloat32x4:
     case kUnboxedFloat64x2:
     case kUnboxedInt32x4:
+      ASSERT(FlowGraphCompiler::SupportsUnboxedDoubles());
       return new UnboxInstr(to, value, deopt_id, speculative_mode);
 
     default:
diff --git a/runtime/vm/compiler/backend/il.h b/runtime/vm/compiler/backend/il.h
index 2a632c2..6241f4b 100644
--- a/runtime/vm/compiler/backend/il.h
+++ b/runtime/vm/compiler/backend/il.h
@@ -17,6 +17,7 @@
 #include "vm/native_entry.h"
 #include "vm/object.h"
 #include "vm/parser.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/token_position.h"
 
 namespace dart {
@@ -44,6 +45,10 @@
 class UnboxIntegerInstr;
 class TypeUsageInfo;
 
+namespace compiler {
+class BlockBuilder;
+}
+
 class Value : public ZoneAllocated {
  public:
   // A forward iterator that allows removing the current value from the
@@ -7833,7 +7838,7 @@
 
  private:
   friend class ShallowIterator;
-  friend class BlockBuilder;  // For Environment constructor.
+  friend class compiler::BlockBuilder;  // For Environment constructor.
 
   Environment(intptr_t length,
               intptr_t fixed_parameter_count,
diff --git a/runtime/vm/compiler/backend/inliner.cc b/runtime/vm/compiler/backend/inliner.cc
index 18f8e22..159a903 100644
--- a/runtime/vm/compiler/backend/inliner.cc
+++ b/runtime/vm/compiler/backend/inliner.cc
@@ -1482,8 +1482,12 @@
           call->FirstArgIndex(), &arguments, call_info[call_idx].caller(),
           call_info[call_idx].caller_graph->inlining_id());
 
-      // Calls outside loops are subject to stricter heuristics under AOT.
+      // Under AOT, calls outside loops may pass our regular heuristics due
+      // to a relatively high ratio. So, unless we are optimizing solely for
+      // speed, such call sites are subject to subsequent stricter heuristic
+      // to limit code size increase.
       bool stricter_heuristic = FLAG_precompiled_mode &&
+                                FLAG_optimization_level <= 2 &&
                                 !inliner_->AlwaysInline(target) &&
                                 call_info[call_idx].nesting_depth == 0;
       if (TryInlining(call->function(), call->argument_names(), &call_data,
diff --git a/runtime/vm/compiler/backend/locations.cc b/runtime/vm/compiler/backend/locations.cc
index a06b4b8..e549879 100644
--- a/runtime/vm/compiler/backend/locations.cc
+++ b/runtime/vm/compiler/backend/locations.cc
@@ -23,6 +23,23 @@
   return count;
 }
 
+void RegisterSet::DebugPrint() {
+  for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
+    Register r = static_cast<Register>(i);
+    if (ContainsRegister(r)) {
+      THR_Print("%s %s\n", Assembler::RegisterName(r),
+                IsTagged(r) ? "tagged" : "untagged");
+    }
+  }
+
+  for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
+    FpuRegister r = static_cast<FpuRegister>(i);
+    if (ContainsFpuRegister(r)) {
+      THR_Print("%s\n", Assembler::FpuRegisterName(r));
+    }
+  }
+}
+
 LocationSummary::LocationSummary(Zone* zone,
                                  intptr_t input_count,
                                  intptr_t temp_count,
diff --git a/runtime/vm/compiler/backend/locations.h b/runtime/vm/compiler/backend/locations.h
index 8be7779..9c76dd6 100644
--- a/runtime/vm/compiler/backend/locations.h
+++ b/runtime/vm/compiler/backend/locations.h
@@ -9,7 +9,6 @@
 #include "vm/bitfield.h"
 #include "vm/bitmap.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/log.h"
 
 namespace dart {
 
@@ -561,22 +560,7 @@
     }
   }
 
-  void DebugPrint() {
-    for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
-      Register r = static_cast<Register>(i);
-      if (ContainsRegister(r)) {
-        THR_Print("%s %s\n", Assembler::RegisterName(r),
-                  IsTagged(r) ? "tagged" : "untagged");
-      }
-    }
-
-    for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) {
-      FpuRegister r = static_cast<FpuRegister>(i);
-      if (ContainsFpuRegister(r)) {
-        THR_Print("%s\n", Assembler::FpuRegisterName(r));
-      }
-    }
-  }
+  void DebugPrint();
 
   void MarkUntagged(Location loc) {
     ASSERT(loc.IsRegister());
diff --git a/runtime/vm/compiler/compiler_pass.cc b/runtime/vm/compiler/compiler_pass.cc
index 17bb17c..4befad9 100644
--- a/runtime/vm/compiler/compiler_pass.cc
+++ b/runtime/vm/compiler/compiler_pass.cc
@@ -176,7 +176,6 @@
     {
       TIMELINE_DURATION(thread, CompilerVerbose, name());
       repeat = DoBody(state);
-      DEBUG_ASSERT(state->flow_graph->VerifyUseLists());
       thread->CheckForSafepoint();
 #if defined(DEBUG)
       FlowGraphChecker(state->flow_graph).Check();
diff --git a/runtime/vm/compiler/compiler_sources.gni b/runtime/vm/compiler/compiler_sources.gni
index afb3abb..24c985a 100644
--- a/runtime/vm/compiler/compiler_sources.gni
+++ b/runtime/vm/compiler/compiler_sources.gni
@@ -9,6 +9,13 @@
   "aot/aot_call_specializer.h",
   "aot/precompiler.cc",
   "aot/precompiler.h",
+  "asm_intrinsifier.cc",
+  "asm_intrinsifier.h",
+  "asm_intrinsifier_arm.cc",
+  "asm_intrinsifier_arm64.cc",
+  "asm_intrinsifier_dbc.cc",
+  "asm_intrinsifier_ia32.cc",
+  "asm_intrinsifier_x64.cc",
   "assembler/assembler.cc",
   "assembler/assembler.h",
   "assembler/assembler_arm.cc",
@@ -36,9 +43,9 @@
   "backend/branch_optimizer.h",
   "backend/code_statistics.cc",
   "backend/code_statistics.h",
+  "backend/compile_type.h",
   "backend/constant_propagator.cc",
   "backend/constant_propagator.h",
-  "backend/compile_type.h",
   "backend/flow_graph.cc",
   "backend/flow_graph.h",
   "backend/flow_graph_checker.cc",
@@ -107,23 +114,31 @@
   "frontend/prologue_builder.h",
   "frontend/scope_builder.cc",
   "frontend/scope_builder.h",
+  "graph_intrinsifier.cc",
+  "graph_intrinsifier.h",
+  "graph_intrinsifier_arm.cc",
+  "graph_intrinsifier_arm64.cc",
+  "graph_intrinsifier_ia32.cc",
+  "graph_intrinsifier_x64.cc",
   "intrinsifier.cc",
   "intrinsifier.h",
-  "intrinsifier_arm.cc",
-  "intrinsifier_arm64.cc",
-  "intrinsifier_dbc.cc",
-  "intrinsifier_ia32.cc",
-  "intrinsifier_x64.cc",
   "jit/compiler.cc",
   "jit/compiler.h",
   "jit/jit_call_specializer.cc",
   "jit/jit_call_specializer.h",
   "method_recognizer.cc",
   "method_recognizer.h",
+  "recognized_methods_list.h",
   "relocation.cc",
   "relocation.h",
   "runtime_api.cc",
   "runtime_api.h",
+  "stub_code_compiler.h",
+  "stub_code_compiler_arm.cc",
+  "stub_code_compiler_arm64.cc",
+  "stub_code_compiler_dbc.cc",
+  "stub_code_compiler_ia32.cc",
+  "stub_code_compiler_x64.cc",
 ]
 
 compiler_sources_tests = [
diff --git a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
index 8628e82..3853076 100644
--- a/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/bytecode_flow_graph_builder.cc
@@ -701,6 +701,33 @@
   B->Push(call);
 }
 
+void BytecodeFlowGraphBuilder::BuildDirectCall() {
+  if (is_generating_interpreter()) {
+    UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
+  }
+
+  const Function& target = Function::Cast(ConstantAt(DecodeOperandD()).value());
+  const Array& arg_desc_array =
+      Array::Cast(ConstantAt(DecodeOperandD(), 1).value());
+  const ArgumentsDescriptor arg_desc(arg_desc_array);
+  intptr_t argc = DecodeOperandA().value();
+
+  ArgumentArray arguments = GetArguments(argc);
+
+  // TODO(alexmarkov): pass ICData::kSuper for super calls
+  // (need to distinguish them in bytecode).
+  StaticCallInstr* call = new (Z) StaticCallInstr(
+      position_, target, arg_desc.TypeArgsLen(),
+      Array::ZoneHandle(Z, arg_desc.GetArgumentNames()), arguments,
+      *ic_data_array_, B->GetNextDeoptId(), ICData::kStatic);
+
+  // TODO(alexmarkov): add type info
+  // SetResultTypeForStaticCall(call, target, argument_count, result_type);
+
+  code_ <<= call;
+  B->Push(call);
+}
+
 void BytecodeFlowGraphBuilder::BuildInterfaceCall() {
   if (is_generating_interpreter()) {
     UNIMPLEMENTED();  // TODO(alexmarkov): interpreter
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.cc b/runtime/vm/compiler/frontend/bytecode_reader.cc
index 6dff9ce..3c7e344 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.cc
+++ b/runtime/vm/compiler/frontend/bytecode_reader.cc
@@ -17,9 +17,8 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
-#define Z (helper_->zone_)
+#define Z (zone_)
 #define H (translation_helper_)
-#define T (type_translator_)
 #define I Isolate::Current()
 
 namespace dart {
@@ -29,14 +28,9 @@
 namespace kernel {
 
 BytecodeMetadataHelper::BytecodeMetadataHelper(KernelReaderHelper* helper,
-                                               TypeTranslator* type_translator,
                                                ActiveClass* active_class)
     : MetadataHelper(helper, tag(), /* precompiler_only = */ false),
-      type_translator_(*type_translator),
-      active_class_(active_class),
-      bytecode_component_(nullptr),
-      closures_(nullptr),
-      function_type_type_parameters_(nullptr) {}
+      active_class_(active_class) {}
 
 bool BytecodeMetadataHelper::HasBytecode(intptr_t node_offset) {
   const intptr_t md_offset = GetNextMetadataPayloadOffset(node_offset);
@@ -64,13 +58,44 @@
   ASSERT(Thread::Current()->IsMutatorThread());
 
   Array& bytecode_component_array =
-      Array::Handle(Z, translation_helper_.GetBytecodeComponent());
+      Array::Handle(helper_->zone_, translation_helper_.GetBytecodeComponent());
   if (bytecode_component_array.IsNull()) {
     bytecode_component_array = ReadBytecodeComponent();
     ASSERT(!bytecode_component_array.IsNull());
   }
+
   BytecodeComponentData bytecode_component(bytecode_component_array);
-  bytecode_component_ = &bytecode_component;
+  BytecodeReaderHelper bytecode_reader(helper_, active_class_,
+                                       &bytecode_component);
+
+  bytecode_reader.ReadMemberBytecode(function, md_offset);
+}
+
+RawArray* BytecodeMetadataHelper::ReadBytecodeComponent() {
+  const intptr_t md_offset = GetComponentMetadataPayloadOffset();
+  if (md_offset < 0) {
+    return Array::null();
+  }
+
+  BytecodeReaderHelper component_reader(helper_, nullptr, nullptr);
+  return component_reader.ReadBytecodeComponent(md_offset);
+}
+
+BytecodeReaderHelper::BytecodeReaderHelper(
+    KernelReaderHelper* helper,
+    ActiveClass* active_class,
+    BytecodeComponentData* bytecode_component)
+    : helper_(helper),
+      translation_helper_(helper->translation_helper_),
+      active_class_(active_class),
+      zone_(helper_->zone_),
+      bytecode_component_(bytecode_component),
+      closures_(nullptr),
+      function_type_type_parameters_(nullptr) {}
+
+void BytecodeReaderHelper::ReadMemberBytecode(const Function& function,
+                                              intptr_t md_offset) {
+  ASSERT(Thread::Current()->IsMutatorThread());
 
   AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
                               md_offset);
@@ -97,8 +122,7 @@
 
   // Create object pool and read pool entries.
   const intptr_t obj_count = helper_->reader_.ReadListLength();
-  const ObjectPool& pool =
-      ObjectPool::Handle(helper_->zone_, ObjectPool::New(obj_count));
+  const ObjectPool& pool = ObjectPool::Handle(Z, ObjectPool::New(obj_count));
 
   {
     // While reading pool entries, deopt_ids are allocated for
@@ -111,11 +135,9 @@
   }
 
   // Read bytecode and attach to function.
-  const Bytecode& bytecode =
-      Bytecode::Handle(helper_->zone_, ReadBytecode(pool));
+  const Bytecode& bytecode = Bytecode::Handle(Z, ReadBytecode(pool));
   function.AttachBytecode(bytecode);
-  ASSERT(bytecode.GetBinary(helper_->zone_) ==
-         helper_->reader_.typed_data()->raw());
+  ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
 
   ReadExceptionsTable(bytecode, has_exceptions_table);
 
@@ -131,7 +153,7 @@
     ASSERT(function.IsGenerativeConstructor());
     const intptr_t num_fields = helper_->ReadListLength();
     if (I->use_field_guards()) {
-      Field& field = Field::Handle(helper_->zone_);
+      Field& field = Field::Handle(Z);
       for (intptr_t i = 0; i < num_fields; i++) {
         field ^= ReadObject();
         field.RecordStore(Object::null_object());
@@ -145,8 +167,8 @@
 
   // Read closures.
   if (has_closures) {
-    Function& closure = Function::Handle(helper_->zone_);
-    Bytecode& closure_bytecode = Bytecode::Handle(helper_->zone_);
+    Function& closure = Function::Handle(Z);
+    Bytecode& closure_bytecode = Bytecode::Handle(Z);
     for (intptr_t i = 0; i < num_closures; i++) {
       closure ^= closures_->At(i);
 
@@ -157,8 +179,7 @@
       // Read closure bytecode and attach to closure function.
       closure_bytecode = ReadBytecode(pool);
       closure.AttachBytecode(closure_bytecode);
-      ASSERT(bytecode.GetBinary(helper_->zone_) ==
-             helper_->reader_.typed_data()->raw());
+      ASSERT(bytecode.GetBinary(Z) == helper_->reader_.typed_data()->raw());
 
       ReadExceptionsTable(closure_bytecode, has_exceptions_table);
 
@@ -169,12 +190,10 @@
       }
     }
   }
-
-  bytecode_component_ = nullptr;
 }
 
-void BytecodeMetadataHelper::ReadClosureDeclaration(const Function& function,
-                                                    intptr_t closureIndex) {
+void BytecodeReaderHelper::ReadClosureDeclaration(const Function& function,
+                                                  intptr_t closureIndex) {
   const int kHasOptionalPositionalParams = 1 << 0;
   const int kHasOptionalNamedParams = 1 << 1;
   const int kHasTypeParams = 1 << 2;
@@ -208,7 +227,7 @@
   closure.SetSignatureType(signature_type);
 }
 
-RawType* BytecodeMetadataHelper::ReadFunctionSignature(
+RawType* BytecodeReaderHelper::ReadFunctionSignature(
     const Function& func,
     bool has_optional_positional_params,
     bool has_optional_named_params,
@@ -270,7 +289,7 @@
   return Type::Cast(type).raw();
 }
 
-void BytecodeMetadataHelper::ReadTypeParametersDeclaration(
+void BytecodeReaderHelper::ReadTypeParametersDeclaration(
     const Class& parameterized_class,
     const Function& parameterized_function,
     intptr_t num_type_params) {
@@ -308,20 +327,20 @@
   }
 }
 
-void BytecodeMetadataHelper::ReadConstantPool(const Function& function,
-                                              const ObjectPool& pool) {
+void BytecodeReaderHelper::ReadConstantPool(const Function& function,
+                                            const ObjectPool& pool) {
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
-                    "BytecodeMetadataHelper::ReadConstantPool");
+                    "BytecodeReaderHelper::ReadConstantPool");
 
   // These enums and the code below reading the constant pool from kernel must
   // be kept in sync with pkg/vm/lib/bytecode/constant_pool.dart.
   enum ConstantPoolTag {
     kInvalid,
-    kNull,
-    kString,
-    kInt,
-    kDouble,
-    kBool,
+    kNull,    // TODO(alexmarkov): obsolete, remove
+    kString,  // TODO(alexmarkov): obsolete, remove
+    kInt,     // TODO(alexmarkov): obsolete, remove
+    kDouble,  // TODO(alexmarkov): obsolete, remove
+    kBool,    // TODO(alexmarkov): obsolete, remove
     kArgDesc,
     kICData,
     kStaticICData,
@@ -329,19 +348,22 @@
     kInstanceField,
     kClass,
     kTypeArgumentsField,
-    kTearOff,
+    kTearOff,  // TODO(alexmarkov): obsolete, remove
     kType,
-    kTypeArguments,
-    kList,
-    kInstance,
-    kTypeArgumentsForInstanceAllocation,
+    kTypeArguments,                       // TODO(alexmarkov): obsolete, remove
+    kList,                                // TODO(alexmarkov): obsolete, remove
+    kInstance,                            // TODO(alexmarkov): obsolete, remove
+    kTypeArgumentsForInstanceAllocation,  // TODO(alexmarkov): obsolete, remove
     kClosureFunction,
     kEndClosureFunctionScope,
     kNativeEntry,
     kSubtypeTestCache,
-    kPartialTearOffInstantiation,
+    kPartialTearOffInstantiation,  // TODO(alexmarkov): obsolete, remove
     kEmptyTypeArguments,
-    kSymbol,
+    kSymbol,           // TODO(alexmarkov): obsolete, remove
+    kInterfaceCallV1,  // TODO(alexmarkov): obsolete, remove
+    kObjectRef,
+    kDirectCall,
     kInterfaceCall,
   };
 
@@ -354,13 +376,13 @@
   const int kInvocationKindMask = 0x3;
   const int kFlagDynamic = 1 << 2;
 
-  Object& obj = Object::Handle(helper_->zone_);
-  Object& elem = Object::Handle(helper_->zone_);
-  Array& array = Array::Handle(helper_->zone_);
-  Field& field = Field::Handle(helper_->zone_);
-  Class& cls = Class::Handle(helper_->zone_);
-  String& name = String::Handle(helper_->zone_);
-  TypeArguments& type_args = TypeArguments::Handle(helper_->zone_);
+  Object& obj = Object::Handle(Z);
+  Object& elem = Object::Handle(Z);
+  Array& array = Array::Handle(Z);
+  Field& field = Field::Handle(Z);
+  Class& cls = Class::Handle(Z);
+  String& name = String::Handle(Z);
+  TypeArguments& type_args = TypeArguments::Handle(Z);
   Class* symbol_class = nullptr;
   Field* symbol_name_field = nullptr;
   const String* simpleInstanceOf = nullptr;
@@ -574,20 +596,18 @@
       case ConstantPoolTag::kPartialTearOffInstantiation: {
         intptr_t tearoff_index = helper_->ReadUInt();
         ASSERT(tearoff_index < i);
-        const Closure& old_closure = Closure::CheckedHandle(
-            helper_->zone_, pool.ObjectAt(tearoff_index));
+        const Closure& old_closure =
+            Closure::CheckedHandle(Z, pool.ObjectAt(tearoff_index));
 
         intptr_t type_args_index = helper_->ReadUInt();
         ASSERT(type_args_index < i);
         type_args ^= pool.ObjectAt(type_args_index);
 
         obj = Closure::New(
-            TypeArguments::Handle(helper_->zone_,
-                                  old_closure.instantiator_type_arguments()),
-            TypeArguments::Handle(helper_->zone_,
-                                  old_closure.function_type_arguments()),
-            type_args, Function::Handle(helper_->zone_, old_closure.function()),
-            Context::Handle(helper_->zone_, old_closure.context()), Heap::kOld);
+            TypeArguments::Handle(Z, old_closure.instantiator_type_arguments()),
+            TypeArguments::Handle(Z, old_closure.function_type_arguments()),
+            type_args, Function::Handle(Z, old_closure.function()),
+            Context::Handle(Z, old_closure.context()), Heap::kOld);
         obj = H.Canonicalize(Instance::Cast(obj));
       } break;
       case ConstantPoolTag::kEmptyTypeArguments:
@@ -600,11 +620,10 @@
           elem = Library::InternalLibrary();
           ASSERT(!elem.IsNull());
           symbol_class = &Class::Handle(
-              helper_->zone_,
-              Library::Cast(elem).LookupClass(Symbols::Symbol()));
+              Z, Library::Cast(elem).LookupClass(Symbols::Symbol()));
           ASSERT(!symbol_class->IsNull());
           symbol_name_field = &Field::Handle(
-              helper_->zone_,
+              Z,
               symbol_class->LookupInstanceFieldAllowPrivate(Symbols::_name()));
           ASSERT(!symbol_name_field->IsNull());
         }
@@ -612,7 +631,7 @@
         Instance::Cast(obj).SetField(*symbol_name_field, name);
         obj = H.Canonicalize(Instance::Cast(obj));
       } break;
-      case ConstantPoolTag::kInterfaceCall: {
+      case ConstantPoolTag::kInterfaceCallV1: {
         helper_->ReadByte();  // TODO(regis): Remove, unneeded.
         name ^= ReadObject();
         ASSERT(name.IsSymbol());
@@ -629,6 +648,37 @@
         // The second entry is used for arguments descriptor.
         obj = array.raw();
       } break;
+      case ConstantPoolTag::kObjectRef:
+        obj = ReadObject();
+        break;
+      case ConstantPoolTag::kDirectCall: {
+        // DirectCall constant occupies 2 entries.
+        // The first entry is used for target function.
+        obj = ReadObject();
+        ASSERT(obj.IsFunction());
+        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
+                       ObjectPool::Patchability::kNotPatchable);
+        pool.SetObjectAt(i, obj);
+        ++i;
+        ASSERT(i < obj_count);
+        // The second entry is used for arguments descriptor.
+        obj = ReadObject();
+      } break;
+      case ConstantPoolTag::kInterfaceCall: {
+        elem = ReadObject();
+        ASSERT(elem.IsFunction());
+        name = Function::Cast(elem).name();
+        ASSERT(name.IsSymbol());
+        // InterfaceCall constant occupies 2 entries.
+        // The first entry is used for selector name.
+        pool.SetTypeAt(i, ObjectPool::EntryType::kTaggedObject,
+                       ObjectPool::Patchability::kNotPatchable);
+        pool.SetObjectAt(i, name);
+        ++i;
+        ASSERT(i < obj_count);
+        // The second entry is used for arguments descriptor.
+        obj = ReadObject();
+      } break;
       default:
         UNREACHABLE();
     }
@@ -638,40 +688,33 @@
   }
 }
 
-RawBytecode* BytecodeMetadataHelper::ReadBytecode(const ObjectPool& pool) {
+RawBytecode* BytecodeReaderHelper::ReadBytecode(const ObjectPool& pool) {
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
-                    "BytecodeMetadataHelper::ReadBytecode");
+                    "BytecodeReaderHelper::ReadBytecode");
   intptr_t size = helper_->ReadUInt();
   intptr_t offset = Utils::RoundUp(helper_->reader_.offset(), sizeof(KBCInstr));
   const uint8_t* data = helper_->reader_.BufferAt(offset);
   ASSERT(Utils::IsAligned(data, sizeof(KBCInstr)));
   helper_->reader_.set_offset(offset + size);
 
-  const ExternalTypedData& instructions = ExternalTypedData::Handle(
-      helper_->zone_,
-      ExternalTypedData::New(kExternalTypedDataInt8ArrayCid,
-                             const_cast<uint8_t*>(data), size, Heap::kOld));
-
   // Create and return bytecode object.
-  return Bytecode::New(instructions, pool);
+  return Bytecode::New(reinterpret_cast<uword>(data), size, offset, pool);
 }
 
-void BytecodeMetadataHelper::ReadExceptionsTable(const Bytecode& bytecode,
-                                                 bool has_exceptions_table) {
+void BytecodeReaderHelper::ReadExceptionsTable(const Bytecode& bytecode,
+                                               bool has_exceptions_table) {
   TIMELINE_DURATION(Thread::Current(), CompilerVerbose,
-                    "BytecodeMetadataHelper::ReadExceptionsTable");
+                    "BytecodeReaderHelper::ReadExceptionsTable");
 
   const intptr_t try_block_count =
       has_exceptions_table ? helper_->reader_.ReadListLength() : 0;
   if (try_block_count > 0) {
-    const ObjectPool& pool =
-        ObjectPool::Handle(helper_->zone_, bytecode.object_pool());
-    AbstractType& handler_type = AbstractType::Handle(helper_->zone_);
-    Array& handler_types = Array::ZoneHandle(helper_->zone_);
-    DescriptorList* pc_descriptors_list =
-        new (helper_->zone_) DescriptorList(64);
+    const ObjectPool& pool = ObjectPool::Handle(Z, bytecode.object_pool());
+    AbstractType& handler_type = AbstractType::Handle(Z);
+    Array& handler_types = Array::ZoneHandle(Z);
+    DescriptorList* pc_descriptors_list = new (Z) DescriptorList(64);
     ExceptionHandlerList* exception_handlers_list =
-        new (helper_->zone_) ExceptionHandlerList();
+        new (Z) ExceptionHandlerList();
 
     // Encoding of ExceptionsTable is described in
     // pkg/vm/lib/bytecode/exceptions.dart.
@@ -711,12 +754,11 @@
           is_generated, handler_types, needs_stacktrace);
     }
     const PcDescriptors& descriptors = PcDescriptors::Handle(
-        helper_->zone_,
-        pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
+        Z, pc_descriptors_list->FinalizePcDescriptors(bytecode.PayloadStart()));
     bytecode.set_pc_descriptors(descriptors);
     const ExceptionHandlers& handlers = ExceptionHandlers::Handle(
-        helper_->zone_, exception_handlers_list->FinalizeExceptionHandlers(
-                            bytecode.PayloadStart()));
+        Z, exception_handlers_list->FinalizeExceptionHandlers(
+               bytecode.PayloadStart()));
     bytecode.set_exception_handlers(handlers);
   } else {
     bytecode.set_pc_descriptors(Object::empty_descriptors());
@@ -724,8 +766,8 @@
   }
 }
 
-void BytecodeMetadataHelper::ReadSourcePositions(const Bytecode& bytecode,
-                                                 bool has_source_positions) {
+void BytecodeReaderHelper::ReadSourcePositions(const Bytecode& bytecode,
+                                               bool has_source_positions) {
   if (!has_source_positions) {
     return;
   }
@@ -735,9 +777,8 @@
   helper_->SkipBytes(length);
 }
 
-RawTypedData* BytecodeMetadataHelper::NativeEntry(const Function& function,
-                                                  const String& external_name) {
-  Zone* zone = helper_->zone_;
+RawTypedData* BytecodeReaderHelper::NativeEntry(const Function& function,
+                                                const String& external_name) {
   MethodRecognizer::Kind kind = MethodRecognizer::RecognizeKind(function);
   // This list of recognized methods must be kept in sync with the list of
   // methods handled specially by the NativeCall bytecode in the interpreter.
@@ -772,8 +813,8 @@
   intptr_t argc_tag = 0;
   if (kind == MethodRecognizer::kUnknown) {
     if (!FLAG_link_natives_lazily) {
-      const Class& cls = Class::Handle(zone, function.Owner());
-      const Library& library = Library::Handle(zone, cls.library());
+      const Class& cls = Class::Handle(Z, function.Owner());
+      const Library& library = Library::Handle(Z, cls.library());
       Dart_NativeEntryResolver resolver = library.native_entry_resolver();
       const bool is_bootstrap_native = Bootstrap::IsBootstrapResolver(resolver);
       const int num_params =
@@ -795,12 +836,7 @@
   return NativeEntryData::New(kind, trampoline, native_function, argc_tag);
 }
 
-RawArray* BytecodeMetadataHelper::ReadBytecodeComponent() {
-  const intptr_t md_offset = GetComponentMetadataPayloadOffset();
-  if (md_offset < 0) {
-    return Array::null();
-  }
-
+RawArray* BytecodeReaderHelper::ReadBytecodeComponent(intptr_t md_offset) {
   ASSERT(Thread::Current()->IsMutatorThread());
 
   AlternativeReadingScope alt(&helper_->reader_, &H.metadata_payloads(),
@@ -844,7 +880,7 @@
   BytecodeComponentData bytecode_component(bytecode_component_array);
 
   // Read object offsets.
-  Smi& offs = Smi::Handle(helper_->zone_);
+  Smi& offs = Smi::Handle(Z);
   for (intptr_t i = 0; i < num_objects; ++i) {
     offs = Smi::New(helper_->reader_.ReadUInt());
     bytecode_component.SetObject(i, offs);
@@ -855,9 +891,7 @@
   return bytecode_component_array.raw();
 }
 
-// TODO(alexmarkov): create a helper class with cached handles to avoid handle
-// allocations.
-RawObject* BytecodeMetadataHelper::ReadObject() {
+RawObject* BytecodeReaderHelper::ReadObject() {
   uint32_t header = helper_->reader_.ReadUInt();
   if ((header & kReferenceBit) != 0) {
     intptr_t index = header >> kIndexShift;
@@ -890,7 +924,7 @@
   return ReadObjectContents(header);
 }
 
-RawObject* BytecodeMetadataHelper::ReadObjectContents(uint32_t header) {
+RawObject* BytecodeReaderHelper::ReadObjectContents(uint32_t header) {
   ASSERT(((header & kReferenceBit) == 0));
 
   // Must be in sync with enum ObjectKind in
@@ -906,6 +940,10 @@
     kGenericType,
     kFunctionType,
     kName,
+    kTypeArguments,
+    kFinalizedGenericType,
+    kConstObject,
+    kArgDesc,
   };
 
   // Member flags, must be in sync with _MemberHandle constants in
@@ -924,6 +962,11 @@
   const int kFlagHasOptionalNamedParams = kFlagBit1;
   const int kFlagHasTypeParams = kFlagBit2;
 
+  // ArgDesc flags, must be in sync with _ArgDescHandle constants in
+  // pkg/vm/lib/bytecode/object_table.dart.
+  const int kFlagHasNamedArgs = kFlagBit0;
+  const int kFlagHasTypeArgs = kFlagBit1;
+
   const intptr_t kind = (header >> kKindShift) & kKindMask;
   const intptr_t flags = header & kFlagsMask;
 
@@ -1047,7 +1090,7 @@
           Z, Function::NewSignatureFunction(*active_class_->klass,
                                             active_class_->enclosing != NULL
                                                 ? *active_class_->enclosing
-                                                : Function::Handle(Z),
+                                                : Function::null_function(),
                                             TokenPosition::kNoSource));
 
       return ReadFunctionSignature(
@@ -1066,12 +1109,157 @@
         return library.PrivateName(name);
       }
     }
+    case kTypeArguments: {
+      return ReadTypeArguments(Class::Handle(Z));
+    }
+    case kFinalizedGenericType: {
+      const Class& cls = Class::CheckedHandle(Z, ReadObject());
+      const TypeArguments& type_arguments =
+          TypeArguments::CheckedHandle(Z, ReadObject());
+      const Type& type = Type::Handle(
+          Z, Type::New(cls, type_arguments, TokenPosition::kNoSource));
+      type.SetIsFinalized();
+      return type.Canonicalize();
+    }
+    case kConstObject: {
+      const intptr_t tag = flags / kFlagBit0;
+      return ReadConstObject(tag);
+    }
+    case kArgDesc: {
+      const intptr_t num_arguments = helper_->ReadUInt();
+      const intptr_t num_type_args =
+          ((flags & kFlagHasTypeArgs) != 0) ? helper_->ReadUInt() : 0;
+      if ((flags & kFlagHasNamedArgs) == 0) {
+        return ArgumentsDescriptor::New(num_type_args, num_arguments);
+      } else {
+        const intptr_t num_arg_names = helper_->ReadListLength();
+        const Array& array = Array::Handle(Z, Array::New(num_arg_names));
+        String& name = String::Handle(Z);
+        for (intptr_t i = 0; i < num_arg_names; ++i) {
+          name ^= ReadObject();
+          array.SetAt(i, name);
+        }
+        return ArgumentsDescriptor::New(num_type_args, num_arguments, array);
+      }
+    }
+    default:
+      UNREACHABLE();
   }
 
   return Object::null();
 }
 
-RawString* BytecodeMetadataHelper::ReadString(bool is_canonical) {
+RawObject* BytecodeReaderHelper::ReadConstObject(intptr_t tag) {
+  // Must be in sync with enum ConstTag in
+  // pkg/vm/lib/bytecode/object_table.dart.
+  enum ConstTag {
+    kInvalid,
+    kInstance,
+    kInt,
+    kDouble,
+    kList,
+    kTearOff,
+    kBool,
+    kSymbol,
+    kTearOffInstantiation,
+  };
+
+  switch (tag) {
+    case kInvalid:
+      UNREACHABLE();
+      break;
+    case kInstance: {
+      const Type& type = Type::CheckedHandle(Z, ReadObject());
+      const Class& cls = Class::Handle(Z, type.type_class());
+      const Instance& obj = Instance::Handle(Z, Instance::New(cls, Heap::kOld));
+      if (type.arguments() != TypeArguments::null()) {
+        const TypeArguments& type_args =
+            TypeArguments::Handle(Z, type.arguments());
+        obj.SetTypeArguments(type_args);
+      }
+      const intptr_t num_fields = helper_->ReadUInt();
+      Field& field = Field::Handle(Z);
+      Object& value = Object::Handle(Z);
+      for (intptr_t i = 0; i < num_fields; ++i) {
+        field ^= ReadObject();
+        value = ReadObject();
+        obj.SetField(field, value);
+      }
+      return H.Canonicalize(obj);
+    }
+    case kInt: {
+      const int64_t value = helper_->reader_.ReadSLEB128AsInt64();
+      if (Smi::IsValid(value)) {
+        return Smi::New(static_cast<intptr_t>(value));
+      }
+      const Integer& obj = Integer::Handle(Z, Integer::New(value, Heap::kOld));
+      return H.Canonicalize(obj);
+    }
+    case kDouble: {
+      const int64_t bits = helper_->reader_.ReadSLEB128AsInt64();
+      double value = bit_cast<double, int64_t>(bits);
+      const Double& obj = Double::Handle(Z, Double::New(value, Heap::kOld));
+      return H.Canonicalize(obj);
+    }
+    case kList: {
+      const AbstractType& elem_type =
+          AbstractType::CheckedHandle(Z, ReadObject());
+      const intptr_t length = helper_->ReadUInt();
+      const Array& array = Array::Handle(Z, Array::New(length, elem_type));
+      Object& value = Object::Handle(Z);
+      for (intptr_t i = 0; i < length; ++i) {
+        value = ReadObject();
+        array.SetAt(i, value);
+      }
+      array.MakeImmutable();
+      return H.Canonicalize(array);
+    }
+    case kTearOff: {
+      Object& obj = Object::Handle(Z, ReadObject());
+      ASSERT(obj.IsFunction());
+      obj = Function::Cast(obj).ImplicitClosureFunction();
+      ASSERT(obj.IsFunction());
+      obj = Function::Cast(obj).ImplicitStaticClosure();
+      ASSERT(obj.IsInstance());
+      return H.Canonicalize(Instance::Cast(obj));
+    }
+    case kBool: {
+      bool is_true = helper_->ReadByte() != 0;
+      return is_true ? Bool::True().raw() : Bool::False().raw();
+    }
+    case kSymbol: {
+      const String& name = String::CheckedHandle(Z, ReadObject());
+      ASSERT(name.IsSymbol());
+      const Library& library = Library::Handle(Z, Library::InternalLibrary());
+      ASSERT(!library.IsNull());
+      const Class& cls =
+          Class::Handle(Z, library.LookupClass(Symbols::Symbol()));
+      ASSERT(!cls.IsNull());
+      const Field& field = Field::Handle(
+          Z, cls.LookupInstanceFieldAllowPrivate(Symbols::_name()));
+      ASSERT(!field.IsNull());
+      const Instance& obj = Instance::Handle(Z, Instance::New(cls, Heap::kOld));
+      obj.SetField(field, name);
+      return H.Canonicalize(obj);
+    }
+    case kTearOffInstantiation: {
+      Closure& closure = Closure::CheckedHandle(Z, ReadObject());
+      const TypeArguments& type_args =
+          TypeArguments::CheckedHandle(Z, ReadObject());
+      closure = Closure::New(
+          TypeArguments::Handle(Z, closure.instantiator_type_arguments()),
+          TypeArguments::Handle(Z, closure.function_type_arguments()),
+          type_args, Function::Handle(Z, closure.function()),
+          Context::Handle(Z, closure.context()), Heap::kOld);
+      return H.Canonicalize(closure);
+    }
+    default:
+      UNREACHABLE();
+  }
+  return Object::null();
+}
+
+RawString* BytecodeReaderHelper::ReadString(bool is_canonical) {
   const int kFlagTwoByteString = 1;
   const int kHeaderFields = 2;
   const int kUInt32Size = 4;
@@ -1121,7 +1309,7 @@
   }
 }
 
-RawTypeArguments* BytecodeMetadataHelper::ReadTypeArguments(
+RawTypeArguments* BytecodeReaderHelper::ReadTypeArguments(
     const Class& instantiator) {
   const intptr_t length = helper_->reader_.ReadUInt();
   TypeArguments& type_arguments =
@@ -1225,11 +1413,9 @@
         ExternalTypedData::Handle(zone, function.KernelData()),
         function.KernelDataProgramOffset());
     ActiveClass active_class;
-    TypeTranslator type_translator(&reader_helper, &active_class,
-                                   /* finalize= */ true);
 
-    BytecodeMetadataHelper bytecode_metadata_helper(
-        &reader_helper, &type_translator, &active_class);
+    BytecodeMetadataHelper bytecode_metadata_helper(&reader_helper,
+                                                    &active_class);
 
     // Setup a [ActiveClassScope] and a [ActiveMemberScope] which will be used
     // e.g. for type translation.
diff --git a/runtime/vm/compiler/frontend/bytecode_reader.h b/runtime/vm/compiler/frontend/bytecode_reader.h
index ad1fef8..600dc84 100644
--- a/runtime/vm/compiler/frontend/bytecode_reader.h
+++ b/runtime/vm/compiler/frontend/bytecode_reader.h
@@ -22,7 +22,6 @@
   static const char* tag() { return "vm.bytecode"; }
 
   explicit BytecodeMetadataHelper(KernelReaderHelper* helper,
-                                  TypeTranslator* type_translator,
                                   ActiveClass* active_class);
 
   bool HasBytecode(intptr_t node_offset);
@@ -32,6 +31,23 @@
   RawArray* ReadBytecodeComponent();
 
  private:
+  ActiveClass* const active_class_;
+
+  DISALLOW_COPY_AND_ASSIGN(BytecodeMetadataHelper);
+};
+
+// Helper class for reading bytecode.
+class BytecodeReaderHelper : public ValueObject {
+ public:
+  explicit BytecodeReaderHelper(KernelReaderHelper* helper,
+                                ActiveClass* active_class,
+                                BytecodeComponentData* bytecode_component);
+
+  void ReadMemberBytecode(const Function& function, intptr_t md_offset);
+
+  RawArray* ReadBytecodeComponent(intptr_t md_offset);
+
+ private:
   // These constants should match corresponding constants in class ObjectHandle
   // (pkg/vm/lib/bytecode/object_table.dart).
   static const int kReferenceBit = 1 << 0;
@@ -41,11 +57,12 @@
   static const int kFlagBit0 = 1 << 5;
   static const int kFlagBit1 = 1 << 6;
   static const int kFlagBit2 = 1 << 7;
-  static const int kFlagsMask = (kFlagBit0 | kFlagBit1 | kFlagBit2);
+  static const int kFlagBit3 = 1 << 8;
+  static const int kFlagsMask = (kFlagBit0 | kFlagBit1 | kFlagBit2 | kFlagBit3);
 
   class FunctionTypeScope : public ValueObject {
    public:
-    explicit FunctionTypeScope(BytecodeMetadataHelper* bytecode_reader)
+    explicit FunctionTypeScope(BytecodeReaderHelper* bytecode_reader)
         : bytecode_reader_(bytecode_reader),
           saved_type_parameters_(
               bytecode_reader->function_type_type_parameters_) {}
@@ -55,7 +72,7 @@
     }
 
    private:
-    BytecodeMetadataHelper* bytecode_reader_;
+    BytecodeReaderHelper* bytecode_reader_;
     TypeArguments* const saved_type_parameters_;
   };
 
@@ -78,16 +95,19 @@
 
   RawObject* ReadObject();
   RawObject* ReadObjectContents(uint32_t header);
+  RawObject* ReadConstObject(intptr_t tag);
   RawString* ReadString(bool is_canonical = true);
   RawTypeArguments* ReadTypeArguments(const Class& instantiator);
 
-  TypeTranslator& type_translator_;
+  KernelReaderHelper* const helper_;
+  TranslationHelper& translation_helper_;
   ActiveClass* const active_class_;
-  BytecodeComponentData* bytecode_component_;
+  Zone* const zone_;
+  BytecodeComponentData* const bytecode_component_;
   Array* closures_;
   TypeArguments* function_type_type_parameters_;
 
-  DISALLOW_COPY_AND_ASSIGN(BytecodeMetadataHelper);
+  DISALLOW_COPY_AND_ASSIGN(BytecodeReaderHelper);
 };
 
 class BytecodeComponentData : ValueObject {
diff --git a/runtime/vm/compiler/frontend/flow_graph_builder.cc b/runtime/vm/compiler/frontend/flow_graph_builder.cc
index 3d14de6..00ff453 100644
--- a/runtime/vm/compiler/frontend/flow_graph_builder.cc
+++ b/runtime/vm/compiler/frontend/flow_graph_builder.cc
@@ -276,6 +276,17 @@
     call_->ReplaceUsesWith(caller_graph_->constant_null());
 
     // Update dominator tree.
+    for (intptr_t i = 0, n = callee_entry->dominated_blocks().length(); i < n;
+         i++) {
+      BlockEntryInstr* block = callee_entry->dominated_blocks()[i];
+      true_target->AddDominatedBlock(block);
+    }
+    for (intptr_t i = 0, n = call_block->dominated_blocks().length(); i < n;
+         i++) {
+      BlockEntryInstr* block = call_block->dominated_blocks()[i];
+      false_block->AddDominatedBlock(block);
+    }
+    call_block->ClearDominatedBlocks();
     call_block->AddDominatedBlock(true_target);
     call_block->AddDominatedBlock(false_block);
 
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
index 1af6d53..bf8977a 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.cc
@@ -2030,6 +2030,7 @@
       return flow_graph_builder_->BuildGraphOfInvokeFieldDispatcher(function);
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
+    case RawFunction::kFfiTrampoline:
       break;
   }
   UNREACHABLE();
diff --git a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
index b16d914..01b6693 100644
--- a/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
+++ b/runtime/vm/compiler/frontend/kernel_binary_flowgraph.h
@@ -39,7 +39,7 @@
                             &type_translator_,
                             active_class_,
                             flow_graph_builder),
-        bytecode_metadata_helper_(this, &type_translator_, active_class_),
+        bytecode_metadata_helper_(this, active_class_),
         direct_call_metadata_helper_(this),
         inferred_type_metadata_helper_(this),
         procedure_attributes_metadata_helper_(this),
diff --git a/runtime/vm/compiler/frontend/kernel_translation_helper.h b/runtime/vm/compiler/frontend/kernel_translation_helper.h
index 46af4b6..d50712e 100644
--- a/runtime/vm/compiler/frontend/kernel_translation_helper.h
+++ b/runtime/vm/compiler/frontend/kernel_translation_helper.h
@@ -713,7 +713,8 @@
   };
 
   enum Flag {
-    kExternal = 1,
+    kExternal = 1 << 0,
+    kSynthetic = 1 << 1,
   };
 
   explicit LibraryHelper(KernelReaderHelper* helper)
@@ -729,6 +730,7 @@
   void SetJustRead(Field field) { next_read_ = field + 1; }
 
   bool IsExternal() const { return (flags_ & kExternal) != 0; }
+  bool IsSynthetic() const { return (flags_ & kSynthetic) != 0; }
 
   uint8_t flags_;
   NameIndex canonical_name_;
@@ -1073,6 +1075,7 @@
   intptr_t data_program_offset_;
 
   friend class BytecodeMetadataHelper;
+  friend class BytecodeReaderHelper;
   friend class ClassHelper;
   friend class CallSiteAttributesMetadataHelper;
   friend class ConstantEvaluator;
diff --git a/runtime/vm/compiler/frontend/scope_builder.cc b/runtime/vm/compiler/frontend/scope_builder.cc
index 201c724..d585002 100644
--- a/runtime/vm/compiler/frontend/scope_builder.cc
+++ b/runtime/vm/compiler/frontend/scope_builder.cc
@@ -267,13 +267,8 @@
       break;
     }
     case RawFunction::kImplicitGetter:
-    case RawFunction::kImplicitStaticFinalGetter:
     case RawFunction::kImplicitSetter: {
       ASSERT(helper_.PeekTag() == kField);
-      if (IsFieldInitializer(function, Z)) {
-        VisitNode();
-        break;
-      }
       const bool is_setter = function.IsImplicitSetterFunction();
       const bool is_method = !function.IsStaticFunction();
       intptr_t pos = 0;
@@ -309,6 +304,18 @@
       }
       break;
     }
+    case RawFunction::kImplicitStaticFinalGetter: {
+      ASSERT(helper_.PeekTag() == kField);
+      ASSERT(function.IsStaticFunction());
+      // In addition to static field initializers, scopes/local variables
+      // are needed for implicit getters of static const fields, in order to
+      // be able to evaluate their initializers in constant evaluator.
+      if (IsFieldInitializer(function, Z) ||
+          Field::Handle(Z, function.accessor_field()).is_const()) {
+        VisitNode();
+      }
+      break;
+    }
     case RawFunction::kDynamicInvocationForwarder: {
       if (helper_.PeekTag() == kField) {
 #ifdef DEBUG
@@ -376,6 +383,7 @@
       break;
     case RawFunction::kSignatureFunction:
     case RawFunction::kIrregexpFunction:
+    case RawFunction::kFfiTrampoline:
       UNREACHABLE();
   }
   if (needs_expr_temp_) {
diff --git a/runtime/vm/compiler/graph_intrinsifier.cc b/runtime/vm/compiler/graph_intrinsifier.cc
new file mode 100644
index 0000000..d537054
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier.cc
@@ -0,0 +1,1039 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 for intrinsifying functions.
+
+// DBC does not use graph intrinsics.
+#if !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
+
+#include "vm/compiler/graph_intrinsifier.h"
+#include "vm/compiler/backend/flow_graph.h"
+#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/linearscan.h"
+#include "vm/compiler/jit/compiler.h"
+#include "vm/cpu.h"
+
+namespace dart {
+
+DECLARE_FLAG(bool, code_comments);
+DECLARE_FLAG(bool, print_flow_graph);
+DECLARE_FLAG(bool, print_flow_graph_optimized);
+
+namespace compiler {
+
+static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) {
+  // The FlowGraph here is constructed by the intrinsics builder methods, and
+  // is different from compiler->flow_graph(), the original method's flow graph.
+  compiler->assembler()->Comment("Graph intrinsic begin");
+  for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) {
+    BlockEntryInstr* block = graph->reverse_postorder()[i];
+    if (block->IsGraphEntry()) continue;  // No code for graph entry needed.
+
+    if (block->HasParallelMove()) {
+      compiler->parallel_move_resolver()->EmitNativeCode(
+          block->parallel_move());
+    }
+
+    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
+      Instruction* instr = it.Current();
+      if (FLAG_code_comments) compiler->EmitComment(instr);
+      if (instr->IsParallelMove()) {
+        compiler->parallel_move_resolver()->EmitNativeCode(
+            instr->AsParallelMove());
+      } else if (instr->IsInvokeMathCFunction()) {
+        ASSERT(instr->locs() != NULL);
+        GraphIntrinsifier::IntrinsicCallPrologue(compiler->assembler());
+        instr->EmitNativeCode(compiler);
+        GraphIntrinsifier::IntrinsicCallEpilogue(compiler->assembler());
+      } else {
+        ASSERT(instr->locs() != NULL);
+        // Calls are not supported in intrinsics code.
+        ASSERT(!instr->locs()->always_calls());
+        instr->EmitNativeCode(compiler);
+      }
+    }
+  }
+  compiler->assembler()->Comment("Graph intrinsic end");
+}
+
+bool GraphIntrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
+                                        FlowGraphCompiler* compiler) {
+  ASSERT(!parsed_function.function().HasOptionalParameters());
+  PrologueInfo prologue_info(-1, -1);
+
+  auto graph_entry =
+      new GraphEntryInstr(parsed_function, Compiler::kNoOSRDeoptId);
+
+  intptr_t block_id = 1;  // 0 is GraphEntry.
+  graph_entry->set_normal_entry(
+      new FunctionEntryInstr(graph_entry, block_id, kInvalidTryIndex,
+                             CompilerState::Current().GetNextDeoptId()));
+
+  FlowGraph* graph =
+      new FlowGraph(parsed_function, graph_entry, block_id, prologue_info);
+  const Function& function = parsed_function.function();
+  switch (function.recognized_kind()) {
+#define EMIT_CASE(class_name, function_name, enum_name, fp)                    \
+  case MethodRecognizer::k##enum_name:                                         \
+    if (!Build_##enum_name(graph)) return false;                               \
+    break;
+
+    GRAPH_INTRINSICS_LIST(EMIT_CASE);
+    default:
+      return false;
+#undef EMIT_CASE
+  }
+
+  if (FLAG_support_il_printer && FLAG_print_flow_graph &&
+      FlowGraphPrinter::ShouldPrint(function)) {
+    THR_Print("Intrinsic graph before\n");
+    FlowGraphPrinter printer(*graph);
+    printer.PrintBlocks();
+  }
+
+  // Prepare for register allocation (cf. FinalizeGraph).
+  graph->RemoveRedefinitions();
+
+  // Ensure loop hierarchy has been computed.
+  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();
+
+  if (FLAG_support_il_printer && FLAG_print_flow_graph &&
+      FlowGraphPrinter::ShouldPrint(function)) {
+    THR_Print("Intrinsic graph after\n");
+    FlowGraphPrinter printer(*graph);
+    printer.PrintBlocks();
+  }
+  EmitCodeFor(compiler, graph);
+  return true;
+}
+
+static intptr_t CidForRepresentation(Representation rep) {
+  switch (rep) {
+    case kUnboxedDouble:
+      return kDoubleCid;
+    case kUnboxedFloat32x4:
+      return kFloat32x4Cid;
+    case kUnboxedInt32x4:
+      return kInt32x4Cid;
+    case kUnboxedFloat64x2:
+      return kFloat64x2Cid;
+    case kUnboxedUint32:
+      return kDynamicCid;  // smi or mint.
+    default:
+      UNREACHABLE();
+      return kIllegalCid;
+  }
+}
+
+static Representation RepresentationForCid(intptr_t cid) {
+  switch (cid) {
+    case kDoubleCid:
+      return kUnboxedDouble;
+    case kFloat32x4Cid:
+      return kUnboxedFloat32x4;
+    case kInt32x4Cid:
+      return kUnboxedInt32x4;
+    case kFloat64x2Cid:
+      return kUnboxedFloat64x2;
+    default:
+      UNREACHABLE();
+      return kNoRepresentation;
+  }
+}
+
+// Notes about the graph intrinsics:
+//
+// IR instructions which would jump to a deoptimization sequence on failure
+// instead branch to the intrinsic slow path.
+//
+class BlockBuilder : public ValueObject {
+ public:
+  BlockBuilder(FlowGraph* flow_graph, BlockEntryInstr* entry)
+      : flow_graph_(flow_graph),
+        entry_(entry),
+        current_(entry),
+        fall_through_env_(new Environment(0,
+                                          0,
+                                          DeoptId::kNone,
+                                          flow_graph->parsed_function(),
+                                          NULL)) {}
+
+  Definition* AddToInitialDefinitions(Definition* def) {
+    def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
+    auto normal_entry = flow_graph_->graph_entry()->normal_entry();
+    flow_graph_->AddToInitialDefinitions(normal_entry, def);
+    return def;
+  }
+
+  Definition* AddDefinition(Definition* def) {
+    def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
+    AddInstruction(def);
+    return def;
+  }
+
+  Instruction* AddInstruction(Instruction* instr) {
+    if (instr->ComputeCanDeoptimize()) {
+      // Since we use the presence of an environment to determine if an
+      // instructions can deoptimize, we need an empty environment for
+      // instructions that "deoptimize" to the intrinsic fall-through code.
+      instr->SetEnvironment(fall_through_env_);
+    }
+    current_ = current_->AppendInstruction(instr);
+    return instr;
+  }
+
+  void AddIntrinsicReturn(Value* value) {
+    ReturnInstr* instr = new ReturnInstr(
+        TokenPos(), value, CompilerState::Current().GetNextDeoptId());
+    AddInstruction(instr);
+    entry_->set_last_instruction(instr);
+  }
+
+  Definition* AddParameter(intptr_t index) {
+    intptr_t adjustment = GraphIntrinsifier::ParameterSlotFromSp();
+    return AddToInitialDefinitions(new ParameterInstr(
+        adjustment + index, flow_graph_->graph_entry(), SPREG));
+  }
+
+  TokenPosition TokenPos() { return flow_graph_->function().token_pos(); }
+
+  Definition* AddNullDefinition() {
+    return AddDefinition(new ConstantInstr(Object::ZoneHandle(Object::null())));
+  }
+
+  Definition* AddUnboxInstr(Representation rep, Value* value, bool is_checked) {
+    Definition* unboxed_value =
+        AddDefinition(UnboxInstr::Create(rep, value, DeoptId::kNone));
+    if (is_checked) {
+      // The type of |value| has already been checked and it is safe to
+      // adjust reaching type. This is done manually because there is no type
+      // propagation when building intrinsics.
+      unboxed_value->AsUnbox()->value()->SetReachingType(
+          new CompileType(CompileType::FromCid(CidForRepresentation(rep))));
+    }
+    return unboxed_value;
+  }
+
+  Definition* AddUnboxInstr(Representation rep,
+                            Definition* boxed,
+                            bool is_checked) {
+    return AddUnboxInstr(rep, new Value(boxed), is_checked);
+  }
+
+  Definition* InvokeMathCFunction(MethodRecognizer::Kind recognized_kind,
+                                  ZoneGrowableArray<Value*>* args) {
+    return InvokeMathCFunctionHelper(recognized_kind, args);
+  }
+
+ private:
+  Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind,
+                                        ZoneGrowableArray<Value*>* args) {
+    InvokeMathCFunctionInstr* invoke_math_c_function =
+        new InvokeMathCFunctionInstr(args, DeoptId::kNone, recognized_kind,
+                                     TokenPos());
+    AddDefinition(invoke_math_c_function);
+    return invoke_math_c_function;
+  }
+
+  FlowGraph* flow_graph_;
+  BlockEntryInstr* entry_;
+  Instruction* current_;
+  Environment* fall_through_env_;
+};
+
+static Definition* PrepareIndexedOp(FlowGraph* flow_graph,
+                                    BlockBuilder* builder,
+                                    Definition* array,
+                                    Definition* index,
+                                    const Slot& length_field) {
+  Definition* length = builder->AddDefinition(new LoadFieldInstr(
+      new Value(array), length_field, TokenPosition::kNoSource));
+  // Note that the intrinsifier must always use deopting array bound
+  // checks, because intrinsics currently don't support calls.
+  Definition* safe_index = new CheckArrayBoundInstr(
+      new Value(length), new Value(index), DeoptId::kNone);
+  builder->AddDefinition(safe_index);
+  return safe_index;
+}
+
+static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
+                                      intptr_t array_cid) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* index = builder.AddParameter(1);
+  Definition* array = builder.AddParameter(2);
+
+  index = PrepareIndexedOp(flow_graph, &builder, array, index,
+                           Slot::GetLengthFieldForArrayCid(array_cid));
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    array = builder.AddDefinition(new LoadUntaggedInstr(
+        new Value(array), ExternalTypedData::data_offset()));
+  }
+
+  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
+      new Value(array), new Value(index),
+      Instance::ElementSizeFor(array_cid),  // index scale
+      array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  // Box and/or convert result if necessary.
+  switch (array_cid) {
+    case kTypedDataInt32ArrayCid:
+    case kExternalTypedDataInt32ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedInt32, new Value(result)));
+      break;
+    case kTypedDataUint32ArrayCid:
+    case kExternalTypedDataUint32ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedUint32, new Value(result)));
+      break;
+    case kTypedDataFloat32ArrayCid:
+      result = builder.AddDefinition(
+          new FloatToDoubleInstr(new Value(result), DeoptId::kNone));
+    // Fall through.
+    case kTypedDataFloat64ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedDouble, new Value(result)));
+      break;
+    case kTypedDataFloat32x4ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedFloat32x4, new Value(result)));
+      break;
+    case kTypedDataInt32x4ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedInt32x4, new Value(result)));
+      break;
+    case kTypedDataFloat64x2ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedFloat64x2, new Value(result)));
+      break;
+    case kArrayCid:
+    case kImmutableArrayCid:
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      // Nothing to do.
+      break;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      result = builder.AddDefinition(
+          BoxInstr::Create(kUnboxedInt64, new Value(result)));
+      break;
+    default:
+      UNREACHABLE();
+      break;
+  }
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
+                                      intptr_t array_cid) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* value = builder.AddParameter(1);
+  Definition* index = builder.AddParameter(2);
+  Definition* array = builder.AddParameter(3);
+
+  index = PrepareIndexedOp(flow_graph, &builder, array, index,
+                           Slot::GetLengthFieldForArrayCid(array_cid));
+
+  // Value check/conversion.
+  switch (array_cid) {
+    case kTypedDataInt8ArrayCid:
+    case kTypedDataUint8ArrayCid:
+    case kExternalTypedDataUint8ArrayCid:
+    case kTypedDataUint8ClampedArrayCid:
+    case kExternalTypedDataUint8ClampedArrayCid:
+    case kTypedDataInt16ArrayCid:
+    case kTypedDataUint16ArrayCid:
+      builder.AddInstruction(new CheckSmiInstr(new Value(value), DeoptId::kNone,
+                                               builder.TokenPos()));
+      break;
+    case kTypedDataInt32ArrayCid:
+    case kExternalTypedDataInt32ArrayCid:
+    // Use same truncating unbox-instruction for int32 and uint32.
+    // Fall-through.
+    case kTypedDataUint32ArrayCid:
+    case kExternalTypedDataUint32ArrayCid:
+      // Supports smi and mint, slow-case for bigints.
+      value = builder.AddUnboxInstr(kUnboxedUint32, new Value(value),
+                                    /* is_checked = */ false);
+      break;
+    case kTypedDataInt64ArrayCid:
+    case kTypedDataUint64ArrayCid:
+      value = builder.AddUnboxInstr(kUnboxedInt64, new Value(value),
+                                    /* is_checked = */ false);
+      break;
+
+    case kTypedDataFloat32ArrayCid:
+    case kTypedDataFloat64ArrayCid:
+    case kTypedDataFloat32x4ArrayCid:
+    case kTypedDataInt32x4ArrayCid:
+    case kTypedDataFloat64x2ArrayCid: {
+      intptr_t value_check_cid = kDoubleCid;
+      Representation rep = kUnboxedDouble;
+      switch (array_cid) {
+        case kTypedDataFloat32x4ArrayCid:
+          value_check_cid = kFloat32x4Cid;
+          rep = kUnboxedFloat32x4;
+          break;
+        case kTypedDataInt32x4ArrayCid:
+          value_check_cid = kInt32x4Cid;
+          rep = kUnboxedInt32x4;
+          break;
+        case kTypedDataFloat64x2ArrayCid:
+          value_check_cid = kFloat64x2Cid;
+          rep = kUnboxedFloat64x2;
+          break;
+        default:
+          // Float32/Float64 case already handled.
+          break;
+      }
+      Zone* zone = flow_graph->zone();
+      Cids* value_check = Cids::CreateMonomorphic(zone, value_check_cid);
+      builder.AddInstruction(new CheckClassInstr(
+          new Value(value), DeoptId::kNone, *value_check, builder.TokenPos()));
+      value = builder.AddUnboxInstr(rep, new Value(value),
+                                    /* is_checked = */ true);
+      if (array_cid == kTypedDataFloat32ArrayCid) {
+        value = builder.AddDefinition(
+            new DoubleToFloatInstr(new Value(value), DeoptId::kNone));
+      }
+      break;
+    }
+    default:
+      UNREACHABLE();
+  }
+
+  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
+    array = builder.AddDefinition(new LoadUntaggedInstr(
+        new Value(array), ExternalTypedData::data_offset()));
+  }
+  // No store barrier.
+  ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
+         RawObject::IsTypedDataClassId(array_cid));
+  builder.AddInstruction(new StoreIndexedInstr(
+      new Value(array), new Value(index), new Value(value), kNoStoreBarrier,
+      Instance::ElementSizeFor(array_cid),  // index scale
+      array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                               \
+  bool GraphIntrinsifier::Build_##enum_name##GetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    return IntrinsifyArrayGetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##GetIndexed));          \
+  }
+
+#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)                               \
+  bool GraphIntrinsifier::Build_##enum_name##SetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    return IntrinsifyArraySetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##SetIndexed));          \
+  }
+
+DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)
+DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
+
+#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                       \
+  DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                                     \
+  DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int64Array)
+DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint64Array)
+
+#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_ARRAY_SETTER_INTRINSIC
+
+#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                         \
+  bool GraphIntrinsifier::Build_##enum_name##GetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                        \
+      return false;                                                            \
+    }                                                                          \
+    return IntrinsifyArrayGetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##GetIndexed));          \
+  }
+
+#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)                         \
+  bool GraphIntrinsifier::Build_##enum_name##SetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                        \
+      return false;                                                            \
+    }                                                                          \
+    return IntrinsifyArraySetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##SetIndexed));          \
+  }
+
+#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                 \
+  DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                               \
+  DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
+DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
+
+#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
+
+#define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name)                          \
+  bool GraphIntrinsifier::Build_##enum_name##GetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {                        \
+      return false;                                                            \
+    }                                                                          \
+    return IntrinsifyArrayGetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##GetIndexed));          \
+  }
+
+#define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)                          \
+  bool GraphIntrinsifier::Build_##enum_name##SetIndexed(                       \
+      FlowGraph* flow_graph) {                                                 \
+    if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {                        \
+      return false;                                                            \
+    }                                                                          \
+    return IntrinsifyArraySetIndexed(                                          \
+        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
+                        MethodRecognizer::k##enum_name##SetIndexed));          \
+  }
+
+#define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                  \
+  DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name)                                \
+  DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)
+
+DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array)
+DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array)
+DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array)
+
+#undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS
+#undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC
+#undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC
+
+static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* index = builder.AddParameter(1);
+  Definition* str = builder.AddParameter(2);
+
+  index =
+      PrepareIndexedOp(flow_graph, &builder, str, index, Slot::String_length());
+
+  // For external strings: Load external data.
+  if (cid == kExternalOneByteStringCid) {
+    str = builder.AddDefinition(new LoadUntaggedInstr(
+        new Value(str), ExternalOneByteString::external_data_offset()));
+  } else if (cid == kExternalTwoByteStringCid) {
+    str = builder.AddDefinition(new LoadUntaggedInstr(
+        new Value(str), ExternalTwoByteString::external_data_offset()));
+  }
+
+  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
+      new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid,
+      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) {
+  return BuildCodeUnitAt(flow_graph, kOneByteStringCid);
+}
+
+bool GraphIntrinsifier::Build_TwoByteStringCodeUnitAt(FlowGraph* flow_graph) {
+  return BuildCodeUnitAt(flow_graph, kTwoByteStringCid);
+}
+
+bool GraphIntrinsifier::Build_ExternalOneByteStringCodeUnitAt(
+    FlowGraph* flow_graph) {
+  return BuildCodeUnitAt(flow_graph, kExternalOneByteStringCid);
+}
+
+bool GraphIntrinsifier::Build_ExternalTwoByteStringCodeUnitAt(
+    FlowGraph* flow_graph) {
+  return BuildCodeUnitAt(flow_graph, kExternalTwoByteStringCid);
+}
+
+static bool BuildSimdOp(FlowGraph* flow_graph, intptr_t cid, Token::Kind kind) {
+  if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false;
+
+  const Representation rep = RepresentationForCid(cid);
+
+  Zone* zone = flow_graph->zone();
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* right = builder.AddParameter(1);
+  Definition* left = builder.AddParameter(2);
+
+  Cids* value_check = Cids::CreateMonomorphic(zone, cid);
+  // Check argument. Receiver (left) is known to be a Float32x4.
+  builder.AddInstruction(new CheckClassInstr(new Value(right), DeoptId::kNone,
+                                             *value_check, builder.TokenPos()));
+  Definition* left_simd = builder.AddUnboxInstr(rep, new Value(left),
+                                                /* is_checked = */ true);
+
+  Definition* right_simd = builder.AddUnboxInstr(rep, new Value(right),
+                                                 /* is_checked = */ true);
+
+  Definition* unboxed_result = builder.AddDefinition(SimdOpInstr::Create(
+      SimdOpInstr::KindForOperator(cid, kind), new Value(left_simd),
+      new Value(right_simd), DeoptId::kNone));
+  Definition* result =
+      builder.AddDefinition(BoxInstr::Create(rep, new Value(unboxed_result)));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) {
+  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kMUL);
+}
+
+bool GraphIntrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) {
+  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kSUB);
+}
+
+bool GraphIntrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) {
+  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kADD);
+}
+
+static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph,
+                                  MethodRecognizer::Kind kind) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles() ||
+      !FlowGraphCompiler::SupportsUnboxedSimd128()) {
+    return false;
+  }
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* receiver = builder.AddParameter(1);
+
+  Definition* unboxed_receiver =
+      builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver),
+                            /* is_checked = */ true);
+
+  Definition* unboxed_result = builder.AddDefinition(
+      SimdOpInstr::Create(kind, new Value(unboxed_receiver), DeoptId::kNone));
+
+  Definition* result = builder.AddDefinition(
+      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) {
+  return BuildFloat32x4Shuffle(flow_graph,
+                               MethodRecognizer::kFloat32x4ShuffleX);
+}
+
+bool GraphIntrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) {
+  return BuildFloat32x4Shuffle(flow_graph,
+                               MethodRecognizer::kFloat32x4ShuffleY);
+}
+
+bool GraphIntrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) {
+  return BuildFloat32x4Shuffle(flow_graph,
+                               MethodRecognizer::kFloat32x4ShuffleZ);
+}
+
+bool GraphIntrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) {
+  return BuildFloat32x4Shuffle(flow_graph,
+                               MethodRecognizer::kFloat32x4ShuffleW);
+}
+
+static bool BuildLoadField(FlowGraph* flow_graph, const Slot& field) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* array = builder.AddParameter(1);
+
+  Definition* length = builder.AddDefinition(
+      new LoadFieldInstr(new Value(array), field, builder.TokenPos()));
+  builder.AddIntrinsicReturn(new Value(length));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) {
+  return BuildLoadField(flow_graph, Slot::Array_length());
+}
+
+bool GraphIntrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) {
+  return BuildLoadField(flow_graph, Slot::Array_length());
+}
+
+bool GraphIntrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
+  return BuildLoadField(flow_graph, Slot::GrowableObjectArray_length());
+}
+
+bool GraphIntrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
+  return BuildLoadField(flow_graph, Slot::String_length());
+}
+
+bool GraphIntrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) {
+  return BuildLoadField(flow_graph, Slot::TypedData_length());
+}
+
+bool GraphIntrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* array = builder.AddParameter(1);
+
+  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
+      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
+  Definition* capacity = builder.AddDefinition(new LoadFieldInstr(
+      new Value(backing_store), Slot::Array_length(), builder.TokenPos()));
+  builder.AddIntrinsicReturn(new Value(capacity));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* index = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+
+  index = PrepareIndexedOp(flow_graph, &builder, growable_array, index,
+                           Slot::GrowableObjectArray_length());
+
+  Definition* backing_store = builder.AddDefinition(
+      new LoadFieldInstr(new Value(growable_array),
+                         Slot::GrowableObjectArray_data(), builder.TokenPos()));
+  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
+      new Value(backing_store), new Value(index),
+      Instance::ElementSizeFor(kArrayCid),  // index scale
+      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_ObjectArraySetIndexed(FlowGraph* flow_graph) {
+  if (Isolate::Current()->argument_type_checks()) {
+    return false;
+  }
+
+  return Build_ObjectArraySetIndexedUnchecked(flow_graph);
+}
+
+bool GraphIntrinsifier::Build_ObjectArraySetIndexedUnchecked(
+    FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* value = builder.AddParameter(1);
+  Definition* index = builder.AddParameter(2);
+  Definition* array = builder.AddParameter(3);
+
+  index = PrepareIndexedOp(flow_graph, &builder, array, index,
+                           Slot::Array_length());
+
+  builder.AddInstruction(new StoreIndexedInstr(
+      new Value(array), new Value(index), new Value(value), kEmitStoreBarrier,
+      Instance::ElementSizeFor(kArrayCid),  // index scale
+      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) {
+  if (Isolate::Current()->argument_type_checks()) {
+    return false;
+  }
+
+  return Build_GrowableArraySetIndexedUnchecked(flow_graph);
+}
+
+bool GraphIntrinsifier::Build_GrowableArraySetIndexedUnchecked(
+    FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* value = builder.AddParameter(1);
+  Definition* index = builder.AddParameter(2);
+  Definition* array = builder.AddParameter(3);
+
+  index = PrepareIndexedOp(flow_graph, &builder, array, index,
+                           Slot::GrowableObjectArray_length());
+
+  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
+      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
+
+  builder.AddInstruction(new StoreIndexedInstr(
+      new Value(backing_store), new Value(index), new Value(value),
+      kEmitStoreBarrier,
+      Instance::ElementSizeFor(kArrayCid),  // index scale
+      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* data = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+  Zone* zone = flow_graph->zone();
+
+  Cids* value_check = Cids::CreateMonomorphic(zone, kArrayCid);
+  builder.AddInstruction(new CheckClassInstr(new Value(data), DeoptId::kNone,
+                                             *value_check, builder.TokenPos()));
+
+  builder.AddInstruction(new StoreInstanceFieldInstr(
+      Slot::GrowableObjectArray_data(), new Value(growable_array),
+      new Value(data), kEmitStoreBarrier, builder.TokenPos()));
+  // Return null.
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) {
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* length = builder.AddParameter(1);
+  Definition* growable_array = builder.AddParameter(2);
+
+  builder.AddInstruction(
+      new CheckSmiInstr(new Value(length), DeoptId::kNone, builder.TokenPos()));
+  builder.AddInstruction(new StoreInstanceFieldInstr(
+      Slot::GrowableObjectArray_length(), new Value(growable_array),
+      new Value(length), kNoStoreBarrier, builder.TokenPos()));
+  Definition* null_def = builder.AddNullDefinition();
+  builder.AddIntrinsicReturn(new Value(null_def));
+  return true;
+}
+
+bool GraphIntrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
+    return false;
+  }
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  Definition* receiver = builder.AddParameter(1);
+  Definition* unboxed_value =
+      builder.AddUnboxInstr(kUnboxedDouble, new Value(receiver),
+                            /* is_checked = */ true);
+  Definition* unboxed_result = builder.AddDefinition(new UnaryDoubleOpInstr(
+      Token::kNEGATE, new Value(unboxed_value), DeoptId::kNone));
+  Definition* result = builder.AddDefinition(
+      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
+  builder.AddIntrinsicReturn(new Value(result));
+  return true;
+}
+
+static bool BuildInvokeMathCFunction(BlockBuilder* builder,
+                                     MethodRecognizer::Kind kind,
+                                     intptr_t num_parameters = 1) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
+    return false;
+  }
+  ZoneGrowableArray<Value*>* args =
+      new ZoneGrowableArray<Value*>(num_parameters);
+
+  for (intptr_t i = 0; i < num_parameters; i++) {
+    const intptr_t parameter_index = (num_parameters - i);
+    Definition* value = builder->AddParameter(parameter_index);
+    Definition* unboxed_value =
+        builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false);
+    args->Add(new Value(unboxed_value));
+  }
+
+  Definition* unboxed_result = builder->InvokeMathCFunction(kind, args);
+
+  Definition* result = builder->AddDefinition(
+      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
+
+  builder->AddIntrinsicReturn(new Value(result));
+
+  return true;
+}
+
+bool GraphIntrinsifier::Build_MathSin(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathSin);
+}
+
+bool GraphIntrinsifier::Build_MathCos(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathCos);
+}
+
+bool GraphIntrinsifier::Build_MathTan(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathTan);
+}
+
+bool GraphIntrinsifier::Build_MathAsin(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAsin);
+}
+
+bool GraphIntrinsifier::Build_MathAcos(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAcos);
+}
+
+bool GraphIntrinsifier::Build_MathAtan(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan);
+}
+
+bool GraphIntrinsifier::Build_MathAtan2(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan2,
+                                  /* num_parameters = */ 2);
+}
+
+bool GraphIntrinsifier::Build_DoubleMod(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleMod,
+                                  /* num_parameters = */ 2);
+}
+
+bool GraphIntrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
+  // way.
+  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleCeil);
+}
+
+bool GraphIntrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
+  // way.
+  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleFloor);
+}
+
+bool GraphIntrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
+  // way.
+  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleTruncate);
+}
+
+bool GraphIntrinsifier::Build_DoubleRound(FlowGraph* flow_graph) {
+  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
+
+  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
+  auto normal_entry = graph_entry->normal_entry();
+  BlockBuilder builder(flow_graph, normal_entry);
+
+  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound);
+}
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // !defined(DART_PRECOMPILED_RUNTIME) && !defined(TARGET_ARCH_DBC)
diff --git a/runtime/vm/compiler/graph_intrinsifier.h b/runtime/vm/compiler/graph_intrinsifier.h
new file mode 100644
index 0000000..6282b58
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier.h
@@ -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.
+// Class for intrinsifying functions.
+
+#ifndef RUNTIME_VM_COMPILER_GRAPH_INTRINSIFIER_H_
+#define RUNTIME_VM_COMPILER_GRAPH_INTRINSIFIER_H_
+
+#include "vm/allocation.h"
+#include "vm/compiler/recognized_methods_list.h"
+
+namespace dart {
+
+// Forward declarations.
+class FlowGraphCompiler;
+class ParsedFunction;
+class FlowGraph;
+
+namespace compiler {
+class Assembler;
+class Label;
+
+#if !defined(TARGET_ARCH_DBC)
+
+class GraphIntrinsifier : public AllStatic {
+ public:
+  static intptr_t ParameterSlotFromSp();
+
+  static bool GraphIntrinsify(const ParsedFunction& parsed_function,
+                              FlowGraphCompiler* compiler);
+
+  static void IntrinsicCallPrologue(Assembler* assembler);
+  static void IntrinsicCallEpilogue(Assembler* assembler);
+
+ private:
+#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
+  static void enum_name(Assembler* assembler, Label* normal_ir_body);
+
+  // On DBC graph intrinsics are handled in the same way as non-graph ones.
+  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
+
+#undef DECLARE_FUNCTION
+
+#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
+  static bool Build_##enum_name(FlowGraph* flow_graph);
+
+  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
+
+#undef DECLARE_FUNCTION
+};
+
+#else  // !defined(TARGET_ARCH_DBC)
+
+class GraphIntrinsifier : public AllStatic {
+ public:
+  static bool GraphIntrinsify(const ParsedFunction& parsed_function,
+                              FlowGraphCompiler* compiler) {
+    return false;
+  }
+};
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_GRAPH_INTRINSIFIER_H_
diff --git a/runtime/vm/compiler/graph_intrinsifier_arm.cc b/runtime/vm/compiler/graph_intrinsifier_arm.cc
new file mode 100644
index 0000000..39b30c2
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier_arm.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM.
+#if defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/graph_intrinsifier.h"
+
+namespace dart {
+namespace compiler {
+
+#define __ assembler->
+
+intptr_t GraphIntrinsifier::ParameterSlotFromSp() {
+  return -1;
+}
+
+static bool IsABIPreservedRegister(Register reg) {
+  return ((1 << reg) & kAbiPreservedCpuRegs) != 0;
+}
+
+void GraphIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+  ASSERT(IsABIPreservedRegister(CODE_REG));
+  ASSERT(IsABIPreservedRegister(ARGS_DESC_REG));
+  ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
+
+  // Save LR by moving it to a callee saved temporary register.
+  assembler->Comment("IntrinsicCallPrologue");
+  assembler->mov(CALLEE_SAVED_TEMP, Operand(LR));
+}
+
+void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+  // Restore LR.
+  assembler->Comment("IntrinsicCallEpilogue");
+  assembler->mov(LR, Operand(CALLEE_SAVED_TEMP));
+}
+
+#undef __
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/graph_intrinsifier_arm64.cc b/runtime/vm/compiler/graph_intrinsifier_arm64.cc
new file mode 100644
index 0000000..0dc98a7
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier_arm64.cc
@@ -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.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_ARM64.
+#if defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/graph_intrinsifier.h"
+
+namespace dart {
+namespace compiler {
+
+#define __ assembler->
+
+intptr_t GraphIntrinsifier::ParameterSlotFromSp() {
+  return -1;
+}
+
+static bool IsABIPreservedRegister(Register reg) {
+  return ((1 << reg) & kAbiPreservedCpuRegs) != 0;
+}
+
+void GraphIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+  ASSERT(IsABIPreservedRegister(CODE_REG));
+  ASSERT(!IsABIPreservedRegister(ARGS_DESC_REG));
+  ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
+  ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP2));
+  ASSERT(CALLEE_SAVED_TEMP != CODE_REG);
+  ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
+  ASSERT(CALLEE_SAVED_TEMP2 != CODE_REG);
+  ASSERT(CALLEE_SAVED_TEMP2 != ARGS_DESC_REG);
+
+  assembler->Comment("IntrinsicCallPrologue");
+  assembler->mov(CALLEE_SAVED_TEMP, LR);
+  assembler->mov(CALLEE_SAVED_TEMP2, ARGS_DESC_REG);
+}
+
+void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+  assembler->Comment("IntrinsicCallEpilogue");
+  assembler->mov(LR, CALLEE_SAVED_TEMP);
+  assembler->mov(ARGS_DESC_REG, CALLEE_SAVED_TEMP2);
+}
+
+#undef __
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/graph_intrinsifier_ia32.cc b/runtime/vm/compiler/graph_intrinsifier_ia32.cc
new file mode 100644
index 0000000..e89c176
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier_ia32.cc
@@ -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.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_IA32.
+#if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/graph_intrinsifier.h"
+
+namespace dart {
+namespace compiler {
+
+#define __ assembler->
+
+intptr_t GraphIntrinsifier::ParameterSlotFromSp() {
+  return 0;
+}
+
+void GraphIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+  COMPILE_ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
+
+  assembler->Comment("IntrinsicCallPrologue");
+  assembler->movl(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
+}
+
+void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+  assembler->Comment("IntrinsicCallEpilogue");
+  assembler->movl(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
+}
+
+#undef __
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/graph_intrinsifier_x64.cc b/runtime/vm/compiler/graph_intrinsifier_x64.cc
new file mode 100644
index 0000000..46a8004
--- /dev/null
+++ b/runtime/vm/compiler/graph_intrinsifier_x64.cc
@@ -0,0 +1,45 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"  // Needed here to get TARGET_ARCH_X64.
+#if defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/graph_intrinsifier.h"
+
+namespace dart {
+namespace compiler {
+
+#define __ assembler->
+
+intptr_t GraphIntrinsifier::ParameterSlotFromSp() {
+  return 0;
+}
+
+static bool IsABIPreservedRegister(Register reg) {
+  return ((1 << reg) & CallingConventions::kCalleeSaveCpuRegisters) != 0;
+}
+
+void GraphIntrinsifier::IntrinsicCallPrologue(Assembler* assembler) {
+  ASSERT(IsABIPreservedRegister(CODE_REG));
+  ASSERT(!IsABIPreservedRegister(ARGS_DESC_REG));
+  ASSERT(IsABIPreservedRegister(CALLEE_SAVED_TEMP));
+  ASSERT(CALLEE_SAVED_TEMP != CODE_REG);
+  ASSERT(CALLEE_SAVED_TEMP != ARGS_DESC_REG);
+
+  assembler->Comment("IntrinsicCallPrologue");
+  assembler->movq(CALLEE_SAVED_TEMP, ARGS_DESC_REG);
+}
+
+void GraphIntrinsifier::IntrinsicCallEpilogue(Assembler* assembler) {
+  assembler->Comment("IntrinsicCallEpilogue");
+  assembler->movq(ARGS_DESC_REG, CALLEE_SAVED_TEMP);
+}
+
+#undef __
+
+}  // namespace compiler
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/intrinsifier.cc b/runtime/vm/compiler/intrinsifier.cc
index 3902dac..ee1649f 100644
--- a/runtime/vm/compiler/intrinsifier.cc
+++ b/runtime/vm/compiler/intrinsifier.cc
@@ -24,9 +24,8 @@
 
 DEFINE_FLAG(bool, intrinsify, true, "Instrinsify when possible");
 DEFINE_FLAG(bool, trace_intrinsifier, false, "Trace intrinsifier");
-DECLARE_FLAG(bool, code_comments);
-DECLARE_FLAG(bool, print_flow_graph);
-DECLARE_FLAG(bool, print_flow_graph_optimized);
+
+namespace compiler {
 
 bool Intrinsifier::CanIntrinsify(const Function& function) {
   if (FLAG_trace_intrinsifier) {
@@ -174,105 +173,6 @@
 }
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-// DBC does not use graph intrinsics.
-#if !defined(TARGET_ARCH_DBC)
-static void EmitCodeFor(FlowGraphCompiler* compiler, FlowGraph* graph) {
-  // The FlowGraph here is constructed by the intrinsics builder methods, and
-  // is different from compiler->flow_graph(), the original method's flow graph.
-  compiler->assembler()->Comment("Graph intrinsic begin");
-  for (intptr_t i = 0; i < graph->reverse_postorder().length(); i++) {
-    BlockEntryInstr* block = graph->reverse_postorder()[i];
-    if (block->IsGraphEntry()) continue;  // No code for graph entry needed.
-
-    if (block->HasParallelMove()) {
-      compiler->parallel_move_resolver()->EmitNativeCode(
-          block->parallel_move());
-    }
-
-    for (ForwardInstructionIterator it(block); !it.Done(); it.Advance()) {
-      Instruction* instr = it.Current();
-      if (FLAG_code_comments) compiler->EmitComment(instr);
-      if (instr->IsParallelMove()) {
-        compiler->parallel_move_resolver()->EmitNativeCode(
-            instr->AsParallelMove());
-      } else if (instr->IsInvokeMathCFunction()) {
-        ASSERT(instr->locs() != NULL);
-        Intrinsifier::IntrinsicCallPrologue(compiler->assembler());
-        instr->EmitNativeCode(compiler);
-        Intrinsifier::IntrinsicCallEpilogue(compiler->assembler());
-      } else {
-        ASSERT(instr->locs() != NULL);
-        // Calls are not supported in intrinsics code.
-        ASSERT(!instr->locs()->always_calls());
-        instr->EmitNativeCode(compiler);
-      }
-    }
-  }
-  compiler->assembler()->Comment("Graph intrinsic end");
-}
-#endif
-
-bool Intrinsifier::GraphIntrinsify(const ParsedFunction& parsed_function,
-                                   FlowGraphCompiler* compiler) {
-#if !defined(TARGET_ARCH_DBC)
-  ASSERT(!parsed_function.function().HasOptionalParameters());
-  PrologueInfo prologue_info(-1, -1);
-
-  auto graph_entry =
-      new GraphEntryInstr(parsed_function, Compiler::kNoOSRDeoptId);
-
-  intptr_t block_id = 1;  // 0 is GraphEntry.
-  graph_entry->set_normal_entry(
-      new FunctionEntryInstr(graph_entry, block_id, kInvalidTryIndex,
-                             CompilerState::Current().GetNextDeoptId()));
-
-  FlowGraph* graph =
-      new FlowGraph(parsed_function, graph_entry, block_id, prologue_info);
-  const Function& function = parsed_function.function();
-  switch (function.recognized_kind()) {
-#define EMIT_CASE(class_name, function_name, enum_name, fp)                    \
-  case MethodRecognizer::k##enum_name:                                         \
-    if (!Build_##enum_name(graph)) return false;                               \
-    break;
-
-    GRAPH_INTRINSICS_LIST(EMIT_CASE);
-    default:
-      return false;
-#undef EMIT_CASE
-  }
-
-  if (FLAG_support_il_printer && FLAG_print_flow_graph &&
-      FlowGraphPrinter::ShouldPrint(function)) {
-    THR_Print("Intrinsic graph before\n");
-    FlowGraphPrinter printer(*graph);
-    printer.PrintBlocks();
-  }
-
-  // Prepare for register allocation (cf. FinalizeGraph).
-  graph->RemoveRedefinitions();
-
-  // Ensure loop hierarchy has been computed.
-  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();
-
-  if (FLAG_support_il_printer && FLAG_print_flow_graph &&
-      FlowGraphPrinter::ShouldPrint(function)) {
-    THR_Print("Intrinsic graph after\n");
-    FlowGraphPrinter printer(*graph);
-    printer.PrintBlocks();
-  }
-  EmitCodeFor(compiler, graph);
-  return true;
-#else
-  return false;
-#endif  // !defined(TARGET_ARCH_DBC)
-}
-
 // Returns true if fall-through code can be omitted.
 bool Intrinsifier::Intrinsify(const ParsedFunction& parsed_function,
                               FlowGraphCompiler* compiler) {
@@ -282,7 +182,7 @@
   }
 
   ASSERT(!compiler->flow_graph().IsCompiledForOsr());
-  if (GraphIntrinsify(parsed_function, compiler)) {
+  if (GraphIntrinsifier::GraphIntrinsify(parsed_function, compiler)) {
     return compiler->intrinsic_slow_path_label()->IsUnused();
   }
 
@@ -308,7 +208,7 @@
     compiler->assembler()->Comment("Intrinsic");                               \
     Label normal_ir_body;                                                      \
     const auto size_before = compiler->assembler()->CodeSize();                \
-    enum_name(compiler->assembler(), &normal_ir_body);                         \
+    AsmIntrinsifier::enum_name(compiler->assembler(), &normal_ir_body);        \
     const auto size_after = compiler->assembler()->CodeSize();                 \
     if (size_before == size_after) return false;                               \
     if (!normal_ir_body.IsBound()) {                                           \
@@ -345,939 +245,7 @@
   return false;
 }
 
-#if !defined(TARGET_ARCH_DBC)
-static intptr_t CidForRepresentation(Representation rep) {
-  switch (rep) {
-    case kUnboxedDouble:
-      return kDoubleCid;
-    case kUnboxedFloat32x4:
-      return kFloat32x4Cid;
-    case kUnboxedInt32x4:
-      return kInt32x4Cid;
-    case kUnboxedFloat64x2:
-      return kFloat64x2Cid;
-    case kUnboxedUint32:
-      return kDynamicCid;  // smi or mint.
-    default:
-      UNREACHABLE();
-      return kIllegalCid;
-  }
-}
-
-static Representation RepresentationForCid(intptr_t cid) {
-  switch (cid) {
-    case kDoubleCid:
-      return kUnboxedDouble;
-    case kFloat32x4Cid:
-      return kUnboxedFloat32x4;
-    case kInt32x4Cid:
-      return kUnboxedInt32x4;
-    case kFloat64x2Cid:
-      return kUnboxedFloat64x2;
-    default:
-      UNREACHABLE();
-      return kNoRepresentation;
-  }
-}
-
-// Notes about the graph intrinsics:
-//
-// IR instructions which would jump to a deoptimization sequence on failure
-// instead branch to the intrinsic slow path.
-//
-class BlockBuilder : public ValueObject {
- public:
-  BlockBuilder(FlowGraph* flow_graph, BlockEntryInstr* entry)
-      : flow_graph_(flow_graph),
-        entry_(entry),
-        current_(entry),
-        fall_through_env_(new Environment(0,
-                                          0,
-                                          DeoptId::kNone,
-                                          flow_graph->parsed_function(),
-                                          NULL)) {}
-
-  Definition* AddToInitialDefinitions(Definition* def) {
-    def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
-    auto normal_entry = flow_graph_->graph_entry()->normal_entry();
-    flow_graph_->AddToInitialDefinitions(normal_entry, def);
-    return def;
-  }
-
-  Definition* AddDefinition(Definition* def) {
-    def->set_ssa_temp_index(flow_graph_->alloc_ssa_temp_index());
-    AddInstruction(def);
-    return def;
-  }
-
-  Instruction* AddInstruction(Instruction* instr) {
-    if (instr->ComputeCanDeoptimize()) {
-      // Since we use the presence of an environment to determine if an
-      // instructions can deoptimize, we need an empty environment for
-      // instructions that "deoptimize" to the intrinsic fall-through code.
-      instr->SetEnvironment(fall_through_env_);
-    }
-    current_ = current_->AppendInstruction(instr);
-    return instr;
-  }
-
-  void AddIntrinsicReturn(Value* value) {
-    ReturnInstr* instr = new ReturnInstr(
-        TokenPos(), value, CompilerState::Current().GetNextDeoptId());
-    AddInstruction(instr);
-    entry_->set_last_instruction(instr);
-  }
-
-  Definition* AddParameter(intptr_t index) {
-    intptr_t adjustment = Intrinsifier::ParameterSlotFromSp();
-    return AddToInitialDefinitions(new ParameterInstr(
-        adjustment + index, flow_graph_->graph_entry(), SPREG));
-  }
-
-  TokenPosition TokenPos() { return flow_graph_->function().token_pos(); }
-
-  Definition* AddNullDefinition() {
-    return AddDefinition(new ConstantInstr(Object::ZoneHandle(Object::null())));
-  }
-
-  Definition* AddUnboxInstr(Representation rep, Value* value, bool is_checked) {
-    Definition* unboxed_value =
-        AddDefinition(UnboxInstr::Create(rep, value, DeoptId::kNone));
-    if (is_checked) {
-      // The type of |value| has already been checked and it is safe to
-      // adjust reaching type. This is done manually because there is no type
-      // propagation when building intrinsics.
-      unboxed_value->AsUnbox()->value()->SetReachingType(
-          new CompileType(CompileType::FromCid(CidForRepresentation(rep))));
-    }
-    return unboxed_value;
-  }
-
-  Definition* AddUnboxInstr(Representation rep,
-                            Definition* boxed,
-                            bool is_checked) {
-    return AddUnboxInstr(rep, new Value(boxed), is_checked);
-  }
-
-  Definition* InvokeMathCFunction(MethodRecognizer::Kind recognized_kind,
-                                  ZoneGrowableArray<Value*>* args) {
-    return InvokeMathCFunctionHelper(recognized_kind, args);
-  }
-
- private:
-  Definition* InvokeMathCFunctionHelper(MethodRecognizer::Kind recognized_kind,
-                                        ZoneGrowableArray<Value*>* args) {
-    InvokeMathCFunctionInstr* invoke_math_c_function =
-        new InvokeMathCFunctionInstr(args, DeoptId::kNone, recognized_kind,
-                                     TokenPos());
-    AddDefinition(invoke_math_c_function);
-    return invoke_math_c_function;
-  }
-
-  FlowGraph* flow_graph_;
-  BlockEntryInstr* entry_;
-  Instruction* current_;
-  Environment* fall_through_env_;
-};
-
-static Definition* PrepareIndexedOp(FlowGraph* flow_graph,
-                                    BlockBuilder* builder,
-                                    Definition* array,
-                                    Definition* index,
-                                    const Slot& length_field) {
-  Definition* length = builder->AddDefinition(new LoadFieldInstr(
-      new Value(array), length_field, TokenPosition::kNoSource));
-  // Note that the intrinsifier must always use deopting array bound
-  // checks, because intrinsics currently don't support calls.
-  Definition* safe_index = new CheckArrayBoundInstr(
-      new Value(length), new Value(index), DeoptId::kNone);
-  builder->AddDefinition(safe_index);
-  return safe_index;
-}
-
-static bool IntrinsifyArrayGetIndexed(FlowGraph* flow_graph,
-                                      intptr_t array_cid) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* array = builder.AddParameter(2);
-
-  index = PrepareIndexedOp(flow_graph, &builder, array, index,
-                           Slot::GetLengthFieldForArrayCid(array_cid));
-
-  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    array = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(array), ExternalTypedData::data_offset()));
-  }
-
-  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
-      new Value(array), new Value(index),
-      Instance::ElementSizeFor(array_cid),  // index scale
-      array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  // Box and/or convert result if necessary.
-  switch (array_cid) {
-    case kTypedDataInt32ArrayCid:
-    case kExternalTypedDataInt32ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedInt32, new Value(result)));
-      break;
-    case kTypedDataUint32ArrayCid:
-    case kExternalTypedDataUint32ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedUint32, new Value(result)));
-      break;
-    case kTypedDataFloat32ArrayCid:
-      result = builder.AddDefinition(
-          new FloatToDoubleInstr(new Value(result), DeoptId::kNone));
-    // Fall through.
-    case kTypedDataFloat64ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedDouble, new Value(result)));
-      break;
-    case kTypedDataFloat32x4ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedFloat32x4, new Value(result)));
-      break;
-    case kTypedDataInt32x4ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedInt32x4, new Value(result)));
-      break;
-    case kTypedDataFloat64x2ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedFloat64x2, new Value(result)));
-      break;
-    case kArrayCid:
-    case kImmutableArrayCid:
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-      // Nothing to do.
-      break;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      result = builder.AddDefinition(
-          BoxInstr::Create(kUnboxedInt64, new Value(result)));
-      break;
-    default:
-      UNREACHABLE();
-      break;
-  }
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-static bool IntrinsifyArraySetIndexed(FlowGraph* flow_graph,
-                                      intptr_t array_cid) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  index = PrepareIndexedOp(flow_graph, &builder, array, index,
-                           Slot::GetLengthFieldForArrayCid(array_cid));
-
-  // Value check/conversion.
-  switch (array_cid) {
-    case kTypedDataInt8ArrayCid:
-    case kTypedDataUint8ArrayCid:
-    case kExternalTypedDataUint8ArrayCid:
-    case kTypedDataUint8ClampedArrayCid:
-    case kExternalTypedDataUint8ClampedArrayCid:
-    case kTypedDataInt16ArrayCid:
-    case kTypedDataUint16ArrayCid:
-      builder.AddInstruction(new CheckSmiInstr(new Value(value), DeoptId::kNone,
-                                               builder.TokenPos()));
-      break;
-    case kTypedDataInt32ArrayCid:
-    case kExternalTypedDataInt32ArrayCid:
-    // Use same truncating unbox-instruction for int32 and uint32.
-    // Fall-through.
-    case kTypedDataUint32ArrayCid:
-    case kExternalTypedDataUint32ArrayCid:
-      // Supports smi and mint, slow-case for bigints.
-      value = builder.AddUnboxInstr(kUnboxedUint32, new Value(value),
-                                    /* is_checked = */ false);
-      break;
-    case kTypedDataInt64ArrayCid:
-    case kTypedDataUint64ArrayCid:
-      value = builder.AddUnboxInstr(kUnboxedInt64, new Value(value),
-                                    /* is_checked = */ false);
-      break;
-
-    case kTypedDataFloat32ArrayCid:
-    case kTypedDataFloat64ArrayCid:
-    case kTypedDataFloat32x4ArrayCid:
-    case kTypedDataInt32x4ArrayCid:
-    case kTypedDataFloat64x2ArrayCid: {
-      intptr_t value_check_cid = kDoubleCid;
-      Representation rep = kUnboxedDouble;
-      switch (array_cid) {
-        case kTypedDataFloat32x4ArrayCid:
-          value_check_cid = kFloat32x4Cid;
-          rep = kUnboxedFloat32x4;
-          break;
-        case kTypedDataInt32x4ArrayCid:
-          value_check_cid = kInt32x4Cid;
-          rep = kUnboxedInt32x4;
-          break;
-        case kTypedDataFloat64x2ArrayCid:
-          value_check_cid = kFloat64x2Cid;
-          rep = kUnboxedFloat64x2;
-          break;
-        default:
-          // Float32/Float64 case already handled.
-          break;
-      }
-      Zone* zone = flow_graph->zone();
-      Cids* value_check = Cids::CreateMonomorphic(zone, value_check_cid);
-      builder.AddInstruction(new CheckClassInstr(
-          new Value(value), DeoptId::kNone, *value_check, builder.TokenPos()));
-      value = builder.AddUnboxInstr(rep, new Value(value),
-                                    /* is_checked = */ true);
-      if (array_cid == kTypedDataFloat32ArrayCid) {
-        value = builder.AddDefinition(
-            new DoubleToFloatInstr(new Value(value), DeoptId::kNone));
-      }
-      break;
-    }
-    default:
-      UNREACHABLE();
-  }
-
-  if (RawObject::IsExternalTypedDataClassId(array_cid)) {
-    array = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(array), ExternalTypedData::data_offset()));
-  }
-  // No store barrier.
-  ASSERT(RawObject::IsExternalTypedDataClassId(array_cid) ||
-         RawObject::IsTypedDataClassId(array_cid));
-  builder.AddInstruction(new StoreIndexedInstr(
-      new Value(array), new Value(index), new Value(value), kNoStoreBarrier,
-      Instance::ElementSizeFor(array_cid),  // index scale
-      array_cid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-#define DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                               \
-  bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) {    \
-    return IntrinsifyArrayGetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##GetIndexed));          \
-  }
-
-#define DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)                               \
-  bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) {    \
-    return IntrinsifyArraySetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##SetIndexed));          \
-  }
-
-DEFINE_ARRAY_GETTER_INTRINSIC(ObjectArray)
-DEFINE_ARRAY_GETTER_INTRINSIC(ImmutableArray)
-
-#define DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                       \
-  DEFINE_ARRAY_GETTER_INTRINSIC(enum_name)                                     \
-  DEFINE_ARRAY_SETTER_INTRINSIC(enum_name)
-
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int8Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint8ClampedArray)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(ExternalUint8ClampedArray)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int16Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint16Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int32Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint32Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Int64Array)
-DEFINE_ARRAY_GETTER_SETTER_INTRINSICS(Uint64Array)
-
-#undef DEFINE_ARRAY_GETTER_SETTER_INTRINSICS
-#undef DEFINE_ARRAY_GETTER_INTRINSIC
-#undef DEFINE_ARRAY_SETTER_INTRINSIC
-
-#define DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                         \
-  bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) {    \
-    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                        \
-      return false;                                                            \
-    }                                                                          \
-    return IntrinsifyArrayGetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##GetIndexed));          \
-  }
-
-#define DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)                         \
-  bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) {    \
-    if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {                        \
-      return false;                                                            \
-    }                                                                          \
-    return IntrinsifyArraySetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##SetIndexed));          \
-  }
-
-#define DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                 \
-  DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC(enum_name)                               \
-  DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC(enum_name)
-
-DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float64Array)
-DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS(Float32Array)
-
-#undef DEFINE_FLOAT_ARRAY_GETTER_SETTER_INTRINSICS
-#undef DEFINE_FLOAT_ARRAY_GETTER_INTRINSIC
-#undef DEFINE_FLOAT_ARRAY_SETTER_INTRINSIC
-
-#define DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name)                          \
-  bool Intrinsifier::Build_##enum_name##GetIndexed(FlowGraph* flow_graph) {    \
-    if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {                        \
-      return false;                                                            \
-    }                                                                          \
-    return IntrinsifyArrayGetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##GetIndexed));          \
-  }
-
-#define DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)                          \
-  bool Intrinsifier::Build_##enum_name##SetIndexed(FlowGraph* flow_graph) {    \
-    if (!FlowGraphCompiler::SupportsUnboxedSimd128()) {                        \
-      return false;                                                            \
-    }                                                                          \
-    return IntrinsifyArraySetIndexed(                                          \
-        flow_graph, MethodRecognizer::MethodKindToReceiverCid(                 \
-                        MethodRecognizer::k##enum_name##SetIndexed));          \
-  }
-
-#define DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(enum_name)                  \
-  DEFINE_SIMD_ARRAY_GETTER_INTRINSIC(enum_name)                                \
-  DEFINE_SIMD_ARRAY_SETTER_INTRINSIC(enum_name)
-
-DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float32x4Array)
-DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Int32x4Array)
-DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS(Float64x2Array)
-
-#undef DEFINE_SIMD_ARRAY_GETTER_SETTER_INTRINSICS
-#undef DEFINE_SIMD_ARRAY_GETTER_INTRINSIC
-#undef DEFINE_SIMD_ARRAY_SETTER_INTRINSIC
-
-static bool BuildCodeUnitAt(FlowGraph* flow_graph, intptr_t cid) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* str = builder.AddParameter(2);
-
-  index =
-      PrepareIndexedOp(flow_graph, &builder, str, index, Slot::String_length());
-
-  // For external strings: Load external data.
-  if (cid == kExternalOneByteStringCid) {
-    str = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(str), ExternalOneByteString::external_data_offset()));
-  } else if (cid == kExternalTwoByteStringCid) {
-    str = builder.AddDefinition(new LoadUntaggedInstr(
-        new Value(str), ExternalTwoByteString::external_data_offset()));
-  }
-
-  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
-      new Value(str), new Value(index), Instance::ElementSizeFor(cid), cid,
-      kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-bool Intrinsifier::Build_OneByteStringCodeUnitAt(FlowGraph* flow_graph) {
-  return BuildCodeUnitAt(flow_graph, kOneByteStringCid);
-}
-
-bool Intrinsifier::Build_TwoByteStringCodeUnitAt(FlowGraph* flow_graph) {
-  return BuildCodeUnitAt(flow_graph, kTwoByteStringCid);
-}
-
-bool Intrinsifier::Build_ExternalOneByteStringCodeUnitAt(
-    FlowGraph* flow_graph) {
-  return BuildCodeUnitAt(flow_graph, kExternalOneByteStringCid);
-}
-
-bool Intrinsifier::Build_ExternalTwoByteStringCodeUnitAt(
-    FlowGraph* flow_graph) {
-  return BuildCodeUnitAt(flow_graph, kExternalTwoByteStringCid);
-}
-
-static bool BuildSimdOp(FlowGraph* flow_graph, intptr_t cid, Token::Kind kind) {
-  if (!FlowGraphCompiler::SupportsUnboxedSimd128()) return false;
-
-  const Representation rep = RepresentationForCid(cid);
-
-  Zone* zone = flow_graph->zone();
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* right = builder.AddParameter(1);
-  Definition* left = builder.AddParameter(2);
-
-  Cids* value_check = Cids::CreateMonomorphic(zone, cid);
-  // Check argument. Receiver (left) is known to be a Float32x4.
-  builder.AddInstruction(new CheckClassInstr(new Value(right), DeoptId::kNone,
-                                             *value_check, builder.TokenPos()));
-  Definition* left_simd = builder.AddUnboxInstr(rep, new Value(left),
-                                                /* is_checked = */ true);
-
-  Definition* right_simd = builder.AddUnboxInstr(rep, new Value(right),
-                                                 /* is_checked = */ true);
-
-  Definition* unboxed_result = builder.AddDefinition(SimdOpInstr::Create(
-      SimdOpInstr::KindForOperator(cid, kind), new Value(left_simd),
-      new Value(right_simd), DeoptId::kNone));
-  Definition* result =
-      builder.AddDefinition(BoxInstr::Create(rep, new Value(unboxed_result)));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-bool Intrinsifier::Build_Float32x4Mul(FlowGraph* flow_graph) {
-  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kMUL);
-}
-
-bool Intrinsifier::Build_Float32x4Sub(FlowGraph* flow_graph) {
-  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kSUB);
-}
-
-bool Intrinsifier::Build_Float32x4Add(FlowGraph* flow_graph) {
-  return BuildSimdOp(flow_graph, kFloat32x4Cid, Token::kADD);
-}
-
-static bool BuildFloat32x4Shuffle(FlowGraph* flow_graph,
-                                  MethodRecognizer::Kind kind) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles() ||
-      !FlowGraphCompiler::SupportsUnboxedSimd128()) {
-    return false;
-  }
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* receiver = builder.AddParameter(1);
-
-  Definition* unboxed_receiver =
-      builder.AddUnboxInstr(kUnboxedFloat32x4, new Value(receiver),
-                            /* is_checked = */ true);
-
-  Definition* unboxed_result = builder.AddDefinition(
-      SimdOpInstr::Create(kind, new Value(unboxed_receiver), DeoptId::kNone));
-
-  Definition* result = builder.AddDefinition(
-      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-bool Intrinsifier::Build_Float32x4ShuffleX(FlowGraph* flow_graph) {
-  return BuildFloat32x4Shuffle(flow_graph,
-                               MethodRecognizer::kFloat32x4ShuffleX);
-}
-
-bool Intrinsifier::Build_Float32x4ShuffleY(FlowGraph* flow_graph) {
-  return BuildFloat32x4Shuffle(flow_graph,
-                               MethodRecognizer::kFloat32x4ShuffleY);
-}
-
-bool Intrinsifier::Build_Float32x4ShuffleZ(FlowGraph* flow_graph) {
-  return BuildFloat32x4Shuffle(flow_graph,
-                               MethodRecognizer::kFloat32x4ShuffleZ);
-}
-
-bool Intrinsifier::Build_Float32x4ShuffleW(FlowGraph* flow_graph) {
-  return BuildFloat32x4Shuffle(flow_graph,
-                               MethodRecognizer::kFloat32x4ShuffleW);
-}
-
-static bool BuildLoadField(FlowGraph* flow_graph, const Slot& field) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* array = builder.AddParameter(1);
-
-  Definition* length = builder.AddDefinition(
-      new LoadFieldInstr(new Value(array), field, builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(length));
-  return true;
-}
-
-bool Intrinsifier::Build_ObjectArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Slot::Array_length());
-}
-
-bool Intrinsifier::Build_ImmutableArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Slot::Array_length());
-}
-
-bool Intrinsifier::Build_GrowableArrayLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Slot::GrowableObjectArray_length());
-}
-
-bool Intrinsifier::Build_StringBaseLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Slot::String_length());
-}
-
-bool Intrinsifier::Build_TypedDataLength(FlowGraph* flow_graph) {
-  return BuildLoadField(flow_graph, Slot::TypedData_length());
-}
-
-bool Intrinsifier::Build_GrowableArrayCapacity(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* array = builder.AddParameter(1);
-
-  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
-      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
-  Definition* capacity = builder.AddDefinition(new LoadFieldInstr(
-      new Value(backing_store), Slot::Array_length(), builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(capacity));
-  return true;
-}
-
-bool Intrinsifier::Build_GrowableArrayGetIndexed(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* index = builder.AddParameter(1);
-  Definition* growable_array = builder.AddParameter(2);
-
-  index = PrepareIndexedOp(flow_graph, &builder, growable_array, index,
-                           Slot::GrowableObjectArray_length());
-
-  Definition* backing_store = builder.AddDefinition(
-      new LoadFieldInstr(new Value(growable_array),
-                         Slot::GrowableObjectArray_data(), builder.TokenPos()));
-  Definition* result = builder.AddDefinition(new LoadIndexedInstr(
-      new Value(backing_store), new Value(index),
-      Instance::ElementSizeFor(kArrayCid),  // index scale
-      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-bool Intrinsifier::Build_ObjectArraySetIndexed(FlowGraph* flow_graph) {
-  if (Isolate::Current()->argument_type_checks()) {
-    return false;
-  }
-
-  return Build_ObjectArraySetIndexedUnchecked(flow_graph);
-}
-
-bool Intrinsifier::Build_ObjectArraySetIndexedUnchecked(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  index = PrepareIndexedOp(flow_graph, &builder, array, index,
-                           Slot::Array_length());
-
-  builder.AddInstruction(new StoreIndexedInstr(
-      new Value(array), new Value(index), new Value(value), kEmitStoreBarrier,
-      Instance::ElementSizeFor(kArrayCid),  // index scale
-      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-bool Intrinsifier::Build_GrowableArraySetIndexed(FlowGraph* flow_graph) {
-  if (Isolate::Current()->argument_type_checks()) {
-    return false;
-  }
-
-  return Build_GrowableArraySetIndexedUnchecked(flow_graph);
-}
-
-bool Intrinsifier::Build_GrowableArraySetIndexedUnchecked(
-    FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* value = builder.AddParameter(1);
-  Definition* index = builder.AddParameter(2);
-  Definition* array = builder.AddParameter(3);
-
-  index = PrepareIndexedOp(flow_graph, &builder, array, index,
-                           Slot::GrowableObjectArray_length());
-
-  Definition* backing_store = builder.AddDefinition(new LoadFieldInstr(
-      new Value(array), Slot::GrowableObjectArray_data(), builder.TokenPos()));
-
-  builder.AddInstruction(new StoreIndexedInstr(
-      new Value(backing_store), new Value(index), new Value(value),
-      kEmitStoreBarrier,
-      Instance::ElementSizeFor(kArrayCid),  // index scale
-      kArrayCid, kAlignedAccess, DeoptId::kNone, builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-bool Intrinsifier::Build_GrowableArraySetData(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* data = builder.AddParameter(1);
-  Definition* growable_array = builder.AddParameter(2);
-  Zone* zone = flow_graph->zone();
-
-  Cids* value_check = Cids::CreateMonomorphic(zone, kArrayCid);
-  builder.AddInstruction(new CheckClassInstr(new Value(data), DeoptId::kNone,
-                                             *value_check, builder.TokenPos()));
-
-  builder.AddInstruction(new StoreInstanceFieldInstr(
-      Slot::GrowableObjectArray_data(), new Value(growable_array),
-      new Value(data), kEmitStoreBarrier, builder.TokenPos()));
-  // Return null.
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-bool Intrinsifier::Build_GrowableArraySetLength(FlowGraph* flow_graph) {
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* length = builder.AddParameter(1);
-  Definition* growable_array = builder.AddParameter(2);
-
-  builder.AddInstruction(
-      new CheckSmiInstr(new Value(length), DeoptId::kNone, builder.TokenPos()));
-  builder.AddInstruction(new StoreInstanceFieldInstr(
-      Slot::GrowableObjectArray_length(), new Value(growable_array),
-      new Value(length), kNoStoreBarrier, builder.TokenPos()));
-  Definition* null_def = builder.AddNullDefinition();
-  builder.AddIntrinsicReturn(new Value(null_def));
-  return true;
-}
-
-bool Intrinsifier::Build_DoubleFlipSignBit(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
-    return false;
-  }
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  Definition* receiver = builder.AddParameter(1);
-  Definition* unboxed_value =
-      builder.AddUnboxInstr(kUnboxedDouble, new Value(receiver),
-                            /* is_checked = */ true);
-  Definition* unboxed_result = builder.AddDefinition(new UnaryDoubleOpInstr(
-      Token::kNEGATE, new Value(unboxed_value), DeoptId::kNone));
-  Definition* result = builder.AddDefinition(
-      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
-  builder.AddIntrinsicReturn(new Value(result));
-  return true;
-}
-
-static bool BuildInvokeMathCFunction(BlockBuilder* builder,
-                                     MethodRecognizer::Kind kind,
-                                     intptr_t num_parameters = 1) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) {
-    return false;
-  }
-  ZoneGrowableArray<Value*>* args =
-      new ZoneGrowableArray<Value*>(num_parameters);
-
-  for (intptr_t i = 0; i < num_parameters; i++) {
-    const intptr_t parameter_index = (num_parameters - i);
-    Definition* value = builder->AddParameter(parameter_index);
-    Definition* unboxed_value =
-        builder->AddUnboxInstr(kUnboxedDouble, value, /* is_checked = */ false);
-    args->Add(new Value(unboxed_value));
-  }
-
-  Definition* unboxed_result = builder->InvokeMathCFunction(kind, args);
-
-  Definition* result = builder->AddDefinition(
-      BoxInstr::Create(kUnboxedDouble, new Value(unboxed_result)));
-
-  builder->AddIntrinsicReturn(new Value(result));
-
-  return true;
-}
-
-bool Intrinsifier::Build_MathSin(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathSin);
-}
-
-bool Intrinsifier::Build_MathCos(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathCos);
-}
-
-bool Intrinsifier::Build_MathTan(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathTan);
-}
-
-bool Intrinsifier::Build_MathAsin(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAsin);
-}
-
-bool Intrinsifier::Build_MathAcos(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAcos);
-}
-
-bool Intrinsifier::Build_MathAtan(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan);
-}
-
-bool Intrinsifier::Build_MathAtan2(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kMathAtan2,
-                                  /* num_parameters = */ 2);
-}
-
-bool Intrinsifier::Build_DoubleMod(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleMod,
-                                  /* num_parameters = */ 2);
-}
-
-bool Intrinsifier::Build_DoubleCeil(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
-  // way.
-  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleCeil);
-}
-
-bool Intrinsifier::Build_DoubleFloor(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
-  // way.
-  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleFloor);
-}
-
-bool Intrinsifier::Build_DoubleTruncate(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-  // TODO(johnmccutchan): On X86 this intrinsic can be written in a different
-  // way.
-  if (TargetCPUFeatures::double_truncate_round_supported()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleTruncate);
-}
-
-bool Intrinsifier::Build_DoubleRound(FlowGraph* flow_graph) {
-  if (!FlowGraphCompiler::SupportsUnboxedDoubles()) return false;
-
-  GraphEntryInstr* graph_entry = flow_graph->graph_entry();
-  auto normal_entry = graph_entry->normal_entry();
-  BlockBuilder builder(flow_graph, normal_entry);
-
-  return BuildInvokeMathCFunction(&builder, MethodRecognizer::kDoubleRound);
-}
-
-void Intrinsifier::String_identityHash(Assembler* assembler,
-                                       Label* normal_ir_body) {
-  String_getHashCode(assembler, normal_ir_body);
-}
-
-void Intrinsifier::Double_identityHash(Assembler* assembler,
-                                       Label* normal_ir_body) {
-  Double_hashCode(assembler, normal_ir_body);
-}
-
-void Intrinsifier::RegExp_ExecuteMatch(Assembler* assembler,
-                                       Label* normal_ir_body) {
-  IntrinsifyRegExpExecuteMatch(assembler, normal_ir_body, /*sticky=*/false);
-}
-
-void Intrinsifier::RegExp_ExecuteMatchSticky(Assembler* assembler,
-                                             Label* normal_ir_body) {
-  IntrinsifyRegExpExecuteMatch(assembler, normal_ir_body, /*sticky=*/true);
-}
-#endif  // !defined(TARGET_ARCH_DBC)
-
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/intrinsifier.h b/runtime/vm/compiler/intrinsifier.h
index 694518e..3aa9148 100644
--- a/runtime/vm/compiler/intrinsifier.h
+++ b/runtime/vm/compiler/intrinsifier.h
@@ -7,23 +7,20 @@
 #define RUNTIME_VM_COMPILER_INTRINSIFIER_H_
 
 #include "vm/allocation.h"
+#include "vm/compiler/asm_intrinsifier.h"
+#include "vm/compiler/graph_intrinsifier.h"
 #include "vm/compiler/method_recognizer.h"
 
 namespace dart {
 
 // Forward declarations.
+class FlowGraphCompiler;
+class Function;
+class ParsedFunction;
+
 namespace compiler {
 class Assembler;
 class Label;
-}  // namespace compiler
-class FlowGraphCompiler;
-class Function;
-class TargetEntryInstr;
-class ParsedFunction;
-class FlowGraph;
-
-using compiler::Assembler;
-using compiler::Label;
 
 class Intrinsifier : public AllStatic {
  public:
@@ -33,46 +30,11 @@
   static void InitializeState();
 #endif
 
-  static bool GraphIntrinsify(const ParsedFunction& parsed_function,
-                              FlowGraphCompiler* compiler);
-
-  static intptr_t ParameterSlotFromSp();
-
-  static void IntrinsicCallPrologue(Assembler* assembler);
-  static void IntrinsicCallEpilogue(Assembler* assembler);
-
  private:
-  // The "_A" value used in the intrinsification of
-  // `runtime/lib/math_patch.dart:_Random._nextState()`
-  static const int64_t kRandomAValue = 0xffffda61;
-
   static bool CanIntrinsify(const Function& function);
-
-#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
-  static void enum_name(Assembler* assembler, Label* normal_ir_body);
-
-  ALL_INTRINSICS_LIST(DECLARE_FUNCTION)
-#if defined(TARGET_ARCH_DBC)
-  // On DBC graph intrinsics are handled in the same way as non-graph ones.
-  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
-#endif
-
-#undef DECLARE_FUNCTION
-
-#if !defined(TARGET_ARCH_DBC)
-#define DECLARE_FUNCTION(class_name, function_name, enum_name, fp)             \
-  static bool Build_##enum_name(FlowGraph* flow_graph);
-
-  GRAPH_INTRINSICS_LIST(DECLARE_FUNCTION)
-
-#undef DECLARE_FUNCTION
-
-  static void IntrinsifyRegExpExecuteMatch(Assembler* assembler,
-                                           Label* normal_ir_body,
-                                           bool sticky);
-#endif
 };
 
+}  // namespace compiler
 }  // namespace dart
 
 #endif  // RUNTIME_VM_COMPILER_INTRINSIFIER_H_
diff --git a/runtime/vm/compiler/jit/compiler.cc b/runtime/vm/compiler/jit/compiler.cc
index 6a8dbc1..66292fa 100644
--- a/runtime/vm/compiler/jit/compiler.cc
+++ b/runtime/vm/compiler/jit/compiler.cc
@@ -103,6 +103,9 @@
     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
+    FLAG_enable_ffi = false;
     FLAG_fields_may_be_reset = true;
     FLAG_interpret_irregexp = true;
     FLAG_lazy_dispatchers = false;
@@ -700,6 +703,19 @@
           }
         }
       }
+      if (!result->IsNull()) {
+#if !defined(PRODUCT)
+        if (!function.HasOptimizedCode()) {
+          isolate()->debugger()->NotifyCompilation(function);
+        }
+#endif
+        if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
+          Disassembler::DisassembleCode(function, *result, optimized());
+        } else if (FLAG_disassemble_optimized && optimized() &&
+                   FlowGraphPrinter::ShouldPrint(function)) {
+          Disassembler::DisassembleCode(function, *result, true);
+        }
+      }
       // Exit the loop and the function with the correct result value.
       done = true;
     } else {
@@ -874,17 +890,6 @@
                 per_compile_timer.TotalElapsedTime());
     }
 
-#if !defined(PRODUCT)
-    isolate->debugger()->NotifyCompilation(function);
-#endif
-
-    if (FLAG_disassemble && FlowGraphPrinter::ShouldPrint(function)) {
-      Disassembler::DisassembleCode(function, result, optimized);
-    } else if (FLAG_disassemble_optimized && optimized &&
-               FlowGraphPrinter::ShouldPrint(function)) {
-      Disassembler::DisassembleCode(function, result, true);
-    }
-
     return result.raw();
   } else {
     Thread* const thread = Thread::Current();
@@ -1193,9 +1198,10 @@
     ASSERT(thread->IsMutatorThread());
     NoOOBMessageScope no_msg_scope(thread);
     NoReloadScope no_reload_scope(thread->isolate(), thread);
-    // Under lazy compilation initializer has not yet been created, so create
-    // it now, but don't bother remembering it because it won't be used again.
-    ASSERT(!field.HasPrecompiledInitializer());
+    if (field.HasInitializer()) {
+      const Function& initializer = Function::Handle(field.Initializer());
+      return DartEntry::InvokeFunction(initializer, Object::empty_array());
+    }
     {
 #if defined(SUPPORT_TIMELINE)
       VMTagScope tagScope(thread, VMTag::kCompileUnoptimizedTagId);
@@ -1698,9 +1704,8 @@
 }
 
 RawObject* Compiler::EvaluateStaticInitializer(const Field& field) {
-  ASSERT(field.HasPrecompiledInitializer());
-  const Function& initializer =
-      Function::Handle(field.PrecompiledInitializer());
+  ASSERT(field.HasInitializer());
+  const Function& initializer = Function::Handle(field.Initializer());
   return DartEntry::InvokeFunction(initializer, Object::empty_array());
 }
 
diff --git a/runtime/vm/compiler/method_recognizer.h b/runtime/vm/compiler/method_recognizer.h
index 75ceb07..dbde9de 100644
--- a/runtime/vm/compiler/method_recognizer.h
+++ b/runtime/vm/compiler/method_recognizer.h
@@ -6,519 +6,12 @@
 #define RUNTIME_VM_COMPILER_METHOD_RECOGNIZER_H_
 
 #include "vm/allocation.h"
+#include "vm/compiler/recognized_methods_list.h"
 #include "vm/growable_array.h"
 #include "vm/token.h"
 
 namespace dart {
 
-// clang-format off
-// (class-name, function-name, recognized enum, result type, fingerprint).
-// When adding a new function add a 0 as fingerprint, build and run to get the
-// correct fingerprint from the mismatch error (or use Library::GetFunction()
-// and print func.SourceFingerprint()).
-#define OTHER_RECOGNIZED_LIST(V)                                               \
-  V(::, identical, ObjectIdentical, 0x49c6e96a)                                \
-  V(ClassID, getID, ClassIDgetID, 0x7b18b257)                                  \
-  V(Object, Object., ObjectConstructor, 0x681617fe)                            \
-  V(List, ., ListFactory, 0x629f8324)                                          \
-  V(_List, ., ObjectArrayAllocate, 0x2121902f)                                 \
-  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
-  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
-  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
-  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
-  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
-  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
-  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, 0x7db75d78)                  \
-  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, 0x1487cfc6)                \
-  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
-  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
-  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
-  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
-  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x12bae36a)                    \
-  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 0x15821cc9)                  \
-  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x1f8237fa)                  \
-  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 0x181e5d16)                \
-  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x7ddb9f87)                  \
-  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74094f8d)                \
-  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, 0x4741396e)                  \
-  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, 0x3b398ae4)                \
-  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x03db087b)              \
-  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
-  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
-  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
-  V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435)                 \
-  V(_StringBase, _interpolate, StringBaseInterpolate, 0x01ecb15a)              \
-  V(_IntegerImplementation, toDouble, IntegerToDouble, 0x05da96ed)             \
-  V(_Double, _add, DoubleAdd, 0x2a38277b)                                      \
-  V(_Double, _sub, DoubleSub, 0x4f466391)                                      \
-  V(_Double, _mul, DoubleMul, 0x175e4f66)                                      \
-  V(_Double, _div, DoubleDiv, 0x0854181b)                                      \
-  V(::, min, MathMin, 0x32ebc57d)                                              \
-  V(::, max, MathMax, 0x377e8889)                                              \
-  V(::, _doublePow, MathDoublePow, 0x5add0ec1)                                 \
-  V(::, _intPow, MathIntPow, 0x11b45569)                                       \
-  V(Float32x4, Float32x4., Float32x4Constructor, 0x26ea459b)                   \
-  V(Float32x4, Float32x4.zero, Float32x4Zero, 0x16eca604)                      \
-  V(Float32x4, Float32x4.splat, Float32x4Splat, 0x694e83e3)                    \
-  V(Float32x4, Float32x4.fromInt32x4Bits, Int32x4ToFloat32x4, 0x2f62ebd3)      \
-  V(Float32x4, Float32x4.fromFloat64x2, Float64x2ToFloat32x4, 0x50ed6910)      \
-  V(_Float32x4, shuffle, Float32x4Shuffle, 0x7829101f)                         \
-  V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 0x4182c06b)                   \
-  V(_Float32x4, get:signMask, Float32x4GetSignMask, 0x1d08b351)                \
-  V(_Float32x4, equal, Float32x4Equal, 0x11adb239)                             \
-  V(_Float32x4, greaterThan, Float32x4GreaterThan, 0x48adaf58)                 \
-  V(_Float32x4, greaterThanOrEqual, Float32x4GreaterThanOrEqual, 0x32db94ca)   \
-  V(_Float32x4, lessThan, Float32x4LessThan, 0x425b000c)                       \
-  V(_Float32x4, lessThanOrEqual, Float32x4LessThanOrEqual, 0x0278c2f8)         \
-  V(_Float32x4, notEqual, Float32x4NotEqual, 0x2987cd26)                       \
-  V(_Float32x4, min, Float32x4Min, 0x5ed74b6f)                                 \
-  V(_Float32x4, max, Float32x4Max, 0x68696442)                                 \
-  V(_Float32x4, scale, Float32x4Scale, 0x704e4122)                             \
-  V(_Float32x4, sqrt, Float32x4Sqrt, 0x2c967a6f)                               \
-  V(_Float32x4, reciprocalSqrt, Float32x4ReciprocalSqrt, 0x6264bfe8)           \
-  V(_Float32x4, reciprocal, Float32x4Reciprocal, 0x3cd7e819)                   \
-  V(_Float32x4, unary-, Float32x4Negate, 0x37accb52)                           \
-  V(_Float32x4, abs, Float32x4Abs, 0x471cdd87)                                 \
-  V(_Float32x4, clamp, Float32x4Clamp, 0x2cb30492)                             \
-  V(_Float32x4, withX, Float32x4WithX, 0x4e336aff)                             \
-  V(_Float32x4, withY, Float32x4WithY, 0x0a72b910)                             \
-  V(_Float32x4, withZ, Float32x4WithZ, 0x31e93658)                             \
-  V(_Float32x4, withW, Float32x4WithW, 0x60ddc105)                             \
-  V(Float64x2, Float64x2., Float64x2Constructor, 0x43054b9f)                   \
-  V(Float64x2, Float64x2.zero, Float64x2Zero, 0x4af12f9d)                      \
-  V(Float64x2, Float64x2.splat, Float64x2Splat, 0x134edef0)                    \
-  V(Float64x2, Float64x2.fromFloat32x4, Float32x4ToFloat64x2, 0x17d6b5e4)      \
-  V(_Float64x2, get:x, Float64x2GetX, 0x58c09c58)                              \
-  V(_Float64x2, get:y, Float64x2GetY, 0x3cf5e5b8)                              \
-  V(_Float64x2, unary-, Float64x2Negate, 0x415ca009)                           \
-  V(_Float64x2, abs, Float64x2Abs, 0x031f9e47)                                 \
-  V(_Float64x2, sqrt, Float64x2Sqrt, 0x77f711dd)                               \
-  V(_Float64x2, get:signMask, Float64x2GetSignMask, 0x27deda4b)                \
-  V(_Float64x2, scale, Float64x2Scale, 0x26830a61)                             \
-  V(_Float64x2, withX, Float64x2WithX, 0x1d2bcaf5)                             \
-  V(_Float64x2, withY, Float64x2WithY, 0x383ed6ac)                             \
-  V(_Float64x2, min, Float64x2Min,  0x28d7ddf6)                                \
-  V(_Float64x2, max, Float64x2Max,  0x0bd74e5b)                                \
-  V(Int32x4, Int32x4., Int32x4Constructor, 0x480555a9)                         \
-  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 0x36aa6963)                 \
-  V(Int32x4, Int32x4.fromFloat32x4Bits, Float32x4ToInt32x4, 0x6715388a)        \
-  V(_Int32x4, get:flagX, Int32x4GetFlagX, 0x56396c82)                          \
-  V(_Int32x4, get:flagY, Int32x4GetFlagY, 0x44704738)                          \
-  V(_Int32x4, get:flagZ, Int32x4GetFlagZ, 0x20d6ff37)                          \
-  V(_Int32x4, get:flagW, Int32x4GetFlagW, 0x5045616a)                          \
-  V(_Int32x4, get:signMask, Int32x4GetSignMask, 0x2c1fb2a3)                    \
-  V(_Int32x4, shuffle, Int32x4Shuffle, 0x20bc0b16)                             \
-  V(_Int32x4, shuffleMix, Int32x4ShuffleMix, 0x5c7056e1)                       \
-  V(_Int32x4, select, Int32x4Select, 0x6b49654f)                               \
-  V(_Int32x4, withFlagX, Int32x4WithFlagX, 0x0ef58fcf)                         \
-  V(_Int32x4, withFlagY, Int32x4WithFlagY, 0x6485a9c4)                         \
-  V(_Int32x4, withFlagZ, Int32x4WithFlagZ, 0x267acdfa)                         \
-  V(_Int32x4, withFlagW, Int32x4WithFlagW, 0x345ac675)                         \
-  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
-  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
-  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac)                 \
-  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x0ec032e8)                 \
-  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x088599ed)         \
-  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x5f42ca86)         \
-  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f3b13b)         \
-  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x7219c45b)         \
-  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2)   \
-  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d)   \
-  V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84)                         \
-  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75)          \
-
-
-// List of intrinsics:
-// (class-name, function-name, intrinsification method, fingerprint).
-#define CORE_LIB_INTRINSIC_LIST(V)                                             \
-  V(_Smi, ~, Smi_bitNegate, 0x67299f4f)                                        \
-  V(_Smi, get:bitLength, Smi_bitLength, 0x25b3cb0a)                            \
-  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, 0x562d5047)                       \
-  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
-  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
-  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
-  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
-  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
-  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
-  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit,         \
-    0x35456d91)                                                                \
-  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
-  V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
-  V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
-  V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
-  V(_Double, <=, Double_lessEqualThan, 0x74b5eb64)                             \
-  V(_Double, ==, Double_equal, 0x613492fc)                                     \
-  V(_Double, +, Double_add, 0x53994370)                                        \
-  V(_Double, -, Double_sub, 0x3b69d466)                                        \
-  V(_Double, *, Double_mul, 0x2bb9bd5d)                                        \
-  V(_Double, /, Double_div, 0x483eee28)                                        \
-  V(_Double, get:hashCode, Double_hashCode, 0x702b77b7)                        \
-  V(_Double, get:_identityHashCode, Double_identityHash, 0x7bda5549)           \
-  V(_Double, get:isNaN, Double_getIsNaN, 0x0af9d4a9)                           \
-  V(_Double, get:isInfinite, Double_getIsInfinite, 0x0f7acb47)                 \
-  V(_Double, get:isNegative, Double_getIsNegative, 0x3a59e7f4)                 \
-  V(_Double, _mulFromInteger, Double_mulFromInteger, 0x2017fcf6)               \
-  V(_Double, .fromInteger, DoubleFromInteger, 0x6d234f4b)                      \
-  V(_GrowableList, .withData, GrowableArray_Allocate, 0x28b2138e)              \
-  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0x380184b1)                   \
-  V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0x79b8f955)       \
-  V(Object, ==, ObjectEquals, 0x7b32a55a)                                      \
-  V(Object, get:runtimeType, ObjectRuntimeType, 0x00e8ab29)                    \
-  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, 0x4dc50799)       \
-  V(_StringBase, get:hashCode, String_getHashCode, 0x78c3d446)                 \
-  V(_StringBase, get:_identityHashCode, String_identityHash, 0x0472b1d8)       \
-  V(_StringBase, get:isEmpty, StringBaseIsEmpty, 0x4a8b29c8)                   \
-  V(_StringBase, _substringMatches, StringBaseSubstringMatches, 0x46de4f10)    \
-  V(_StringBase, [], StringBaseCharAt, 0x7cbb8603)                             \
-  V(_OneByteString, get:hashCode, OneByteString_getHashCode, 0x78c3d446)       \
-  V(_OneByteString, _substringUncheckedNative,                                 \
-    OneByteString_substringUnchecked,  0x3538ad86)                             \
-  V(_OneByteString, _setAt, OneByteStringSetAt, 0x11ffddd1)                    \
-  V(_OneByteString, _allocate, OneByteString_allocate,          0x74933376)    \
-  V(_OneByteString, ==, OneByteString_equality, 0x4eda197e)                    \
-  V(_TwoByteString, ==, TwoByteString_equality, 0x4eda197e)                    \
-  V(_Type, get:hashCode, Type_getHashCode, 0x18d1523f)                         \
-  V(::, _getHash, Object_getHash, 0x2827856d)                                  \
-  V(::, _setHash, Object_setHash, 0x690faebd)                                  \
-
-
-#define CORE_INTEGER_LIB_INTRINSIC_LIST(V)                                     \
-  V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger,           \
-    0x6a10c54a)                                                                \
-  V(_IntegerImplementation, +, Integer_add, 0x43d53af7)                        \
-  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger,           \
-    0x3fa4b1ed)                                                                \
-  V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03)                        \
-  V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger,           \
-    0x3216e299)                                                                \
-  V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24)                        \
-  V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger,     \
-     0x6348b974)                                                               \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39)               \
-  V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa)                \
-  V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger,     \
-    0x395b1678)                                                                \
-  V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30)                     \
-  V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger,       \
-    0x6a36b395)                                                                \
-  V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107)                      \
-  V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger,     \
-    0x72da93f0)                                                                \
-  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230)                     \
-  V(_IntegerImplementation, _greaterThanFromInteger,                           \
-    Integer_greaterThanFromInt, 0x4a50ed58)                                    \
-  V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1)                \
-  V(_IntegerImplementation, ==, Integer_equal, 0x58abc487)                     \
-  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger,           \
-    0x063be842)                                                                \
-  V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba)                   \
-  V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64)             \
-  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184)          \
-  V(_IntegerImplementation, <<, Integer_shl, 0x371c45fa)                       \
-  V(_IntegerImplementation, >>, Integer_sar, 0x2b630578)                       \
-  V(_Double, toInt, DoubleToInteger, 0x26ef344b)                               \
-
-#define MATH_LIB_INTRINSIC_LIST(V)                                             \
-  V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
-  V(_Random, _nextState, Random_nextState, 0x2842c4d5)                         \
-
-#define GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                       \
-  V(::, sin, MathSin, 0x6b7bd98c)                                              \
-  V(::, cos, MathCos, 0x459bf5fe)                                              \
-  V(::, tan, MathTan, 0x3bcd772a)                                              \
-  V(::, asin, MathAsin, 0x2ecc2fcd)                                            \
-  V(::, acos, MathAcos, 0x08cf2212)                                            \
-  V(::, atan, MathAtan, 0x1e2731d5)                                            \
-  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
-
-#define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
-  V(Int8List, ., TypedData_Int8Array_factory, 0x7e39a3a1)                      \
-  V(Uint8List, ., TypedData_Uint8Array_factory, 0x3a79adf7)                    \
-  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 0x67f38395)      \
-  V(Int16List, ., TypedData_Int16Array_factory, 0x6477bda8)                    \
-  V(Uint16List, ., TypedData_Uint16Array_factory, 0x5707c5a2)                  \
-  V(Int32List, ., TypedData_Int32Array_factory, 0x2b96ec0e)                    \
-  V(Uint32List, ., TypedData_Uint32Array_factory, 0x0c1c0d62)                  \
-  V(Int64List, ., TypedData_Int64Array_factory, 0x279ab485)                    \
-  V(Uint64List, ., TypedData_Uint64Array_factory, 0x7bcb89c2)                  \
-  V(Float32List, ., TypedData_Float32Array_factory, 0x43506c09)                \
-  V(Float64List, ., TypedData_Float64Array_factory, 0x1fde3eaf)                \
-  V(Float32x4List, ., TypedData_Float32x4Array_factory, 0x4a4030d6)            \
-  V(Int32x4List, ., TypedData_Int32x4Array_factory, 0x6dd02406)                \
-  V(Float64x2List, ., TypedData_Float64x2Array_factory, 0x688e4e97)            \
-
-#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
-  V(_Int8List, [], Int8ArrayGetIndexed, 0x49767a2c)                            \
-  V(_Int8List, []=, Int8ArraySetIndexed, 0x24f42cd0)                           \
-  V(_Uint8List, [], Uint8ArrayGetIndexed, 0x088d86d4)                          \
-  V(_Uint8List, []=, Uint8ArraySetIndexed, 0x12639541)                         \
-  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 0x088d86d4)         \
-  V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 0x12639541)        \
-  V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 0x088d86d4)            \
-  V(_Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 0x6790dba1)           \
-  V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
-    0x088d86d4)                                                                \
-  V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
-    0x6790dba1)                                                                \
-  V(_Int16List, [], Int16ArrayGetIndexed, 0x5ec64948)                          \
-  V(_Int16List, []=, Int16ArraySetIndexed, 0x0e4e8221)                         \
-  V(_Uint16List, [], Uint16ArrayGetIndexed, 0x5f49d093)                        \
-  V(_Uint16List, []=, Uint16ArraySetIndexed, 0x2efbc90f)                       \
-  V(_Int32List, [], Int32ArrayGetIndexed, 0x4bc0d3dd)                          \
-  V(_Int32List, []=, Int32ArraySetIndexed, 0x1adf9823)                         \
-  V(_Uint32List, [], Uint32ArrayGetIndexed, 0x188658ce)                        \
-  V(_Uint32List, []=, Uint32ArraySetIndexed, 0x01f51a79)                       \
-  V(_Int64List, [], Int64ArrayGetIndexed, 0x51eafb97)                          \
-  V(_Int64List, []=, Int64ArraySetIndexed, 0x376181fb)                         \
-  V(_Uint64List, [], Uint64ArrayGetIndexed, 0x4b2a1ba2)                        \
-  V(_Uint64List, []=, Uint64ArraySetIndexed, 0x5f881bd4)                       \
-  V(_Float64List, [], Float64ArrayGetIndexed, 0x0a714486)                      \
-  V(_Float64List, []=, Float64ArraySetIndexed, 0x04937367)                     \
-  V(_Float32List, [], Float32ArrayGetIndexed, 0x5ade301f)                      \
-  V(_Float32List, []=, Float32ArraySetIndexed, 0x0d5c2e2b)                     \
-  V(_Float32x4List, [], Float32x4ArrayGetIndexed, 0x128cddeb)                  \
-  V(_Float32x4List, []=, Float32x4ArraySetIndexed, 0x7ad55c72)                 \
-  V(_Int32x4List, [], Int32x4ArrayGetIndexed, 0x4b78af9c)                      \
-  V(_Int32x4List, []=, Int32x4ArraySetIndexed, 0x31453dab)                     \
-  V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0x644a0be1)                  \
-  V(_Float64x2List, []=, Float64x2ArraySetIndexed, 0x6b836b0b)                 \
-  V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
-  V(_Float32x4, get:x, Float32x4ShuffleX, 0x63d1a9fd)                          \
-  V(_Float32x4, get:y, Float32x4ShuffleY, 0x203523d9)                          \
-  V(_Float32x4, get:z, Float32x4ShuffleZ, 0x13190678)                          \
-  V(_Float32x4, get:w, Float32x4ShuffleW, 0x698a38de)                          \
-  V(_Float32x4, *, Float32x4Mul, 0x5dec68b2)                                   \
-  V(_Float32x4, -, Float32x4Sub, 0x3ea14461)                                   \
-  V(_Float32x4, +, Float32x4Add, 0x7ffcf301)                                   \
-
-#define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
-  V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
-  V(_List, [], ObjectArrayGetIndexed, 0x653da02e)                              \
-  V(_List, []=, ObjectArraySetIndexed, 0x16b3d2b0)                             \
-  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, 0x50d64c75)            \
-  V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
-  V(_ImmutableList, [], ImmutableArrayGetIndexed, 0x653da02e)                  \
-  V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
-  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
-  V(_GrowableList, _setData, GrowableArraySetData, 0x3dbea348)                 \
-  V(_GrowableList, _setLength, GrowableArraySetLength, 0x753e55da)             \
-  V(_GrowableList, [], GrowableArrayGetIndexed, 0x446fe1f0)                    \
-  V(_GrowableList, []=, GrowableArraySetIndexed, 0x40a462ec)                   \
-  V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, 0x297083df)  \
-  V(_StringBase, get:length, StringBaseLength, 0x2a2d03d1)                     \
-  V(_OneByteString, codeUnitAt, OneByteStringCodeUnitAt, 0x55a0a1f3)           \
-  V(_TwoByteString, codeUnitAt, TwoByteStringCodeUnitAt, 0x55a0a1f3)           \
-  V(_ExternalOneByteString, codeUnitAt, ExternalOneByteStringCodeUnitAt,       \
-    0x55a0a1f3)                                                                \
-  V(_ExternalTwoByteString, codeUnitAt, ExternalTwoByteStringCodeUnitAt,       \
-    0x55a0a1f3)                                                                \
-  V(_Double, unary-, DoubleFlipSignBit, 0x6db4674f)                            \
-  V(_Double, truncateToDouble, DoubleTruncate, 0x2f27e5d3)                     \
-  V(_Double, roundToDouble, DoubleRound, 0x2f89c512)                           \
-  V(_Double, floorToDouble, DoubleFloor, 0x6aa87a5f)                           \
-  V(_Double, ceilToDouble, DoubleCeil, 0x1b045e9e)                             \
-  V(_Double, _modulo, DoubleMod, 0x5b8ceed7)
-
-
-#define GRAPH_INTRINSICS_LIST(V)                                               \
-  GRAPH_CORE_INTRINSICS_LIST(V)                                                \
-  GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                          \
-  GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                             \
-
-#define DEVELOPER_LIB_INTRINSIC_LIST(V)                                        \
-  V(_UserTag, makeCurrent, UserTag_makeCurrent, 0x0b3066fd)                    \
-  V(::, _getDefaultTag, UserTag_defaultTag, 0x69f3f1ad)                        \
-  V(::, _getCurrentTag, Profiler_getCurrentTag, 0x05fa99d2)                    \
-  V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, 0x72f13f7a)        \
-
-#define ASYNC_LIB_INTRINSIC_LIST(V)                                            \
-  V(::, _clearAsyncThreadStackTrace, ClearAsyncThreadStackTrace, 0x2edd4b25)   \
-  V(::, _setAsyncThreadStackTrace, SetAsyncThreadStackTrace, 0x04f429a7)       \
-
-#define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
-  ASYNC_LIB_INTRINSIC_LIST(V)                                                  \
-  CORE_LIB_INTRINSIC_LIST(V)                                                   \
-  DEVELOPER_LIB_INTRINSIC_LIST(V)                                              \
-  MATH_LIB_INTRINSIC_LIST(V)                                                   \
-  TYPED_DATA_LIB_INTRINSIC_LIST(V)                                             \
-
-#define ALL_INTRINSICS_LIST(V)                                                 \
-  ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                        \
-  CORE_INTEGER_LIB_INTRINSIC_LIST(V)
-
-#define RECOGNIZED_LIST(V)                                                     \
-  OTHER_RECOGNIZED_LIST(V)                                                     \
-  ALL_INTRINSICS_LIST(V)                                                       \
-  GRAPH_INTRINSICS_LIST(V)
-
-// A list of core function that should always be inlined.
-#define INLINE_WHITE_LIST(V)                                                   \
-  V(Object, ==, ObjectEquals, 0x7b32a55a)                                      \
-  V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
-  V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
-  V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
-  V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
-  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
-  V(_GrowableList, add, GrowableListAdd, 0x40b490b8)                           \
-  V(_GrowableList, removeLast, GrowableListRemoveLast, 0x007855e5)             \
-  V(_StringBase, get:length, StringBaseLength, 0x2a2d03d1)                     \
-  V(ListIterator, moveNext, ListIteratorMoveNext, 0x2dca30ce)                  \
-  V(_FixedSizeArrayIterator, moveNext, FixedListIteratorMoveNext, 0x324eb20b)  \
-  V(_GrowableList, get:iterator, GrowableArrayIterator, 0x5bd2ef37)            \
-  V(_GrowableList, forEach, GrowableArrayForEach, 0x74900bb8)                  \
-  V(_List, ., ObjectArrayAllocate, 0x2121902f)                                 \
-  V(ListMixin, get:isEmpty, ListMixinIsEmpty, 0x7be74d04)                      \
-  V(_List, get:iterator, ObjectArrayIterator, 0x6c851c55)                      \
-  V(_List, forEach, ObjectArrayForEach, 0x11406b13)                            \
-  V(_List, _slice, ObjectArraySlice, 0x4c865d1d)                               \
-  V(_ImmutableList, get:iterator, ImmutableArrayIterator, 0x6c851c55)          \
-  V(_ImmutableList, forEach, ImmutableArrayForEach, 0x11406b13)                \
-  V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 0x7e5a8458)                   \
-  V(_Int8ArrayView, []=, Int8ArrayViewSetIndexed, 0x62f615e4)                  \
-  V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 0x7d308247)                 \
-  V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 0x65ba546e)                \
-  V(_Uint8ClampedArrayView, [], Uint8ClampedArrayViewGetIndexed, 0x7d308247)   \
-  V(_Uint8ClampedArrayView, []=, Uint8ClampedArrayViewSetIndexed, 0x65ba546e)  \
-  V(_Uint16ArrayView, [], Uint16ArrayViewGetIndexed, 0xe96836dd)               \
-  V(_Uint16ArrayView, []=, Uint16ArrayViewSetIndexed, 0x15b02947)              \
-  V(_Int16ArrayView, [], Int16ArrayViewGetIndexed, 0x1b24a48b)                 \
-  V(_Int16ArrayView, []=, Int16ArrayViewSetIndexed, 0xb91ec2e6)                \
-  V(_Uint32ArrayView, [], Uint32ArrayViewGetIndexed, 0x8a4f93b3)               \
-  V(_Uint32ArrayView, []=, Uint32ArrayViewSetIndexed, 0xf54918b5)              \
-  V(_Int32ArrayView, [], Int32ArrayViewGetIndexed, 0x85040819)                 \
-  V(_Int32ArrayView, []=, Int32ArrayViewSetIndexed, 0xaec8c6f5)                \
-  V(_Uint64ArrayView, [], Uint64ArrayViewGetIndexed, 0xd0c44fe7)               \
-  V(_Uint64ArrayView, []=, Uint64ArrayViewSetIndexed, 0x402712b7)              \
-  V(_Int64ArrayView, [], Int64ArrayViewGetIndexed, 0xf3090b95)                 \
-  V(_Int64ArrayView, []=, Int64ArrayViewSetIndexed, 0xca07e497)                \
-  V(_Float32ArrayView, [], Float32ArrayViewGetIndexed, 0xef967533)             \
-  V(_Float32ArrayView, []=, Float32ArrayViewSetIndexed, 0xc9b691bd)            \
-  V(_Float64ArrayView, [], Float64ArrayViewGetIndexed, 0x9d83f585)             \
-  V(_Float64ArrayView, []=, Float64ArrayViewSetIndexed, 0x3c1adabd)            \
-  V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x6395293e)                   \
-  V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x79979d1f)                 \
-  V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x525ec534)                 \
-  V(_ByteDataView, setUint16, ByteDataViewSetUint16, 0x48eda263)               \
-  V(_ByteDataView, setInt32, ByteDataViewSetInt32, 0x523666fa)                 \
-  V(_ByteDataView, setUint32, ByteDataViewSetUint32, 0x5a4683da)               \
-  V(_ByteDataView, setInt64, ByteDataViewSetInt64, 0x4283a650)                 \
-  V(_ByteDataView, setUint64, ByteDataViewSetUint64, 0x687a1892)               \
-  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 0x7d5784fd)             \
-  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 0x00101e3f)             \
-  V(_ByteDataView, getInt8, ByteDataViewGetInt8, 0x68448b4d)                   \
-  V(_ByteDataView, getUint8, ByteDataViewGetUint8, 0x5d68cbf2)                 \
-  V(_ByteDataView, getInt16, ByteDataViewGetInt16, 0x691b5ead)                 \
-  V(_ByteDataView, getUint16, ByteDataViewGetUint16, 0x78b744d8)               \
-  V(_ByteDataView, getInt32, ByteDataViewGetInt32, 0x3a0f4efa)                 \
-  V(_ByteDataView, getUint32, ByteDataViewGetUint32, 0x583261be)               \
-  V(_ByteDataView, getInt64, ByteDataViewGetInt64, 0x77de471c)                 \
-  V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x0ffadc4b)               \
-  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x6a205749)             \
-  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x69f58d27)             \
-  V(::, exp, MathExp, 0x32ab9efa)                                              \
-  V(::, log, MathLog, 0x1ee8f9fc)                                              \
-  V(::, max, MathMax, 0x377e8889)                                              \
-  V(::, min, MathMin, 0x32ebc57d)                                              \
-  V(::, pow, MathPow, 0x79efc5a2)                                              \
-  V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84)                         \
-  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75)          \
-  V(::, _toInt, ConvertMaskedInt, 0x713908fd)                                  \
-  V(::, _toInt8, ConvertIntToInt8, 0x7484a780)                                 \
-  V(::, _toUint8, ConvertIntToUint8, 0x0a15b522)                               \
-  V(::, _toInt16, ConvertIntToInt16, 0x0a83fcc6)                               \
-  V(::, _toUint16, ConvertIntToUint16, 0x6087d1af)                             \
-  V(::, _toInt32, ConvertIntToInt32, 0x62b451b9)                               \
-  V(::, _toUint32, ConvertIntToUint32, 0x17a8e085)                             \
-  V(::, _byteSwap16, ByteSwap16, 0x44f173be)                                   \
-  V(::, _byteSwap32, ByteSwap32, 0x6219333b)                                   \
-  V(::, _byteSwap64, ByteSwap64, 0x9abe57e0)                                   \
-  V(Lists, copy, ListsCopy, 0x40e974f6)                                        \
-  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
-  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
-  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac)                 \
-  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x0ec032e8)                 \
-  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x088599ed)         \
-  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x5f42ca86)         \
-  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f3b13b)         \
-  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x7219c45b)         \
-  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2)   \
-  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d)   \
-
-// A list of core function that should never be inlined.
-#define INLINE_BLACK_LIST(V)                                                   \
-  V(::, asin, MathAsin, 0x2ecc2fcd)                                            \
-  V(::, acos, MathAcos, 0x08cf2212)                                            \
-  V(::, atan, MathAtan, 0x1e2731d5)                                            \
-  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
-  V(::, cos, MathCos, 0x459bf5fe)                                              \
-  V(::, sin, MathSin, 0x6b7bd98c)                                              \
-  V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
-  V(::, tan, MathTan, 0x3bcd772a)                                              \
-  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
-  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
-  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
-  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
-  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
-  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
-  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit,         \
-    0x35456d91)                                                                \
-  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
-  V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
-  V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
-  V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
-  V(_Double, <=, Double_lessEqualThan, 0x74b5eb64)                             \
-  V(_Double, ==, Double_equal, 0x613492fc)                                     \
-  V(_Double, +, Double_add, 0x53994370)                                        \
-  V(_Double, -, Double_sub, 0x3b69d466)                                        \
-  V(_Double, *, Double_mul, 0x2bb9bd5d)                                        \
-  V(_Double, /, Double_div, 0x483eee28)                                        \
-  V(_IntegerImplementation, +, Integer_add, 0x43d53af7)                        \
-  V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03)                        \
-  V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24)                        \
-  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39)               \
-  V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa)                \
-  V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30)                     \
-  V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107)                      \
-  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230)                     \
-  V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1)                \
-  V(_IntegerImplementation, ==, Integer_equal, 0x58abc487)                     \
-  V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba)                   \
-  V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64)             \
-  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184)          \
-  V(_IntegerImplementation, <<, Integer_shl, 0x371c45fa)                       \
-  V(_IntegerImplementation, >>, Integer_sar, 0x2b630578)                       \
-
-// A list of core functions that internally dispatch based on received id.
-#define POLYMORPHIC_TARGET_LIST(V)                                             \
-  V(_StringBase, [], StringBaseCharAt, 0x7cbb8603)                             \
-  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
-  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
-  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
-  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
-  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
-  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
-  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, 0x7db75d78)                  \
-  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, 0x1487cfc6)                \
-  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
-  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
-  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
-  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
-  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x12bae36a)                    \
-  V(_TypedList, _setUint8, ByteArrayBaseSetInt8, 0x15821cc9)                   \
-  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x1f8237fa)                  \
-  V(_TypedList, _setUint16, ByteArrayBaseSetInt16, 0x181e5d16)                 \
-  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x7ddb9f87)                  \
-  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74094f8d)                \
-  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, 0x4741396e)                  \
-  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, 0x3b398ae4)                \
-  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x03db087b)              \
-  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
-  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
-  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
-  V(Object, get:runtimeType, ObjectRuntimeType, 0x00e8ab29)
-
-// clang-format on
-
 // Forward declarations.
 class Function;
 class Library;
@@ -588,35 +81,6 @@
   ASSERT(f.CheckSourceFingerprint(#p0 ", " #p1 ", " #p2, fp))
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
-// clang-format off
-// List of recognized list factories:
-// (factory-name-symbol, class-name-string, constructor-name-string,
-//  result-cid, fingerprint).
-#define RECOGNIZED_LIST_FACTORY_LIST(V)                                        \
-  V(_ListFactory, _List, ., kArrayCid, 0x2121902f)                             \
-  V(_GrowableListWithData, _GrowableList, .withData, kGrowableObjectArrayCid,  \
-    0x28b2138e)                                                                \
-  V(_GrowableListFactory, _GrowableList, ., kGrowableObjectArrayCid,           \
-    0x3eed680b)                                                                \
-  V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x7e39a3a1)        \
-  V(_Uint8ArrayFactory, Uint8List, ., kTypedDataUint8ArrayCid, 0x3a79adf7)     \
-  V(_Uint8ClampedArrayFactory, Uint8ClampedList, .,                            \
-    kTypedDataUint8ClampedArrayCid, 0x67f38395)                                \
-  V(_Int16ArrayFactory, Int16List, ., kTypedDataInt16ArrayCid, 0x6477bda8)     \
-  V(_Uint16ArrayFactory, Uint16List, ., kTypedDataUint16ArrayCid, 0x5707c5a2)  \
-  V(_Int32ArrayFactory, Int32List, ., kTypedDataInt32ArrayCid, 0x2b96ec0e)     \
-  V(_Uint32ArrayFactory, Uint32List, ., kTypedDataUint32ArrayCid, 0x0c1c0d62)  \
-  V(_Int64ArrayFactory, Int64List, ., kTypedDataInt64ArrayCid, 0x279ab485)     \
-  V(_Uint64ArrayFactory, Uint64List, ., kTypedDataUint64ArrayCid, 0x7bcb89c2)  \
-  V(_Float64ArrayFactory, Float64List, ., kTypedDataFloat64ArrayCid,           \
-    0x1fde3eaf)                                                                \
-  V(_Float32ArrayFactory, Float32List, ., kTypedDataFloat32ArrayCid,           \
-    0x43506c09)                                                                \
-  V(_Float32x4ArrayFactory, Float32x4List, ., kTypedDataFloat32x4ArrayCid,     \
-    0x4a4030d6)
-
-// clang-format on
-
 // Class that recognizes factories and returns corresponding result cid.
 class FactoryRecognizer : public AllStatic {
  public:
diff --git a/runtime/vm/compiler/recognized_methods_list.h b/runtime/vm/compiler/recognized_methods_list.h
new file mode 100644
index 0000000..fa35d7c
--- /dev/null
+++ b/runtime/vm/compiler/recognized_methods_list.h
@@ -0,0 +1,545 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_RECOGNIZED_METHODS_LIST_H_
+#define RUNTIME_VM_COMPILER_RECOGNIZED_METHODS_LIST_H_
+
+namespace dart {
+
+// clang-format off
+// (class-name, function-name, recognized enum, result type, fingerprint).
+// When adding a new function add a 0 as fingerprint, build and run to get the
+// correct fingerprint from the mismatch error (or use Library::GetFunction()
+// and print func.SourceFingerprint()).
+#define OTHER_RECOGNIZED_LIST(V)                                               \
+  V(::, identical, ObjectIdentical, 0x49c6e96a)                                \
+  V(ClassID, getID, ClassIDgetID, 0x7b18b257)                                  \
+  V(Object, Object., ObjectConstructor, 0x681617fe)                            \
+  V(List, ., ListFactory, 0x629f8324)                                          \
+  V(_List, ., ObjectArrayAllocate, 0x2121902f)                                 \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
+  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, 0x7db75d78)                  \
+  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, 0x1487cfc6)                \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
+  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
+  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x12bae36a)                    \
+  V(_TypedList, _setUint8, ByteArrayBaseSetUint8, 0x15821cc9)                  \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x1f8237fa)                  \
+  V(_TypedList, _setUint16, ByteArrayBaseSetUint16, 0x181e5d16)                \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x7ddb9f87)                  \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74094f8d)                \
+  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, 0x4741396e)                  \
+  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, 0x3b398ae4)                \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x03db087b)              \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
+  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
+  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(::, _toClampedUint8, ConvertIntToClampedUint8, 0x564b0435)                 \
+  V(_StringBase, _interpolate, StringBaseInterpolate, 0x01ecb15a)              \
+  V(_IntegerImplementation, toDouble, IntegerToDouble, 0x05da96ed)             \
+  V(_Double, _add, DoubleAdd, 0x2a38277b)                                      \
+  V(_Double, _sub, DoubleSub, 0x4f466391)                                      \
+  V(_Double, _mul, DoubleMul, 0x175e4f66)                                      \
+  V(_Double, _div, DoubleDiv, 0x0854181b)                                      \
+  V(::, min, MathMin, 0x32ebc57d)                                              \
+  V(::, max, MathMax, 0x377e8889)                                              \
+  V(::, _doublePow, MathDoublePow, 0x5add0ec1)                                 \
+  V(::, _intPow, MathIntPow, 0x11b45569)                                       \
+  V(Float32x4, Float32x4., Float32x4Constructor, 0x26ea459b)                   \
+  V(Float32x4, Float32x4.zero, Float32x4Zero, 0x16eca604)                      \
+  V(Float32x4, Float32x4.splat, Float32x4Splat, 0x694e83e3)                    \
+  V(Float32x4, Float32x4.fromInt32x4Bits, Int32x4ToFloat32x4, 0x2f62ebd3)      \
+  V(Float32x4, Float32x4.fromFloat64x2, Float64x2ToFloat32x4, 0x50ed6910)      \
+  V(_Float32x4, shuffle, Float32x4Shuffle, 0x7829101f)                         \
+  V(_Float32x4, shuffleMix, Float32x4ShuffleMix, 0x4182c06b)                   \
+  V(_Float32x4, get:signMask, Float32x4GetSignMask, 0x1d08b351)                \
+  V(_Float32x4, equal, Float32x4Equal, 0x11adb239)                             \
+  V(_Float32x4, greaterThan, Float32x4GreaterThan, 0x48adaf58)                 \
+  V(_Float32x4, greaterThanOrEqual, Float32x4GreaterThanOrEqual, 0x32db94ca)   \
+  V(_Float32x4, lessThan, Float32x4LessThan, 0x425b000c)                       \
+  V(_Float32x4, lessThanOrEqual, Float32x4LessThanOrEqual, 0x0278c2f8)         \
+  V(_Float32x4, notEqual, Float32x4NotEqual, 0x2987cd26)                       \
+  V(_Float32x4, min, Float32x4Min, 0x5ed74b6f)                                 \
+  V(_Float32x4, max, Float32x4Max, 0x68696442)                                 \
+  V(_Float32x4, scale, Float32x4Scale, 0x704e4122)                             \
+  V(_Float32x4, sqrt, Float32x4Sqrt, 0x2c967a6f)                               \
+  V(_Float32x4, reciprocalSqrt, Float32x4ReciprocalSqrt, 0x6264bfe8)           \
+  V(_Float32x4, reciprocal, Float32x4Reciprocal, 0x3cd7e819)                   \
+  V(_Float32x4, unary-, Float32x4Negate, 0x37accb52)                           \
+  V(_Float32x4, abs, Float32x4Abs, 0x471cdd87)                                 \
+  V(_Float32x4, clamp, Float32x4Clamp, 0x2cb30492)                             \
+  V(_Float32x4, withX, Float32x4WithX, 0x4e336aff)                             \
+  V(_Float32x4, withY, Float32x4WithY, 0x0a72b910)                             \
+  V(_Float32x4, withZ, Float32x4WithZ, 0x31e93658)                             \
+  V(_Float32x4, withW, Float32x4WithW, 0x60ddc105)                             \
+  V(Float64x2, Float64x2., Float64x2Constructor, 0x43054b9f)                   \
+  V(Float64x2, Float64x2.zero, Float64x2Zero, 0x4af12f9d)                      \
+  V(Float64x2, Float64x2.splat, Float64x2Splat, 0x134edef0)                    \
+  V(Float64x2, Float64x2.fromFloat32x4, Float32x4ToFloat64x2, 0x17d6b5e4)      \
+  V(_Float64x2, get:x, Float64x2GetX, 0x58c09c58)                              \
+  V(_Float64x2, get:y, Float64x2GetY, 0x3cf5e5b8)                              \
+  V(_Float64x2, unary-, Float64x2Negate, 0x415ca009)                           \
+  V(_Float64x2, abs, Float64x2Abs, 0x031f9e47)                                 \
+  V(_Float64x2, sqrt, Float64x2Sqrt, 0x77f711dd)                               \
+  V(_Float64x2, get:signMask, Float64x2GetSignMask, 0x27deda4b)                \
+  V(_Float64x2, scale, Float64x2Scale, 0x26830a61)                             \
+  V(_Float64x2, withX, Float64x2WithX, 0x1d2bcaf5)                             \
+  V(_Float64x2, withY, Float64x2WithY, 0x383ed6ac)                             \
+  V(_Float64x2, min, Float64x2Min,  0x28d7ddf6)                                \
+  V(_Float64x2, max, Float64x2Max,  0x0bd74e5b)                                \
+  V(Int32x4, Int32x4., Int32x4Constructor, 0x480555a9)                         \
+  V(Int32x4, Int32x4.bool, Int32x4BoolConstructor, 0x36aa6963)                 \
+  V(Int32x4, Int32x4.fromFloat32x4Bits, Float32x4ToInt32x4, 0x6715388a)        \
+  V(_Int32x4, get:flagX, Int32x4GetFlagX, 0x56396c82)                          \
+  V(_Int32x4, get:flagY, Int32x4GetFlagY, 0x44704738)                          \
+  V(_Int32x4, get:flagZ, Int32x4GetFlagZ, 0x20d6ff37)                          \
+  V(_Int32x4, get:flagW, Int32x4GetFlagW, 0x5045616a)                          \
+  V(_Int32x4, get:signMask, Int32x4GetSignMask, 0x2c1fb2a3)                    \
+  V(_Int32x4, shuffle, Int32x4Shuffle, 0x20bc0b16)                             \
+  V(_Int32x4, shuffleMix, Int32x4ShuffleMix, 0x5c7056e1)                       \
+  V(_Int32x4, select, Int32x4Select, 0x6b49654f)                               \
+  V(_Int32x4, withFlagX, Int32x4WithFlagX, 0x0ef58fcf)                         \
+  V(_Int32x4, withFlagY, Int32x4WithFlagY, 0x6485a9c4)                         \
+  V(_Int32x4, withFlagZ, Int32x4WithFlagZ, 0x267acdfa)                         \
+  V(_Int32x4, withFlagW, Int32x4WithFlagW, 0x345ac675)                         \
+  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
+  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
+  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac)                 \
+  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x0ec032e8)                 \
+  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x088599ed)         \
+  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x5f42ca86)         \
+  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f3b13b)         \
+  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x7219c45b)         \
+  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2)   \
+  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d)   \
+  V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84)                         \
+  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75)          \
+
+// List of intrinsics:
+// (class-name, function-name, intrinsification method, fingerprint).
+#define CORE_LIB_INTRINSIC_LIST(V)                                             \
+  V(_Smi, ~, Smi_bitNegate, 0x67299f4f)                                        \
+  V(_Smi, get:bitLength, Smi_bitLength, 0x25b3cb0a)                            \
+  V(_Smi, _bitAndFromSmi, Smi_bitAndFromSmi, 0x562d5047)                       \
+  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
+  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
+  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
+  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
+  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
+  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
+  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit,         \
+    0x35456d91)                                                                \
+  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
+  V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
+  V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
+  V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
+  V(_Double, <=, Double_lessEqualThan, 0x74b5eb64)                             \
+  V(_Double, ==, Double_equal, 0x613492fc)                                     \
+  V(_Double, +, Double_add, 0x53994370)                                        \
+  V(_Double, -, Double_sub, 0x3b69d466)                                        \
+  V(_Double, *, Double_mul, 0x2bb9bd5d)                                        \
+  V(_Double, /, Double_div, 0x483eee28)                                        \
+  V(_Double, get:hashCode, Double_hashCode, 0x702b77b7)                        \
+  V(_Double, get:_identityHashCode, Double_identityHash, 0x7bda5549)           \
+  V(_Double, get:isNaN, Double_getIsNaN, 0x0af9d4a9)                           \
+  V(_Double, get:isInfinite, Double_getIsInfinite, 0x0f7acb47)                 \
+  V(_Double, get:isNegative, Double_getIsNegative, 0x3a59e7f4)                 \
+  V(_Double, _mulFromInteger, Double_mulFromInteger, 0x2017fcf6)               \
+  V(_Double, .fromInteger, DoubleFromInteger, 0x6d234f4b)                      \
+  V(_GrowableList, .withData, GrowableArray_Allocate, 0x28b2138e)              \
+  V(_RegExp, _ExecuteMatch, RegExp_ExecuteMatch, 0x380184b1)                   \
+  V(_RegExp, _ExecuteMatchSticky, RegExp_ExecuteMatchSticky, 0x79b8f955)       \
+  V(Object, ==, ObjectEquals, 0x7b32a55a)                                      \
+  V(Object, get:runtimeType, ObjectRuntimeType, 0x00e8ab29)                    \
+  V(Object, _haveSameRuntimeType, ObjectHaveSameRuntimeType, 0x4dc50799)       \
+  V(_StringBase, get:hashCode, String_getHashCode, 0x78c3d446)                 \
+  V(_StringBase, get:_identityHashCode, String_identityHash, 0x0472b1d8)       \
+  V(_StringBase, get:isEmpty, StringBaseIsEmpty, 0x4a8b29c8)                   \
+  V(_StringBase, _substringMatches, StringBaseSubstringMatches, 0x46de4f10)    \
+  V(_StringBase, [], StringBaseCharAt, 0x7cbb8603)                             \
+  V(_OneByteString, get:hashCode, OneByteString_getHashCode, 0x78c3d446)       \
+  V(_OneByteString, _substringUncheckedNative,                                 \
+    OneByteString_substringUnchecked,  0x3538ad86)                             \
+  V(_OneByteString, _setAt, OneByteStringSetAt, 0x11ffddd1)                    \
+  V(_OneByteString, _allocate, OneByteString_allocate,          0x74933376)    \
+  V(_OneByteString, ==, OneByteString_equality, 0x4eda197e)                    \
+  V(_TwoByteString, ==, TwoByteString_equality, 0x4eda197e)                    \
+  V(_Type, get:hashCode, Type_getHashCode, 0x18d1523f)                         \
+  V(::, _getHash, Object_getHash, 0x2827856d)                                  \
+  V(::, _setHash, Object_setHash, 0x690faebd)                                  \
+
+
+#define CORE_INTEGER_LIB_INTRINSIC_LIST(V)                                     \
+  V(_IntegerImplementation, _addFromInteger, Integer_addFromInteger,           \
+    0x6a10c54a)                                                                \
+  V(_IntegerImplementation, +, Integer_add, 0x43d53af7)                        \
+  V(_IntegerImplementation, _subFromInteger, Integer_subFromInteger,           \
+    0x3fa4b1ed)                                                                \
+  V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03)                        \
+  V(_IntegerImplementation, _mulFromInteger, Integer_mulFromInteger,           \
+    0x3216e299)                                                                \
+  V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24)                        \
+  V(_IntegerImplementation, _moduloFromInteger, Integer_moduloFromInteger,     \
+     0x6348b974)                                                               \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39)               \
+  V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa)                \
+  V(_IntegerImplementation, _bitAndFromInteger, Integer_bitAndFromInteger,     \
+    0x395b1678)                                                                \
+  V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30)                     \
+  V(_IntegerImplementation, _bitOrFromInteger, Integer_bitOrFromInteger,       \
+    0x6a36b395)                                                                \
+  V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107)                      \
+  V(_IntegerImplementation, _bitXorFromInteger, Integer_bitXorFromInteger,     \
+    0x72da93f0)                                                                \
+  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230)                     \
+  V(_IntegerImplementation, _greaterThanFromInteger,                           \
+    Integer_greaterThanFromInt, 0x4a50ed58)                                    \
+  V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1)                \
+  V(_IntegerImplementation, ==, Integer_equal, 0x58abc487)                     \
+  V(_IntegerImplementation, _equalToInteger, Integer_equalToInteger,           \
+    0x063be842)                                                                \
+  V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba)                   \
+  V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64)             \
+  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184)          \
+  V(_IntegerImplementation, <<, Integer_shl, 0x371c45fa)                       \
+  V(_IntegerImplementation, >>, Integer_sar, 0x2b630578)                       \
+  V(_Double, toInt, DoubleToInteger, 0x26ef344b)                               \
+
+#define MATH_LIB_INTRINSIC_LIST(V)                                             \
+  V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
+  V(_Random, _nextState, Random_nextState, 0x2842c4d5)                         \
+
+#define GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                       \
+  V(::, sin, MathSin, 0x6b7bd98c)                                              \
+  V(::, cos, MathCos, 0x459bf5fe)                                              \
+  V(::, tan, MathTan, 0x3bcd772a)                                              \
+  V(::, asin, MathAsin, 0x2ecc2fcd)                                            \
+  V(::, acos, MathAcos, 0x08cf2212)                                            \
+  V(::, atan, MathAtan, 0x1e2731d5)                                            \
+  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
+
+#define TYPED_DATA_LIB_INTRINSIC_LIST(V)                                       \
+  V(Int8List, ., TypedData_Int8Array_factory, 0x7e39a3a1)                      \
+  V(Uint8List, ., TypedData_Uint8Array_factory, 0x3a79adf7)                    \
+  V(Uint8ClampedList, ., TypedData_Uint8ClampedArray_factory, 0x67f38395)      \
+  V(Int16List, ., TypedData_Int16Array_factory, 0x6477bda8)                    \
+  V(Uint16List, ., TypedData_Uint16Array_factory, 0x5707c5a2)                  \
+  V(Int32List, ., TypedData_Int32Array_factory, 0x2b96ec0e)                    \
+  V(Uint32List, ., TypedData_Uint32Array_factory, 0x0c1c0d62)                  \
+  V(Int64List, ., TypedData_Int64Array_factory, 0x279ab485)                    \
+  V(Uint64List, ., TypedData_Uint64Array_factory, 0x7bcb89c2)                  \
+  V(Float32List, ., TypedData_Float32Array_factory, 0x43506c09)                \
+  V(Float64List, ., TypedData_Float64Array_factory, 0x1fde3eaf)                \
+  V(Float32x4List, ., TypedData_Float32x4Array_factory, 0x4a4030d6)            \
+  V(Int32x4List, ., TypedData_Int32x4Array_factory, 0x6dd02406)                \
+  V(Float64x2List, ., TypedData_Float64x2Array_factory, 0x688e4e97)            \
+
+#define GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                    \
+  V(_Int8List, [], Int8ArrayGetIndexed, 0x49767a2c)                            \
+  V(_Int8List, []=, Int8ArraySetIndexed, 0x24f42cd0)                           \
+  V(_Uint8List, [], Uint8ArrayGetIndexed, 0x088d86d4)                          \
+  V(_Uint8List, []=, Uint8ArraySetIndexed, 0x12639541)                         \
+  V(_ExternalUint8Array, [], ExternalUint8ArrayGetIndexed, 0x088d86d4)         \
+  V(_ExternalUint8Array, []=, ExternalUint8ArraySetIndexed, 0x12639541)        \
+  V(_Uint8ClampedList, [], Uint8ClampedArrayGetIndexed, 0x088d86d4)            \
+  V(_Uint8ClampedList, []=, Uint8ClampedArraySetIndexed, 0x6790dba1)           \
+  V(_ExternalUint8ClampedArray, [], ExternalUint8ClampedArrayGetIndexed,       \
+    0x088d86d4)                                                                \
+  V(_ExternalUint8ClampedArray, []=, ExternalUint8ClampedArraySetIndexed,      \
+    0x6790dba1)                                                                \
+  V(_Int16List, [], Int16ArrayGetIndexed, 0x5ec64948)                          \
+  V(_Int16List, []=, Int16ArraySetIndexed, 0x0e4e8221)                         \
+  V(_Uint16List, [], Uint16ArrayGetIndexed, 0x5f49d093)                        \
+  V(_Uint16List, []=, Uint16ArraySetIndexed, 0x2efbc90f)                       \
+  V(_Int32List, [], Int32ArrayGetIndexed, 0x4bc0d3dd)                          \
+  V(_Int32List, []=, Int32ArraySetIndexed, 0x1adf9823)                         \
+  V(_Uint32List, [], Uint32ArrayGetIndexed, 0x188658ce)                        \
+  V(_Uint32List, []=, Uint32ArraySetIndexed, 0x01f51a79)                       \
+  V(_Int64List, [], Int64ArrayGetIndexed, 0x51eafb97)                          \
+  V(_Int64List, []=, Int64ArraySetIndexed, 0x376181fb)                         \
+  V(_Uint64List, [], Uint64ArrayGetIndexed, 0x4b2a1ba2)                        \
+  V(_Uint64List, []=, Uint64ArraySetIndexed, 0x5f881bd4)                       \
+  V(_Float64List, [], Float64ArrayGetIndexed, 0x0a714486)                      \
+  V(_Float64List, []=, Float64ArraySetIndexed, 0x04937367)                     \
+  V(_Float32List, [], Float32ArrayGetIndexed, 0x5ade301f)                      \
+  V(_Float32List, []=, Float32ArraySetIndexed, 0x0d5c2e2b)                     \
+  V(_Float32x4List, [], Float32x4ArrayGetIndexed, 0x128cddeb)                  \
+  V(_Float32x4List, []=, Float32x4ArraySetIndexed, 0x7ad55c72)                 \
+  V(_Int32x4List, [], Int32x4ArrayGetIndexed, 0x4b78af9c)                      \
+  V(_Int32x4List, []=, Int32x4ArraySetIndexed, 0x31453dab)                     \
+  V(_Float64x2List, [], Float64x2ArrayGetIndexed, 0x644a0be1)                  \
+  V(_Float64x2List, []=, Float64x2ArraySetIndexed, 0x6b836b0b)                 \
+  V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
+  V(_Float32x4, get:x, Float32x4ShuffleX, 0x63d1a9fd)                          \
+  V(_Float32x4, get:y, Float32x4ShuffleY, 0x203523d9)                          \
+  V(_Float32x4, get:z, Float32x4ShuffleZ, 0x13190678)                          \
+  V(_Float32x4, get:w, Float32x4ShuffleW, 0x698a38de)                          \
+  V(_Float32x4, *, Float32x4Mul, 0x5dec68b2)                                   \
+  V(_Float32x4, -, Float32x4Sub, 0x3ea14461)                                   \
+  V(_Float32x4, +, Float32x4Add, 0x7ffcf301)                                   \
+
+#define GRAPH_CORE_INTRINSICS_LIST(V)                                          \
+  V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
+  V(_List, [], ObjectArrayGetIndexed, 0x653da02e)                              \
+  V(_List, []=, ObjectArraySetIndexed, 0x16b3d2b0)                             \
+  V(_List, _setIndexed, ObjectArraySetIndexedUnchecked, 0x50d64c75)            \
+  V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
+  V(_ImmutableList, [], ImmutableArrayGetIndexed, 0x653da02e)                  \
+  V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
+  V(_GrowableList, _setData, GrowableArraySetData, 0x3dbea348)                 \
+  V(_GrowableList, _setLength, GrowableArraySetLength, 0x753e55da)             \
+  V(_GrowableList, [], GrowableArrayGetIndexed, 0x446fe1f0)                    \
+  V(_GrowableList, []=, GrowableArraySetIndexed, 0x40a462ec)                   \
+  V(_GrowableList, _setIndexed, GrowableArraySetIndexedUnchecked, 0x297083df)  \
+  V(_StringBase, get:length, StringBaseLength, 0x2a2d03d1)                     \
+  V(_OneByteString, codeUnitAt, OneByteStringCodeUnitAt, 0x55a0a1f3)           \
+  V(_TwoByteString, codeUnitAt, TwoByteStringCodeUnitAt, 0x55a0a1f3)           \
+  V(_ExternalOneByteString, codeUnitAt, ExternalOneByteStringCodeUnitAt,       \
+    0x55a0a1f3)                                                                \
+  V(_ExternalTwoByteString, codeUnitAt, ExternalTwoByteStringCodeUnitAt,       \
+    0x55a0a1f3)                                                                \
+  V(_Double, unary-, DoubleFlipSignBit, 0x6db4674f)                            \
+  V(_Double, truncateToDouble, DoubleTruncate, 0x2f27e5d3)                     \
+  V(_Double, roundToDouble, DoubleRound, 0x2f89c512)                           \
+  V(_Double, floorToDouble, DoubleFloor, 0x6aa87a5f)                           \
+  V(_Double, ceilToDouble, DoubleCeil, 0x1b045e9e)                             \
+  V(_Double, _modulo, DoubleMod, 0x5b8ceed7)
+
+
+#define GRAPH_INTRINSICS_LIST(V)                                               \
+  GRAPH_CORE_INTRINSICS_LIST(V)                                                \
+  GRAPH_TYPED_DATA_INTRINSICS_LIST(V)                                          \
+  GRAPH_MATH_LIB_INTRINSIC_LIST(V)                                             \
+
+#define DEVELOPER_LIB_INTRINSIC_LIST(V)                                        \
+  V(_UserTag, makeCurrent, UserTag_makeCurrent, 0x0b3066fd)                    \
+  V(::, _getDefaultTag, UserTag_defaultTag, 0x69f3f1ad)                        \
+  V(::, _getCurrentTag, Profiler_getCurrentTag, 0x05fa99d2)                    \
+  V(::, _isDartStreamEnabled, Timeline_isDartStreamEnabled, 0x72f13f7a)        \
+
+#define ASYNC_LIB_INTRINSIC_LIST(V)                                            \
+  V(::, _clearAsyncThreadStackTrace, ClearAsyncThreadStackTrace, 0x2edd4b25)   \
+  V(::, _setAsyncThreadStackTrace, SetAsyncThreadStackTrace, 0x04f429a7)       \
+
+#define ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                  \
+  ASYNC_LIB_INTRINSIC_LIST(V)                                                  \
+  CORE_LIB_INTRINSIC_LIST(V)                                                   \
+  DEVELOPER_LIB_INTRINSIC_LIST(V)                                              \
+  MATH_LIB_INTRINSIC_LIST(V)                                                   \
+  TYPED_DATA_LIB_INTRINSIC_LIST(V)                                             \
+
+#define ALL_INTRINSICS_LIST(V)                                                 \
+  ALL_INTRINSICS_NO_INTEGER_LIB_LIST(V)                                        \
+  CORE_INTEGER_LIB_INTRINSIC_LIST(V)
+
+#define RECOGNIZED_LIST(V)                                                     \
+  OTHER_RECOGNIZED_LIST(V)                                                     \
+  ALL_INTRINSICS_LIST(V)                                                       \
+  GRAPH_INTRINSICS_LIST(V)
+
+// A list of core function that should always be inlined.
+#define INLINE_WHITE_LIST(V)                                                   \
+  V(Object, ==, ObjectEquals, 0x7b32a55a)                                      \
+  V(_List, get:length, ObjectArrayLength, 0x25952390)                          \
+  V(_ImmutableList, get:length, ImmutableArrayLength, 0x25952390)              \
+  V(_TypedList, get:length, TypedDataLength, 0x2091c4d8)                       \
+  V(_GrowableList, get:length, GrowableArrayLength, 0x18dd86b4)                \
+  V(_GrowableList, get:_capacity, GrowableArrayCapacity, 0x2e04be60)           \
+  V(_GrowableList, add, GrowableListAdd, 0x40b490b8)                           \
+  V(_GrowableList, removeLast, GrowableListRemoveLast, 0x007855e5)             \
+  V(_StringBase, get:length, StringBaseLength, 0x2a2d03d1)                     \
+  V(ListIterator, moveNext, ListIteratorMoveNext, 0x2dca30ce)                  \
+  V(_FixedSizeArrayIterator, moveNext, FixedListIteratorMoveNext, 0x324eb20b)  \
+  V(_GrowableList, get:iterator, GrowableArrayIterator, 0x5bd2ef37)            \
+  V(_GrowableList, forEach, GrowableArrayForEach, 0x74900bb8)                  \
+  V(_List, ., ObjectArrayAllocate, 0x2121902f)                                 \
+  V(ListMixin, get:isEmpty, ListMixinIsEmpty, 0x7be74d04)                      \
+  V(_List, get:iterator, ObjectArrayIterator, 0x6c851c55)                      \
+  V(_List, forEach, ObjectArrayForEach, 0x11406b13)                            \
+  V(_List, _slice, ObjectArraySlice, 0x4c865d1d)                               \
+  V(_ImmutableList, get:iterator, ImmutableArrayIterator, 0x6c851c55)          \
+  V(_ImmutableList, forEach, ImmutableArrayForEach, 0x11406b13)                \
+  V(_Int8ArrayView, [], Int8ArrayViewGetIndexed, 0x7e5a8458)                   \
+  V(_Int8ArrayView, []=, Int8ArrayViewSetIndexed, 0x62f615e4)                  \
+  V(_Uint8ArrayView, [], Uint8ArrayViewGetIndexed, 0x7d308247)                 \
+  V(_Uint8ArrayView, []=, Uint8ArrayViewSetIndexed, 0x65ba546e)                \
+  V(_Uint8ClampedArrayView, [], Uint8ClampedArrayViewGetIndexed, 0x7d308247)   \
+  V(_Uint8ClampedArrayView, []=, Uint8ClampedArrayViewSetIndexed, 0x65ba546e)  \
+  V(_Uint16ArrayView, [], Uint16ArrayViewGetIndexed, 0xe96836dd)               \
+  V(_Uint16ArrayView, []=, Uint16ArrayViewSetIndexed, 0x15b02947)              \
+  V(_Int16ArrayView, [], Int16ArrayViewGetIndexed, 0x1b24a48b)                 \
+  V(_Int16ArrayView, []=, Int16ArrayViewSetIndexed, 0xb91ec2e6)                \
+  V(_Uint32ArrayView, [], Uint32ArrayViewGetIndexed, 0x8a4f93b3)               \
+  V(_Uint32ArrayView, []=, Uint32ArrayViewSetIndexed, 0xf54918b5)              \
+  V(_Int32ArrayView, [], Int32ArrayViewGetIndexed, 0x85040819)                 \
+  V(_Int32ArrayView, []=, Int32ArrayViewSetIndexed, 0xaec8c6f5)                \
+  V(_Uint64ArrayView, [], Uint64ArrayViewGetIndexed, 0xd0c44fe7)               \
+  V(_Uint64ArrayView, []=, Uint64ArrayViewSetIndexed, 0x402712b7)              \
+  V(_Int64ArrayView, [], Int64ArrayViewGetIndexed, 0xf3090b95)                 \
+  V(_Int64ArrayView, []=, Int64ArrayViewSetIndexed, 0xca07e497)                \
+  V(_Float32ArrayView, [], Float32ArrayViewGetIndexed, 0xef967533)             \
+  V(_Float32ArrayView, []=, Float32ArrayViewSetIndexed, 0xc9b691bd)            \
+  V(_Float64ArrayView, [], Float64ArrayViewGetIndexed, 0x9d83f585)             \
+  V(_Float64ArrayView, []=, Float64ArrayViewSetIndexed, 0x3c1adabd)            \
+  V(_ByteDataView, setInt8, ByteDataViewSetInt8, 0x6395293e)                   \
+  V(_ByteDataView, setUint8, ByteDataViewSetUint8, 0x79979d1f)                 \
+  V(_ByteDataView, setInt16, ByteDataViewSetInt16, 0x525ec534)                 \
+  V(_ByteDataView, setUint16, ByteDataViewSetUint16, 0x48eda263)               \
+  V(_ByteDataView, setInt32, ByteDataViewSetInt32, 0x523666fa)                 \
+  V(_ByteDataView, setUint32, ByteDataViewSetUint32, 0x5a4683da)               \
+  V(_ByteDataView, setInt64, ByteDataViewSetInt64, 0x4283a650)                 \
+  V(_ByteDataView, setUint64, ByteDataViewSetUint64, 0x687a1892)               \
+  V(_ByteDataView, setFloat32, ByteDataViewSetFloat32, 0x7d5784fd)             \
+  V(_ByteDataView, setFloat64, ByteDataViewSetFloat64, 0x00101e3f)             \
+  V(_ByteDataView, getInt8, ByteDataViewGetInt8, 0x68448b4d)                   \
+  V(_ByteDataView, getUint8, ByteDataViewGetUint8, 0x5d68cbf2)                 \
+  V(_ByteDataView, getInt16, ByteDataViewGetInt16, 0x691b5ead)                 \
+  V(_ByteDataView, getUint16, ByteDataViewGetUint16, 0x78b744d8)               \
+  V(_ByteDataView, getInt32, ByteDataViewGetInt32, 0x3a0f4efa)                 \
+  V(_ByteDataView, getUint32, ByteDataViewGetUint32, 0x583261be)               \
+  V(_ByteDataView, getInt64, ByteDataViewGetInt64, 0x77de471c)                 \
+  V(_ByteDataView, getUint64, ByteDataViewGetUint64, 0x0ffadc4b)               \
+  V(_ByteDataView, getFloat32, ByteDataViewGetFloat32, 0x6a205749)             \
+  V(_ByteDataView, getFloat64, ByteDataViewGetFloat64, 0x69f58d27)             \
+  V(::, exp, MathExp, 0x32ab9efa)                                              \
+  V(::, log, MathLog, 0x1ee8f9fc)                                              \
+  V(::, max, MathMax, 0x377e8889)                                              \
+  V(::, min, MathMin, 0x32ebc57d)                                              \
+  V(::, pow, MathPow, 0x79efc5a2)                                              \
+  V(::, _classRangeCheck, ClassRangeCheck, 0x2ae76b84)                         \
+  V(::, _classRangeCheckNegative, ClassRangeCheckNegated, 0x5acdfb75)          \
+  V(::, _toInt, ConvertMaskedInt, 0x713908fd)                                  \
+  V(::, _toInt8, ConvertIntToInt8, 0x7484a780)                                 \
+  V(::, _toUint8, ConvertIntToUint8, 0x0a15b522)                               \
+  V(::, _toInt16, ConvertIntToInt16, 0x0a83fcc6)                               \
+  V(::, _toUint16, ConvertIntToUint16, 0x6087d1af)                             \
+  V(::, _toInt32, ConvertIntToInt32, 0x62b451b9)                               \
+  V(::, _toUint32, ConvertIntToUint32, 0x17a8e085)                             \
+  V(::, _byteSwap16, ByteSwap16, 0x44f173be)                                   \
+  V(::, _byteSwap32, ByteSwap32, 0x6219333b)                                   \
+  V(::, _byteSwap64, ByteSwap64, 0x9abe57e0)                                   \
+  V(Lists, copy, ListsCopy, 0x40e974f6)                                        \
+  V(_HashVMBase, get:_index, LinkedHashMap_getIndex, 0x02477157)               \
+  V(_HashVMBase, set:_index, LinkedHashMap_setIndex, 0x4fc8d5e0)               \
+  V(_HashVMBase, get:_data, LinkedHashMap_getData, 0x2d7a70ac)                 \
+  V(_HashVMBase, set:_data, LinkedHashMap_setData, 0x0ec032e8)                 \
+  V(_HashVMBase, get:_usedData, LinkedHashMap_getUsedData, 0x088599ed)         \
+  V(_HashVMBase, set:_usedData, LinkedHashMap_setUsedData, 0x5f42ca86)         \
+  V(_HashVMBase, get:_hashMask, LinkedHashMap_getHashMask, 0x32f3b13b)         \
+  V(_HashVMBase, set:_hashMask, LinkedHashMap_setHashMask, 0x7219c45b)         \
+  V(_HashVMBase, get:_deletedKeys, LinkedHashMap_getDeletedKeys, 0x558481c2)   \
+  V(_HashVMBase, set:_deletedKeys, LinkedHashMap_setDeletedKeys, 0x5aa9888d)   \
+
+// A list of core function that should never be inlined.
+#define INLINE_BLACK_LIST(V)                                                   \
+  V(::, asin, MathAsin, 0x2ecc2fcd)                                            \
+  V(::, acos, MathAcos, 0x08cf2212)                                            \
+  V(::, atan, MathAtan, 0x1e2731d5)                                            \
+  V(::, atan2, MathAtan2, 0x39f1fa41)                                          \
+  V(::, cos, MathCos, 0x459bf5fe)                                              \
+  V(::, sin, MathSin, 0x6b7bd98c)                                              \
+  V(::, sqrt, MathSqrt, 0x70482cf3)                                            \
+  V(::, tan, MathTan, 0x3bcd772a)                                              \
+  V(_BigIntImpl, _lsh, Bigint_lsh, 0x5b6cfc8b)                                 \
+  V(_BigIntImpl, _rsh, Bigint_rsh, 0x6ff14a49)                                 \
+  V(_BigIntImpl, _absAdd, Bigint_absAdd, 0x5bf14238)                           \
+  V(_BigIntImpl, _absSub, Bigint_absSub, 0x1de5bd32)                           \
+  V(_BigIntImpl, _mulAdd, Bigint_mulAdd, 0x6f277966)                           \
+  V(_BigIntImpl, _sqrAdd, Bigint_sqrAdd, 0x68e4c8ea)                           \
+  V(_BigIntImpl, _estimateQuotientDigit, Bigint_estimateQuotientDigit,         \
+    0x35456d91)                                                                \
+  V(_BigIntMontgomeryReduction, _mulMod, Montgomery_mulMod, 0x0f7b0375)        \
+  V(_Double, >, Double_greaterThan, 0x4f1375a3)                                \
+  V(_Double, >=, Double_greaterEqualThan, 0x4260c184)                          \
+  V(_Double, <, Double_lessThan, 0x365d1eba)                                   \
+  V(_Double, <=, Double_lessEqualThan, 0x74b5eb64)                             \
+  V(_Double, ==, Double_equal, 0x613492fc)                                     \
+  V(_Double, +, Double_add, 0x53994370)                                        \
+  V(_Double, -, Double_sub, 0x3b69d466)                                        \
+  V(_Double, *, Double_mul, 0x2bb9bd5d)                                        \
+  V(_Double, /, Double_div, 0x483eee28)                                        \
+  V(_IntegerImplementation, +, Integer_add, 0x43d53af7)                        \
+  V(_IntegerImplementation, -, Integer_sub, 0x2dc22e03)                        \
+  V(_IntegerImplementation, *, Integer_mul, 0x4e7a1c24)                        \
+  V(_IntegerImplementation, ~/, Integer_truncDivide, 0x4efb2d39)               \
+  V(_IntegerImplementation, unary-, Integer_negate, 0x428bf6fa)                \
+  V(_IntegerImplementation, &, Integer_bitAnd, 0x5ab35f30)                     \
+  V(_IntegerImplementation, |, Integer_bitOr, 0x267fa107)                      \
+  V(_IntegerImplementation, ^, Integer_bitXor, 0x0c7b0230)                     \
+  V(_IntegerImplementation, >, Integer_greaterThan, 0x6599a6e1)                \
+  V(_IntegerImplementation, ==, Integer_equal, 0x58abc487)                     \
+  V(_IntegerImplementation, <, Integer_lessThan, 0x365d1eba)                   \
+  V(_IntegerImplementation, <=, Integer_lessEqualThan, 0x74b5eb64)             \
+  V(_IntegerImplementation, >=, Integer_greaterEqualThan, 0x4260c184)          \
+  V(_IntegerImplementation, <<, Integer_shl, 0x371c45fa)                       \
+  V(_IntegerImplementation, >>, Integer_sar, 0x2b630578)                       \
+
+// A list of core functions that internally dispatch based on received id.
+#define POLYMORPHIC_TARGET_LIST(V)                                             \
+  V(_StringBase, [], StringBaseCharAt, 0x7cbb8603)                             \
+  V(_TypedList, _getInt8, ByteArrayBaseGetInt8, 0x7041895a)                    \
+  V(_TypedList, _getUint8, ByteArrayBaseGetUint8, 0x336fa3ea)                  \
+  V(_TypedList, _getInt16, ByteArrayBaseGetInt16, 0x231bbe2e)                  \
+  V(_TypedList, _getUint16, ByteArrayBaseGetUint16, 0x0371785f)                \
+  V(_TypedList, _getInt32, ByteArrayBaseGetInt32, 0x65ab3a20)                  \
+  V(_TypedList, _getUint32, ByteArrayBaseGetUint32, 0x0cb0fcf6)                \
+  V(_TypedList, _getInt64, ByteArrayBaseGetInt64, 0x7db75d78)                  \
+  V(_TypedList, _getUint64, ByteArrayBaseGetUint64, 0x1487cfc6)                \
+  V(_TypedList, _getFloat32, ByteArrayBaseGetFloat32, 0x6674ea6f)              \
+  V(_TypedList, _getFloat64, ByteArrayBaseGetFloat64, 0x236c6e7a)              \
+  V(_TypedList, _getFloat32x4, ByteArrayBaseGetFloat32x4, 0x5c367ffb)          \
+  V(_TypedList, _getInt32x4, ByteArrayBaseGetInt32x4, 0x772d1c0f)              \
+  V(_TypedList, _setInt8, ByteArrayBaseSetInt8, 0x12bae36a)                    \
+  V(_TypedList, _setUint8, ByteArrayBaseSetInt8, 0x15821cc9)                   \
+  V(_TypedList, _setInt16, ByteArrayBaseSetInt16, 0x1f8237fa)                  \
+  V(_TypedList, _setUint16, ByteArrayBaseSetInt16, 0x181e5d16)                 \
+  V(_TypedList, _setInt32, ByteArrayBaseSetInt32, 0x7ddb9f87)                  \
+  V(_TypedList, _setUint32, ByteArrayBaseSetUint32, 0x74094f8d)                \
+  V(_TypedList, _setInt64, ByteArrayBaseSetInt64, 0x4741396e)                  \
+  V(_TypedList, _setUint64, ByteArrayBaseSetUint64, 0x3b398ae4)                \
+  V(_TypedList, _setFloat32, ByteArrayBaseSetFloat32, 0x03db087b)              \
+  V(_TypedList, _setFloat64, ByteArrayBaseSetFloat64, 0x38a80b0d)              \
+  V(_TypedList, _setFloat32x4, ByteArrayBaseSetFloat32x4, 0x40052c4e)          \
+  V(_TypedList, _setInt32x4, ByteArrayBaseSetInt32x4, 0x07b89f54)              \
+  V(Object, get:runtimeType, ObjectRuntimeType, 0x00e8ab29)
+
+// List of recognized list factories:
+// (factory-name-symbol, class-name-string, constructor-name-string,
+//  result-cid, fingerprint).
+#define RECOGNIZED_LIST_FACTORY_LIST(V)                                        \
+  V(_ListFactory, _List, ., kArrayCid, 0x2121902f)                             \
+  V(_GrowableListWithData, _GrowableList, .withData, kGrowableObjectArrayCid,  \
+    0x28b2138e)                                                                \
+  V(_GrowableListFactory, _GrowableList, ., kGrowableObjectArrayCid,           \
+    0x3eed680b)                                                                \
+  V(_Int8ArrayFactory, Int8List, ., kTypedDataInt8ArrayCid, 0x7e39a3a1)        \
+  V(_Uint8ArrayFactory, Uint8List, ., kTypedDataUint8ArrayCid, 0x3a79adf7)     \
+  V(_Uint8ClampedArrayFactory, Uint8ClampedList, .,                            \
+    kTypedDataUint8ClampedArrayCid, 0x67f38395)                                \
+  V(_Int16ArrayFactory, Int16List, ., kTypedDataInt16ArrayCid, 0x6477bda8)     \
+  V(_Uint16ArrayFactory, Uint16List, ., kTypedDataUint16ArrayCid, 0x5707c5a2)  \
+  V(_Int32ArrayFactory, Int32List, ., kTypedDataInt32ArrayCid, 0x2b96ec0e)     \
+  V(_Uint32ArrayFactory, Uint32List, ., kTypedDataUint32ArrayCid, 0x0c1c0d62)  \
+  V(_Int64ArrayFactory, Int64List, ., kTypedDataInt64ArrayCid, 0x279ab485)     \
+  V(_Uint64ArrayFactory, Uint64List, ., kTypedDataUint64ArrayCid, 0x7bcb89c2)  \
+  V(_Float64ArrayFactory, Float64List, ., kTypedDataFloat64ArrayCid,           \
+    0x1fde3eaf)                                                                \
+  V(_Float32ArrayFactory, Float32List, ., kTypedDataFloat32ArrayCid,           \
+    0x43506c09)                                                                \
+  V(_Float32x4ArrayFactory, Float32x4List, ., kTypedDataFloat32x4ArrayCid,     \
+    0x4a4030d6)
+
+// clang-format on
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_RECOGNIZED_METHODS_LIST_H_
diff --git a/runtime/vm/compiler/relocation.cc b/runtime/vm/compiler/relocation.cc
index 83ff87c..467aa78 100644
--- a/runtime/vm/compiler/relocation.cc
+++ b/runtime/vm/compiler/relocation.cc
@@ -106,7 +106,7 @@
 
   for (intptr_t i = 0; i < code_objects_->length(); ++i) {
     current_caller = (*code_objects_)[i];
-    const intptr_t size = current_caller.instructions()->Size();
+    const intptr_t size = current_caller.instructions()->HeapSize();
     if (size > max_instructions_size_) {
       max_instructions_size_ = size;
     }
@@ -181,7 +181,7 @@
   }
   text_offsets_.Insert({instructions, next_text_offset_});
   commands_->Add(ImageWriterCommand(next_text_offset_, code));
-  next_text_offset_ += instructions->Size();
+  next_text_offset_ += instructions->HeapSize();
 
   return true;
 }
diff --git a/runtime/vm/compiler/runtime_api.cc b/runtime/vm/compiler/runtime_api.cc
index 9431ff2..aca31eb 100644
--- a/runtime/vm/compiler/runtime_api.cc
+++ b/runtime/vm/compiler/runtime_api.cc
@@ -6,8 +6,15 @@
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/dart_entry.h"
 #include "vm/longjump.h"
+#include "vm/native_arguments.h"
+#include "vm/native_entry.h"
 #include "vm/object.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/symbols.h"
+#include "vm/timeline.h"
 
 namespace dart {
 namespace compiler {
@@ -20,6 +27,11 @@
   return obj.IsNotTemporaryScopedHandle();
 }
 
+#define DO(clazz)                                                              \
+  bool Is##clazz##Handle(const Object& obj) { return obj.Is##clazz(); }
+CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+
 bool IsInOldSpace(const Object& obj) {
   return obj.IsOld();
 }
@@ -57,6 +69,53 @@
   return Object::ZoneHandle(zone, obj.raw());
 }
 
+const Object& NullObject() {
+  return Object::null_object();
+}
+
+const Bool& TrueObject() {
+  return dart::Bool::True();
+}
+
+const Bool& FalseObject() {
+  return dart::Bool::False();
+}
+
+const Object& EmptyTypeArguments() {
+  return Object::empty_type_arguments();
+}
+
+const Type& DynamicType() {
+  return dart::Type::dynamic_type();
+}
+
+const Type& ObjectType() {
+  return Type::Handle(dart::Type::ObjectType());
+}
+
+const Type& VoidType() {
+  return dart::Type::void_type();
+}
+
+const Type& IntType() {
+  return Type::Handle(dart::Type::IntType());
+}
+
+const Class& GrowableObjectArrayClass() {
+  auto object_store = Isolate::Current()->object_store();
+  return Class::Handle(object_store->growable_object_array_class());
+}
+
+const Class& MintClass() {
+  auto object_store = Isolate::Current()->object_store();
+  return Class::Handle(object_store->mint_class());
+}
+
+const Class& DoubleClass() {
+  auto object_store = Isolate::Current()->object_store();
+  return Class::Handle(object_store->double_class());
+}
+
 bool IsOriginalObject(const Object& object) {
   if (object.IsICData()) {
     return ICData::Cast(object).IsOriginal();
@@ -82,12 +141,69 @@
   return static_cast<int32_t>(Isolate::Current()->random()->NextUInt32());
 }
 
+word TypedDataElementSizeInBytes(classid_t cid) {
+  return dart::TypedData::ElementSizeInBytes(cid);
+}
+
+word TypedDataMaxNewSpaceElements(classid_t cid) {
+  return dart::TypedData::MaxNewSpaceElements(cid);
+}
+
+const Field& LookupMathRandomStateFieldOffset() {
+  const auto& math_lib = dart::Library::Handle(dart::Library::MathLibrary());
+  ASSERT(!math_lib.IsNull());
+  const auto& random_class = dart::Class::Handle(
+      math_lib.LookupClassAllowPrivate(dart::Symbols::_Random()));
+  ASSERT(!random_class.IsNull());
+  const auto& state_field = dart::Field::ZoneHandle(
+      random_class.LookupInstanceFieldAllowPrivate(dart::Symbols::_state()));
+  return state_field;
+}
+
+word LookupFieldOffsetInBytes(const Field& field) {
+  return field.Offset();
+}
+
+#if defined(TARGET_ARCH_IA32)
+uword SymbolsPredefinedAddress() {
+  return reinterpret_cast<uword>(dart::Symbols::PredefinedAddress());
+}
+#endif
+
+#if !defined(TARGET_ARCH_DBC)
+const Code& StubCodeAllocateArray() {
+  return dart::StubCode::AllocateArray();
+}
+
+const Code& StubCodeSubtype2TestCache() {
+  return dart::StubCode::Subtype2TestCache();
+}
+
+const Code& StubCodeSubtype6TestCache() {
+  return dart::StubCode::Subtype6TestCache();
+}
+#endif  // !defined(TARGET_ARCH_DBC)
+
+#define DEFINE_ALIAS(name)                                                     \
+  const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry);
+RUNTIME_ENTRY_LIST(DEFINE_ALIAS)
+#undef DEFINE_ALIAS
+
+#define DEFINE_ALIAS(type, name, ...)                                          \
+  const RuntimeEntry& k##name##RuntimeEntry(dart::k##name##RuntimeEntry);
+LEAF_RUNTIME_ENTRY_LIST(DEFINE_ALIAS)
+#undef DEFINE_ALIAS
+
 void BailoutWithBranchOffsetError() {
   Thread::Current()->long_jump_base()->Jump(1, Object::branch_offset_error());
 }
 
 namespace target {
 
+const word kPageSize = dart::kPageSize;
+const word kPageSizeInWords = dart::kPageSizeInWords;
+const word kPageMask = dart::kPageMask;
+
 uint32_t MakeTagWordForNewSpaceObject(classid_t cid, uword instance_size) {
   return dart::RawObject::SizeTag::encode(instance_size) |
          dart::RawObject::ClassIdTag::encode(cid) |
@@ -98,10 +214,27 @@
   return dart::Object::tags_offset();
 }
 
+const word RawObject::kCardRememberedBit = dart::RawObject::kCardRememberedBit;
+
+const word RawObject::kOldAndNotRememberedBit =
+    dart::RawObject::kOldAndNotRememberedBit;
+
+const word RawObject::kOldAndNotMarkedBit =
+    dart::RawObject::kOldAndNotMarkedBit;
+
 const word RawObject::kClassIdTagPos = dart::RawObject::kClassIdTagPos;
 
 const word RawObject::kClassIdTagSize = dart::RawObject::kClassIdTagSize;
 
+const word RawObject::kSizeTagMaxSizeTag =
+    dart::RawObject::SizeTag::kMaxSizeTag;
+
+const word RawObject::kTagBitsSizeTagPos =
+    dart::RawObject::TagBits::kSizeTagPos;
+
+const word RawAbstractType::kTypeStateFinalizedInstantiated =
+    dart::RawAbstractType::kFinalizedInstantiated;
+
 const word RawObject::kBarrierOverlapShift =
     dart::RawObject::kBarrierOverlapShift;
 
@@ -109,6 +242,20 @@
   return dart::ObjectPool::element_offset(index);
 }
 
+word Class::type_arguments_field_offset_in_words_offset() {
+  return dart::Class::type_arguments_field_offset_in_words_offset();
+}
+
+word Class::declaration_type_offset() {
+  return dart::Class::declaration_type_offset();
+}
+
+word Class::num_type_arguments_offset_in_bytes() {
+  return dart::Class::num_type_arguments_offset();
+}
+
+const word Class::kNoTypeArguments = dart::Class::kNoTypeArguments;
+
 classid_t Class::GetId(const dart::Class& handle) {
   return handle.id();
 }
@@ -117,27 +264,263 @@
   return handle.instance_size();
 }
 
+intptr_t Class::NumTypeArguments(const dart::Class& klass) {
+  return klass.NumTypeArguments() > 0;
+}
+
+bool Class::HasTypeArgumentsField(const dart::Class& klass) {
+  return klass.type_arguments_field_offset() != dart::Class::kNoTypeArguments;
+}
+
+intptr_t Class::TypeArgumentsFieldOffset(const dart::Class& klass) {
+  return klass.type_arguments_field_offset();
+}
+
+intptr_t Class::InstanceSize(const dart::Class& klass) {
+  return klass.instance_size();
+}
+
+bool Class::TraceAllocation(const dart::Class& klass) {
+  return klass.TraceAllocation(dart::Isolate::Current());
+}
+
+word Instance::first_field_offset() {
+  return dart::Instance::NextFieldOffset();
+}
+
 word Instance::DataOffsetFor(intptr_t cid) {
   return dart::Instance::DataOffsetFor(cid);
 }
 
+word Instance::ElementSizeFor(intptr_t cid) {
+  return dart::Instance::ElementSizeFor(cid);
+}
+
+word Function::code_offset() {
+  return dart::Function::code_offset();
+}
+
+word Function::entry_point_offset() {
+  return dart::Function::entry_point_offset();
+}
+
+word Function::usage_counter_offset() {
+  return dart::Function::usage_counter_offset();
+}
+
+word Function::unchecked_entry_point_offset() {
+  return dart::Function::unchecked_entry_point_offset();
+}
+
+word ICData::CodeIndexFor(word num_args) {
+  return dart::ICData::CodeIndexFor(num_args);
+}
+
+word ICData::owner_offset() {
+  return dart::ICData::owner_offset();
+}
+
+word ICData::arguments_descriptor_offset() {
+  return dart::ICData::arguments_descriptor_offset();
+}
+
+word ICData::entries_offset() {
+  return dart::ICData::entries_offset();
+}
+
+word ICData::static_receiver_type_offset() {
+  return dart::ICData::static_receiver_type_offset();
+}
+
+word ICData::state_bits_offset() {
+  return dart::ICData::state_bits_offset();
+}
+
+word ICData::CountIndexFor(word num_args) {
+  return dart::ICData::CountIndexFor(num_args);
+}
+
+word ICData::TargetIndexFor(word num_args) {
+  return dart::ICData::TargetIndexFor(num_args);
+}
+
+word ICData::ExactnessOffsetFor(word num_args) {
+  return dart::ICData::ExactnessOffsetFor(num_args);
+}
+
+word ICData::TestEntryLengthFor(word num_args, bool exactness_check) {
+  return dart::ICData::TestEntryLengthFor(num_args, exactness_check);
+}
+
+word ICData::EntryPointIndexFor(word num_args) {
+  return dart::ICData::EntryPointIndexFor(num_args);
+}
+
+word ICData::NumArgsTestedShift() {
+  return dart::ICData::NumArgsTestedShift();
+}
+
+word ICData::NumArgsTestedMask() {
+  return dart::ICData::NumArgsTestedMask();
+}
+
+const word MegamorphicCache::kSpreadFactor =
+    dart::MegamorphicCache::kSpreadFactor;
+
+word MegamorphicCache::mask_offset() {
+  return dart::MegamorphicCache::mask_offset();
+}
+word MegamorphicCache::buckets_offset() {
+  return dart::MegamorphicCache::buckets_offset();
+}
+word MegamorphicCache::arguments_descriptor_offset() {
+  return dart::MegamorphicCache::arguments_descriptor_offset();
+}
+
+word SingleTargetCache::lower_limit_offset() {
+  return dart::SingleTargetCache::lower_limit_offset();
+}
+word SingleTargetCache::upper_limit_offset() {
+  return dart::SingleTargetCache::upper_limit_offset();
+}
+word SingleTargetCache::entry_point_offset() {
+  return dart::SingleTargetCache::entry_point_offset();
+}
+word SingleTargetCache::target_offset() {
+  return dart::SingleTargetCache::target_offset();
+}
+
+const word Array::kMaxNewSpaceElements = dart::Array::kMaxNewSpaceElements;
+
+word Context::InstanceSize(word n) {
+  return dart::Context::InstanceSize(n);
+}
+
+word Context::variable_offset(word n) {
+  return dart::Context::variable_offset(n);
+}
+
+word TypedData::InstanceSize() {
+  return sizeof(RawTypedData);
+}
+
+word Array::header_size() {
+  return sizeof(dart::RawArray);
+}
+
+#define CLASS_NAME_LIST(V)                                                     \
+  V(AbstractType, type_test_stub_entry_point_offset)                           \
+  V(ArgumentsDescriptor, count_offset)                                         \
+  V(ArgumentsDescriptor, type_args_len_offset)                                 \
+  V(Array, data_offset)                                                        \
+  V(Array, length_offset)                                                      \
+  V(Array, tags_offset)                                                        \
+  V(Array, type_arguments_offset)                                              \
+  V(ClassTable, table_offset)                                                  \
+  V(Closure, context_offset)                                                   \
+  V(Closure, delayed_type_arguments_offset)                                    \
+  V(Closure, function_offset)                                                  \
+  V(Closure, function_type_arguments_offset)                                   \
+  V(Closure, instantiator_type_arguments_offset)                               \
+  V(Code, object_pool_offset)                                                  \
+  V(Code, saved_instructions_offset)                                           \
+  V(Context, num_variables_offset)                                             \
+  V(Context, parent_offset)                                                    \
+  V(Double, value_offset)                                                      \
+  V(Float32x4, value_offset)                                                   \
+  V(Float64x2, value_offset)                                                   \
+  V(GrowableObjectArray, data_offset)                                          \
+  V(GrowableObjectArray, length_offset)                                        \
+  V(GrowableObjectArray, type_arguments_offset)                                \
+  V(HeapPage, card_table_offset)                                               \
+  V(Isolate, class_table_offset)                                               \
+  V(Isolate, current_tag_offset)                                               \
+  V(Isolate, default_tag_offset)                                               \
+  V(Isolate, ic_miss_code_offset)                                              \
+  V(Isolate, object_store_offset)                                              \
+  V(Isolate, user_tag_offset)                                                  \
+  V(MarkingStackBlock, pointers_offset)                                        \
+  V(MarkingStackBlock, top_offset)                                             \
+  V(Mint, value_offset)                                                        \
+  V(NativeArguments, argc_tag_offset)                                          \
+  V(NativeArguments, argv_offset)                                              \
+  V(NativeArguments, retval_offset)                                            \
+  V(NativeArguments, thread_offset)                                            \
+  V(ObjectStore, double_type_offset)                                           \
+  V(ObjectStore, int_type_offset)                                              \
+  V(ObjectStore, string_type_offset)                                           \
+  V(OneByteString, data_offset)                                                \
+  V(StoreBufferBlock, pointers_offset)                                         \
+  V(StoreBufferBlock, top_offset)                                              \
+  V(String, hash_offset)                                                       \
+  V(String, length_offset)                                                     \
+  V(SubtypeTestCache, cache_offset)                                            \
+  V(Thread, active_exception_offset)                                           \
+  V(Thread, active_stacktrace_offset)                                          \
+  V(Thread, async_stack_trace_offset)                                          \
+  V(Thread, auto_scope_native_wrapper_entry_point_offset)                      \
+  V(Thread, bool_false_offset)                                                 \
+  V(Thread, bool_true_offset)                                                  \
+  V(Thread, dart_stream_offset)                                                \
+  V(Thread, end_offset)                                                        \
+  V(Thread, global_object_pool_offset)                                         \
+  V(Thread, isolate_offset)                                                    \
+  V(Thread, marking_stack_block_offset)                                        \
+  V(Thread, no_scope_native_wrapper_entry_point_offset)                        \
+  V(Thread, object_null_offset)                                                \
+  V(Thread, predefined_symbols_address_offset)                                 \
+  V(Thread, resume_pc_offset)                                                  \
+  V(Thread, store_buffer_block_offset)                                         \
+  V(Thread, top_exit_frame_info_offset)                                        \
+  V(Thread, top_offset)                                                        \
+  V(Thread, top_resource_offset)                                               \
+  V(Thread, vm_tag_offset)                                                     \
+  V(TimelineStream, enabled_offset)                                            \
+  V(TwoByteString, data_offset)                                                \
+  V(Type, arguments_offset)                                                    \
+  V(TypedData, data_offset)                                                    \
+  V(TypedData, length_offset)                                                  \
+  V(Type, hash_offset)                                                         \
+  V(TypeRef, type_offset)                                                      \
+  V(Type, signature_offset)                                                    \
+  V(Type, type_state_offset)                                                   \
+  V(UserTag, tag_offset)
+
+#define DEFINE_FORWARDER(clazz, name)                                          \
+  word clazz::name() { return dart::clazz::name(); }
+
+CLASS_NAME_LIST(DEFINE_FORWARDER)
+#undef DEFINE_FORWARDER
+
+const word HeapPage::kBytesPerCardLog2 = dart::HeapPage::kBytesPerCardLog2;
+
+const word String::kHashBits = dart::String::kHashBits;
+
+word String::InstanceSize() {
+  return sizeof(dart::RawString);
+}
+
 bool Heap::IsAllocatableInNewSpace(intptr_t instance_size) {
   return dart::Heap::IsAllocatableInNewSpace(instance_size);
 }
 
-word Thread::top_offset() {
-  return dart::Thread::top_offset();
-}
-
-word Thread::end_offset() {
-  return dart::Thread::end_offset();
-}
-
-word Thread::isolate_offset() {
-  return dart::Thread::isolate_offset();
-}
-
 #if !defined(TARGET_ARCH_DBC)
+word Thread::write_barrier_code_offset() {
+  return dart::Thread::write_barrier_code_offset();
+}
+
+word Thread::array_write_barrier_code_offset() {
+  return dart::Thread::array_write_barrier_code_offset();
+}
+
+word Thread::fix_callers_target_code_offset() {
+  return dart::Thread::fix_callers_target_code_offset();
+}
+
+word Thread::fix_allocation_stub_code_offset() {
+  return dart::Thread::fix_allocation_stub_code_offset();
+}
+
 word Thread::call_to_runtime_entry_point_offset() {
   return dart::Thread::call_to_runtime_entry_point_offset();
 }
@@ -175,10 +558,70 @@
 }
 #endif
 
-word Thread::vm_tag_offset() {
-  return dart::Thread::vm_tag_offset();
+#if !defined(TARGET_ARCH_DBC)
+
+word Thread::monomorphic_miss_stub_offset() {
+  return dart::Thread::monomorphic_miss_stub_offset();
 }
 
+word Thread::ic_lookup_through_code_stub_offset() {
+  return dart::Thread::ic_lookup_through_code_stub_offset();
+}
+
+word Thread::lazy_specialize_type_test_stub_offset() {
+  return dart::Thread::lazy_specialize_type_test_stub_offset();
+}
+
+word Thread::slow_type_test_stub_offset() {
+  return dart::Thread::slow_type_test_stub_offset();
+}
+
+word Thread::call_to_runtime_stub_offset() {
+  return dart::Thread::call_to_runtime_stub_offset();
+}
+
+word Thread::invoke_dart_code_stub_offset() {
+  return dart::Thread::invoke_dart_code_stub_offset();
+}
+
+word Thread::interpret_call_entry_point_offset() {
+  return dart::Thread::interpret_call_entry_point_offset();
+}
+
+word Thread::invoke_dart_code_from_bytecode_stub_offset() {
+  return dart::Thread::invoke_dart_code_from_bytecode_stub_offset();
+}
+
+word Thread::null_error_shared_without_fpu_regs_stub_offset() {
+  return dart::Thread::null_error_shared_without_fpu_regs_stub_offset();
+}
+
+word Thread::null_error_shared_with_fpu_regs_stub_offset() {
+  return dart::Thread::null_error_shared_with_fpu_regs_stub_offset();
+}
+
+word Thread::stack_overflow_shared_without_fpu_regs_stub_offset() {
+  return dart::Thread::stack_overflow_shared_without_fpu_regs_stub_offset();
+}
+
+word Thread::stack_overflow_shared_with_fpu_regs_stub_offset() {
+  return dart::Thread::stack_overflow_shared_with_fpu_regs_stub_offset();
+}
+
+word Thread::lazy_deopt_from_return_stub_offset() {
+  return dart::Thread::lazy_deopt_from_return_stub_offset();
+}
+
+word Thread::lazy_deopt_from_throw_stub_offset() {
+  return dart::Thread::lazy_deopt_from_throw_stub_offset();
+}
+
+word Thread::deoptimize_stub_offset() {
+  return dart::Thread::deoptimize_stub_offset();
+}
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
 #define DECLARE_CONSTANT_OFFSET_GETTER(name)                                   \
   word Thread::name##_address_offset() {                                       \
     return dart::Thread::name##_address_offset();                              \
@@ -186,13 +629,19 @@
 THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
 #undef DECLARE_CONSTANT_OFFSET_GETTER
 
-word Isolate::class_table_offset() {
-  return dart::Isolate::class_table_offset();
+word Thread::OffsetFromThread(const dart::Object& object) {
+  return dart::Thread::OffsetFromThread(object);
 }
 
-word ClassTable::table_offset() {
-  return dart::ClassTable::table_offset();
+const word StoreBufferBlock::kSize = dart::StoreBufferBlock::kSize;
+
+const word MarkingStackBlock::kSize = dart::MarkingStackBlock::kSize;
+
+#if !defined(PRODUCT)
+word Isolate::single_step_offset() {
+  return dart::Isolate::single_step_offset();
 }
+#endif  // !defined(PRODUCT)
 
 #if !defined(PRODUCT)
 word ClassTable::ClassOffsetFor(intptr_t cid) {
@@ -228,18 +677,30 @@
   return dart::Instructions::HeaderSize();
 }
 
-intptr_t Code::object_pool_offset() {
-  return dart::Code::object_pool_offset();
-}
-
-intptr_t Code::saved_instructions_offset() {
-  return dart::Code::saved_instructions_offset();
-}
-
 intptr_t Code::entry_point_offset(CodeEntryKind kind) {
   return dart::Code::entry_point_offset(kind);
 }
 
+const word SubtypeTestCache::kTestEntryLength =
+    dart::SubtypeTestCache::kTestEntryLength;
+const word SubtypeTestCache::kInstanceClassIdOrFunction =
+    dart::SubtypeTestCache::kInstanceClassIdOrFunction;
+const word SubtypeTestCache::kInstanceTypeArguments =
+    dart::SubtypeTestCache::kInstanceTypeArguments;
+const word SubtypeTestCache::kInstantiatorTypeArguments =
+    dart::SubtypeTestCache::kInstantiatorTypeArguments;
+const word SubtypeTestCache::kFunctionTypeArguments =
+    dart::SubtypeTestCache::kFunctionTypeArguments;
+const word SubtypeTestCache::kInstanceParentFunctionTypeArguments =
+    dart::SubtypeTestCache::kInstanceParentFunctionTypeArguments;
+const word SubtypeTestCache::kInstanceDelayedFunctionTypeArguments =
+    dart::SubtypeTestCache::kInstanceDelayedFunctionTypeArguments;
+const word SubtypeTestCache::kTestResult = dart::SubtypeTestCache::kTestResult;
+
+word Context::header_size() {
+  return sizeof(dart::RawContext);
+}
+
 #if !defined(PRODUCT)
 word ClassHeapStats::TraceAllocationMask() {
   return dart::ClassHeapStats::TraceAllocationMask();
@@ -258,18 +719,7 @@
 }
 #endif  // !defined(PRODUCT)
 
-word Double::value_offset() {
-  return dart::Double::value_offset();
-}
-
-word Float32x4::value_offset() {
-  return dart::Float32x4::value_offset();
-}
-
-word Float64x2::value_offset() {
-  return dart::Float64x2::value_offset();
-}
-
+const word Smi::kBits = dart::Smi::kBits;
 bool IsSmi(const dart::Object& a) {
   return a.IsSmi();
 }
@@ -314,6 +764,22 @@
 }
 #endif  // defined(TARGET_ARCH_IA32)
 
+const word NativeEntry::kNumCallWrapperArguments =
+    dart::NativeEntry::kNumCallWrapperArguments;
+
+word NativeArguments::StructSize() {
+  return sizeof(dart::NativeArguments);
+}
+
+word RegExp::function_offset(classid_t cid, bool sticky) {
+  return dart::RegExp::function_offset(cid, sticky);
+}
+
+const word Symbols::kNumberOfOneCharCodeSymbols =
+    dart::Symbols::kNumberOfOneCharCodeSymbols;
+const word Symbols::kNullCharCodeSymbolOffset =
+    dart::Symbols::kNullCharCodeSymbolOffset;
+
 }  // namespace target
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/runtime_api.h b/runtime/vm/compiler/runtime_api.h
index 2d6e127..853fac0 100644
--- a/runtime/vm/compiler/runtime_api.h
+++ b/runtime/vm/compiler/runtime_api.h
@@ -21,20 +21,25 @@
 #include "platform/globals.h"
 #include "vm/allocation.h"
 #include "vm/bitfield.h"
+#include "vm/class_id.h"
 #include "vm/code_entry_kind.h"
 #include "vm/frame_layout.h"
 #include "vm/pointer_tagging.h"
+#include "vm/runtime_entry_list.h"
+#include "vm/token.h"
 
 namespace dart {
 
 // Forward declarations.
-class Class;
-class Code;
-class Function;
 class LocalVariable;
 class Object;
-class String;
+class RuntimeEntry;
 class Zone;
+
+#define DO(clazz) class clazz;
+CLASS_LIST_FOR_HANDLES(DO)
+#undef DO
+
 namespace compiler {
 class Assembler;
 }
@@ -77,6 +82,27 @@
 // Clone the given handle.
 Object& NewZoneHandle(Zone* zone, const Object&);
 
+//
+// Constant objects.
+//
+
+const Object& NullObject();
+const Bool& TrueObject();
+const Bool& FalseObject();
+const Object& EmptyTypeArguments();
+const Type& DynamicType();
+const Type& ObjectType();
+const Type& VoidType();
+const Type& IntType();
+const Class& GrowableObjectArrayClass();
+const Class& MintClass();
+const Class& DoubleClass();
+
+template <typename To, typename From>
+const To& CastHandle(const From& from) {
+  return reinterpret_cast<const To&>(from);
+}
+
 // Returns true if [a] and [b] are the same object.
 bool IsSameObject(const Object& a, const Object& b);
 
@@ -123,13 +149,81 @@
 // generated code.
 int32_t CreateJitCookie();
 
+// Returns the size in bytes for the given class id.
+word TypedDataElementSizeInBytes(classid_t cid);
+
+// Returns the size in bytes for the given class id.
+word TypedDataMaxNewSpaceElements(classid_t cid);
+
+// Looks up the dart:math's _Random._A field.
+const Field& LookupMathRandomStateFieldOffset();
+
+// Returns the offset in bytes of [field].
+word LookupFieldOffsetInBytes(const Field& field);
+
+#if defined(TARGET_ARCH_IA32)
+uword SymbolsPredefinedAddress();
+#endif
+
+typedef void (*RuntimeEntryCallInternal)(const dart::RuntimeEntry*,
+                                         compiler::Assembler*,
+                                         intptr_t);
+
+#if !defined(TARGET_ARCH_DBC)
+const Code& StubCodeAllocateArray();
+const Code& StubCodeSubtype2TestCache();
+const Code& StubCodeSubtype6TestCache();
+#endif  // !defined(TARGET_ARCH_DBC)
+
 class RuntimeEntry : public ValueObject {
  public:
   virtual ~RuntimeEntry() {}
-  virtual void Call(compiler::Assembler* assembler,
-                    intptr_t argument_count) const = 0;
+
+  void Call(compiler::Assembler* assembler, intptr_t argument_count) const {
+    ASSERT(call_ != NULL);
+    ASSERT(runtime_entry_ != NULL);
+
+    // We call a manually set function pointer which points to the
+    // implementation of call for the subclass. We do this instead of just
+    // defining Call in this class as a pure virtual method and providing an
+    // implementation in the subclass as RuntimeEntry objects are declared as
+    // globals which causes problems on Windows.
+    //
+    // When exit() is called on Windows, global objects start to be destroyed.
+    // As part of an object's destruction, the vtable is reset to that of the
+    // base class. Since some threads may still be running and accessing these
+    // now destroyed globals, an invocation to dart::RuntimeEntry::Call would
+    // instead invoke dart::compiler::RuntimeEntry::Call. If
+    // dart::compiler::RuntimeEntry::Call were a pure virtual method, _purecall
+    // would be invoked to handle the invalid call and attempt to call exit(),
+    // causing the process to hang on a lock.
+    //
+    // By removing the need to rely on a potentially invalid vtable at exit,
+    // we should be able to avoid hanging or crashing the process at shutdown,
+    // even as global objects start to be destroyed. See issue #35855.
+    call_(runtime_entry_, assembler, argument_count);
+  }
+
+ protected:
+  RuntimeEntry(const dart::RuntimeEntry* runtime_entry,
+               RuntimeEntryCallInternal call)
+      : runtime_entry_(runtime_entry), call_(call) {}
+
+ private:
+  const dart::RuntimeEntry* runtime_entry_;
+  RuntimeEntryCallInternal call_;
 };
 
+#define DECLARE_RUNTIME_ENTRY(name)                                            \
+  extern const RuntimeEntry& k##name##RuntimeEntry;
+RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
+#undef DECLARE_RUNTIME_ENTRY
+
+#define DECLARE_RUNTIME_ENTRY(type, name, ...)                                 \
+  extern const RuntimeEntry& k##name##RuntimeEntry;
+LEAF_RUNTIME_ENTRY_LIST(DECLARE_RUNTIME_ENTRY)
+#undef DECLARE_RUNTIME_ENTRY
+
 // Allocate a string object with the given content in the runtime heap.
 const String& AllocateString(const char* buffer);
 
@@ -157,6 +251,11 @@
 
 using ObjectAlignment = dart::ObjectAlignment<kWordSize, kWordSizeLog2>;
 
+// Information about heap pages.
+extern const word kPageSize;
+extern const word kPageSizeInWords;
+extern const word kPageMask;
+
 // Information about frame_layout that compiler should be targeting.
 extern FrameLayout frame_layout;
 
@@ -214,11 +313,21 @@
 
 class RawObject : public AllStatic {
  public:
+  static const word kCardRememberedBit;
+  static const word kOldAndNotRememberedBit;
+  static const word kOldAndNotMarkedBit;
   static const word kClassIdTagPos;
   static const word kClassIdTagSize;
+  static const word kSizeTagMaxSizeTag;
+  static const word kTagBitsSizeTagPos;
   static const word kBarrierOverlapShift;
 };
 
+class RawAbstractType : public AllStatic {
+ public:
+  static const word kTypeStateFinalizedInstantiated;
+};
+
 class Object : public AllStatic {
  public:
   // Offset of the tags word.
@@ -233,16 +342,135 @@
 
 class Class : public AllStatic {
  public:
+  static word type_arguments_field_offset_in_words_offset();
+
+  static word declaration_type_offset();
+
+  // The offset of the RawObject::num_type_arguments_ field in bytes.
+  static word num_type_arguments_offset_in_bytes();
+
+  // The value used if no type arguments vector is present.
+  static const word kNoTypeArguments;
+
   // Return class id of the given class on the target.
   static classid_t GetId(const dart::Class& handle);
 
   // Return instance size for the given class on the target.
   static uword GetInstanceSize(const dart::Class& handle);
+
+  // Returns the number of type arguments.
+  static intptr_t NumTypeArguments(const dart::Class& klass);
+
+  // Whether [klass] has a type arguments vector field.
+  static bool HasTypeArgumentsField(const dart::Class& klass);
+
+  // Returns the offset (in bytes) of the type arguments vector.
+  static intptr_t TypeArgumentsFieldOffset(const dart::Class& klass);
+
+  // Returns the instance size (in bytes).
+  static intptr_t InstanceSize(const dart::Class& klass);
+
+  // Whether to trace allocation for this klass.
+  static bool TraceAllocation(const dart::Class& klass);
 };
 
 class Instance : public AllStatic {
  public:
+  // Returns the offset to the first field of [RawInstance].
+  static word first_field_offset();
   static word DataOffsetFor(intptr_t cid);
+  static word ElementSizeFor(intptr_t cid);
+};
+
+class Function : public AllStatic {
+ public:
+  static word code_offset();
+  static word entry_point_offset();
+  static word usage_counter_offset();
+  static word unchecked_entry_point_offset();
+};
+
+class ICData : public AllStatic {
+ public:
+  static word owner_offset();
+  static word arguments_descriptor_offset();
+  static word entries_offset();
+  static word static_receiver_type_offset();
+  static word state_bits_offset();
+
+  static word CodeIndexFor(word num_args);
+  static word CountIndexFor(word num_args);
+  static word TargetIndexFor(word num_args);
+  static word ExactnessOffsetFor(word num_args);
+  static word TestEntryLengthFor(word num_args, bool exactness_check);
+  static word EntryPointIndexFor(word num_args);
+  static word NumArgsTestedShift();
+  static word NumArgsTestedMask();
+};
+
+class MegamorphicCache : public AllStatic {
+ public:
+  static const word kSpreadFactor;
+  static word mask_offset();
+  static word buckets_offset();
+  static word arguments_descriptor_offset();
+};
+
+class SingleTargetCache : public AllStatic {
+ public:
+  static word lower_limit_offset();
+  static word upper_limit_offset();
+  static word entry_point_offset();
+  static word target_offset();
+};
+
+class Array : public AllStatic {
+ public:
+  static word header_size();
+  static word tags_offset();
+  static word data_offset();
+  static word type_arguments_offset();
+  static word length_offset();
+
+  static const word kMaxNewSpaceElements;
+};
+
+class GrowableObjectArray : public AllStatic {
+ public:
+  static word data_offset();
+  static word type_arguments_offset();
+  static word length_offset();
+};
+
+class TypedData : public AllStatic {
+ public:
+  static word data_offset();
+  static word length_offset();
+  static word InstanceSize();
+};
+
+class ArgumentsDescriptor : public AllStatic {
+ public:
+  static word count_offset();
+  static word type_args_len_offset();
+};
+
+class AbstractType : public AllStatic {
+ public:
+  static word type_test_stub_entry_point_offset();
+};
+
+class Type : public AllStatic {
+ public:
+  static word hash_offset();
+  static word type_state_offset();
+  static word arguments_offset();
+  static word signature_offset();
+};
+
+class TypeRef : public AllStatic {
+ public:
+  static word type_offset();
 };
 
 class Double : public AllStatic {
@@ -250,6 +478,34 @@
   static word value_offset();
 };
 
+class Smi : public AllStatic {
+ public:
+  static const word kBits;
+};
+
+class Mint : public AllStatic {
+ public:
+  static word value_offset();
+};
+
+class String : public AllStatic {
+ public:
+  static const word kHashBits;
+  static word hash_offset();
+  static word length_offset();
+  static word InstanceSize();
+};
+
+class OneByteString : public AllStatic {
+ public:
+  static word data_offset();
+};
+
+class TwoByteString : public AllStatic {
+ public:
+  static word data_offset();
+};
+
 class Float32x4 : public AllStatic {
  public:
   static word value_offset();
@@ -260,11 +516,31 @@
   static word value_offset();
 };
 
+class TimelineStream : public AllStatic {
+ public:
+  static word enabled_offset();
+};
+
 class Thread : public AllStatic {
  public:
+  static word dart_stream_offset();
+  static word async_stack_trace_offset();
+  static word predefined_symbols_address_offset();
+
+  static word active_exception_offset();
+  static word active_stacktrace_offset();
+  static word resume_pc_offset();
+  static word marking_stack_block_offset();
+  static word top_exit_frame_info_offset();
+  static word top_resource_offset();
+  static word global_object_pool_offset();
+  static word object_null_offset();
+  static word bool_true_offset();
+  static word bool_false_offset();
   static word top_offset();
   static word end_offset();
   static word isolate_offset();
+  static word store_buffer_block_offset();
   static word call_to_runtime_entry_point_offset();
   static word null_error_shared_with_fpu_regs_entry_point_offset();
   static word null_error_shared_without_fpu_regs_entry_point_offset();
@@ -275,6 +551,32 @@
   static word write_barrier_entry_point_offset();
   static word vm_tag_offset();
 
+#if !defined(TARGET_ARCH_DBC)
+  static word write_barrier_code_offset();
+  static word array_write_barrier_code_offset();
+  static word fix_callers_target_code_offset();
+  static word fix_allocation_stub_code_offset();
+
+  static word monomorphic_miss_stub_offset();
+  static word ic_lookup_through_code_stub_offset();
+  static word lazy_specialize_type_test_stub_offset();
+  static word slow_type_test_stub_offset();
+  static word call_to_runtime_stub_offset();
+  static word invoke_dart_code_stub_offset();
+  static word interpret_call_entry_point_offset();
+  static word invoke_dart_code_from_bytecode_stub_offset();
+  static word null_error_shared_without_fpu_regs_stub_offset();
+  static word null_error_shared_with_fpu_regs_stub_offset();
+  static word stack_overflow_shared_without_fpu_regs_stub_offset();
+  static word stack_overflow_shared_with_fpu_regs_stub_offset();
+  static word lazy_deopt_from_return_stub_offset();
+  static word lazy_deopt_from_throw_stub_offset();
+  static word deoptimize_stub_offset();
+#endif  // !defined(TARGET_ARCH_DBC)
+
+  static word no_scope_native_wrapper_entry_point_offset();
+  static word auto_scope_native_wrapper_entry_point_offset();
+
 #define THREAD_XMM_CONSTANT_LIST(V)                                            \
   V(float_not)                                                                 \
   V(float_negate)                                                              \
@@ -287,11 +589,42 @@
   static word name##_address_offset();
   THREAD_XMM_CONSTANT_LIST(DECLARE_CONSTANT_OFFSET_GETTER)
 #undef DECLARE_CONSTANT_OFFSET_GETTER
+
+  static word OffsetFromThread(const dart::Object& object);
+};
+
+class StoreBufferBlock : public AllStatic {
+ public:
+  static word top_offset();
+  static word pointers_offset();
+  static const word kSize;
+};
+
+class MarkingStackBlock : public AllStatic {
+ public:
+  static word top_offset();
+  static word pointers_offset();
+  static const word kSize;
+};
+
+class ObjectStore : public AllStatic {
+ public:
+  static word double_type_offset();
+  static word int_type_offset();
+  static word string_type_offset();
 };
 
 class Isolate : public AllStatic {
  public:
+  static word object_store_offset();
+  static word default_tag_offset();
+  static word current_tag_offset();
+  static word user_tag_offset();
   static word class_table_offset();
+  static word ic_miss_code_offset();
+#if !defined(PRODUCT)
+  static word single_step_offset();
+#endif  // !defined(PRODUCT)
 };
 
 class ClassTable : public AllStatic {
@@ -336,6 +669,45 @@
   static intptr_t saved_instructions_offset();
 };
 
+class SubtypeTestCache : public AllStatic {
+ public:
+  static word cache_offset();
+
+  static const word kTestEntryLength;
+  static const word kInstanceClassIdOrFunction;
+  static const word kInstanceTypeArguments;
+  static const word kInstantiatorTypeArguments;
+  static const word kFunctionTypeArguments;
+  static const word kInstanceParentFunctionTypeArguments;
+  static const word kInstanceDelayedFunctionTypeArguments;
+  static const word kTestResult;
+};
+
+class Context : public AllStatic {
+ public:
+  static word header_size();
+  static word parent_offset();
+  static word num_variables_offset();
+  static word variable_offset(word i);
+  static word InstanceSize(word n);
+};
+
+class Closure : public AllStatic {
+ public:
+  static word context_offset();
+  static word delayed_type_arguments_offset();
+  static word function_offset();
+  static word function_type_arguments_offset();
+  static word instantiator_type_arguments_offset();
+};
+
+class HeapPage : public AllStatic {
+ public:
+  static const word kBytesPerCardLog2;
+
+  static word card_table_offset();
+};
+
 class Heap : public AllStatic {
  public:
   // Return true if an object with the given instance size is allocatable
@@ -343,6 +715,37 @@
   static bool IsAllocatableInNewSpace(intptr_t instance_size);
 };
 
+class NativeArguments {
+ public:
+  static word thread_offset();
+  static word argc_tag_offset();
+  static word argv_offset();
+  static word retval_offset();
+
+  static word StructSize();
+};
+
+class NativeEntry {
+ public:
+  static const word kNumCallWrapperArguments;
+};
+
+class RegExp : public AllStatic {
+ public:
+  static word function_offset(classid_t cid, bool sticky);
+};
+
+class UserTag : public AllStatic {
+ public:
+  static word tag_offset();
+};
+
+class Symbols : public AllStatic {
+ public:
+  static const word kNumberOfOneCharCodeSymbols;
+  static const word kNullCharCodeSymbolOffset;
+};
+
 }  // namespace target
 }  // namespace compiler
 }  // namespace dart
diff --git a/runtime/vm/compiler/stub_code_compiler.h b/runtime/vm/compiler/stub_code_compiler.h
new file mode 100644
index 0000000..c227889
--- /dev/null
+++ b/runtime/vm/compiler/stub_code_compiler.h
@@ -0,0 +1,86 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#ifndef RUNTIME_VM_COMPILER_STUB_CODE_COMPILER_H_
+#define RUNTIME_VM_COMPILER_STUB_CODE_COMPILER_H_
+
+#include "vm/allocation.h"
+#include "vm/compiler/runtime_api.h"
+#include "vm/constants.h"
+#include "vm/stub_code_list.h"
+
+namespace dart {
+
+namespace compiler {
+
+// Forward declarations.
+class Assembler;
+
+class StubCodeCompiler : public AllStatic {
+ public:
+#if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
+  static void GenerateBuildMethodExtractorStub(
+      Assembler* assembler,
+      const Object& closure_allocation_stub,
+      const Object& context_allocation_stub);
+#endif
+
+#if !defined(DART_PRECOMPILED_RUNTIME)
+#define STUB_CODE_GENERATE(name)                                               \
+  static void Generate##name##Stub(Assembler* assembler);
+  VM_STUB_CODE_LIST(STUB_CODE_GENERATE)
+#undef STUB_CODE_GENERATE
+
+  static void GenerateSharedStub(Assembler* assembler,
+                                 bool save_fpu_registers,
+                                 const RuntimeEntry* target,
+                                 intptr_t self_code_stub_offset_from_thread,
+                                 bool allow_return);
+
+  static void GenerateMegamorphicMissStub(Assembler* assembler);
+  static void GenerateAllocationStubForClass(Assembler* assembler,
+                                             const Class& cls);
+  static void GenerateNArgsCheckInlineCacheStub(
+      Assembler* assembler,
+      intptr_t num_args,
+      const RuntimeEntry& handle_ic_miss,
+      Token::Kind kind,
+      bool optimized = false,
+      bool exactness_check = false);
+  static void GenerateUsageCounterIncrement(Assembler* assembler,
+                                            Register temp_reg);
+  static void GenerateOptimizedUsageCounterIncrement(Assembler* assembler);
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
+};
+
+}  // namespace compiler
+
+enum DeoptStubKind { kLazyDeoptFromReturn, kLazyDeoptFromThrow, kEagerDeopt };
+
+// Invocation mode for TypeCheck runtime entry that describes
+// where we are calling it from.
+enum TypeCheckMode {
+  // TypeCheck is invoked from LazySpecializeTypeTest stub.
+  // It should replace stub on the type with a specialized version.
+  kTypeCheckFromLazySpecializeStub,
+
+  // TypeCheck is invoked from the SlowTypeTest stub.
+  // This means that cache can be lazily created (if needed)
+  // and dst_name can be fetched from the pool.
+  kTypeCheckFromSlowStub,
+
+  // TypeCheck is invoked from normal inline AssertAssignable.
+  // Both cache and dst_name must be already populated.
+  kTypeCheckFromInline
+};
+
+// Zap value used to indicate unused CODE_REG in deopt.
+static const uword kZapCodeReg = 0xf1f1f1f1;
+
+// Zap value used to indicate unused return address in deopt.
+static const uword kZapReturnAddress = 0xe1e1e1e1;
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_COMPILER_STUB_CODE_COMPILER_H_
diff --git a/runtime/vm/stub_code_arm.cc b/runtime/vm/compiler/stub_code_compiler_arm.cc
similarity index 65%
rename from runtime/vm/stub_code_arm.cc
rename to runtime/vm/compiler/stub_code_compiler_arm.cc
index 5d0f2d8..fc4b9dc 100644
--- a/runtime/vm/stub_code_arm.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm.cc
@@ -1,24 +1,23 @@
-// Copyright (c) 2013, 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.
 
 #include "vm/globals.h"
 
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/stub_code_compiler.h"
+
 #if defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/class_id.h"
+#include "vm/code_entry_kind.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/constants_arm.h"
 #include "vm/instructions.h"
-#include "vm/isolate.h"
-#include "vm/object_store.h"
-#include "vm/runtime_entry.h"
-#include "vm/stack_frame.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/tags.h"
-#include "vm/type_testing_stubs.h"
 
 #define __ assembler->
 
@@ -31,6 +30,8 @@
             "Set to true for debugging & verifying the slow paths.");
 DECLARE_FLAG(bool, precompiled_mode);
 
+namespace compiler {
+
 // Input parameters:
 //   LR : return address.
 //   SP : address of last argument in argument array.
@@ -38,24 +39,25 @@
 //   SP + 4*R4 : address of return value.
 //   R9 : address of the runtime function to call.
 //   R4 : number of arguments to the call.
-void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
-  __ ldr(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::call_to_runtime_stub_offset()));
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -64,48 +66,51 @@
 #endif
 
   // Mark that the thread is executing VM code.
-  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for arguments and align frame before entering C++ world.
-  // NativeArguments are passed in registers.
-  ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
+  // target::NativeArguments are passed in registers.
+  ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
   __ ReserveAlignedFrameSpace(0);
 
-  // Pass NativeArguments structure by value and call runtime.
+  // Pass target::NativeArguments structure by value and call runtime.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, Operand(THR));
 
   // There are no runtime calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  __ mov(R1, Operand(R4));  // Set argc in NativeArguments.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  __ mov(R1, Operand(R4));  // Set argc in target::NativeArguments.
 
-  ASSERT(argv_offset == 2 * kWordSize);
+  ASSERT(argv_offset == 2 * target::kWordSize);
   __ add(R2, FP, Operand(R4, LSL, 2));  // Compute argv.
-  // Set argv in NativeArguments.
-  __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize);
+  // Set argv in target::NativeArguments.
+  __ AddImmediate(R2,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
 
-  ASSERT(retval_offset == 3 * kWordSize);
-  __ add(R3, R2, Operand(kWordSize));  // Retval is next to 1st argument.
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ add(R3, R2,
+         Operand(target::kWordSize));  // Retval is next to 1st argument.
 
   // Call runtime or redirection via simulator.
   __ blx(R9);
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
   // Restore the global object pool after returning from runtime (old space is
   // moving, so the GOP could have been relocated).
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
   }
 
   __ LeaveStubFrame();
@@ -119,11 +124,19 @@
   __ Ret();
 }
 
-void StubCode::GenerateSharedStub(Assembler* assembler,
-                                  bool save_fpu_registers,
-                                  const RuntimeEntry* target,
-                                  intptr_t self_code_stub_offset_from_thread,
-                                  bool allow_return) {
+void StubCodeCompiler::GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return) {
+  // If the target CPU does not support VFP the caller should always use the
+  // non-FPU stub.
+  if (save_fpu_registers && !TargetCPUFeatures::vfp_supported()) {
+    __ Breakpoint();
+    return;
+  }
+
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   RegisterSet all_registers;
@@ -150,27 +163,19 @@
 // R1: The extracted method.
 // R4: The type_arguments_field_offset (or 0)
 // SP+0: The object from which we are tearing a method off.
-void StubCode::GenerateBuildMethodExtractorStub(Assembler* assembler) {
-  Thread* thread = Thread::Current();
-  Zone* Z = thread->zone();
-  ObjectStore* object_store = thread->isolate()->object_store();
-
-  const auto& closure_class =
-      Class::ZoneHandle(Z, object_store->closure_class());
-  const auto& closure_allocation_stub =
-      Code::ZoneHandle(Z, StubCode::GetAllocationStubForClass(closure_class));
-
+void StubCodeCompiler::GenerateBuildMethodExtractorStub(
+    Assembler* assembler,
+    const Object& closure_allocation_stub,
+    const Object& context_allocation_stub) {
   const intptr_t kReceiverOffset =
       compiler::target::frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub = StubCode::AllocateContext();
-
   __ EnterStubFrame();
 
   // Build type_arguments vector (or null)
   __ cmp(R4, Operand(0));
-  __ ldr(R3, Address(THR, Thread::object_null_offset()), EQ);
-  __ ldr(R0, Address(FP, kReceiverOffset * kWordSize), NE);
+  __ ldr(R3, Address(THR, target::Thread::object_null_offset()), EQ);
+  __ ldr(R0, Address(FP, kReceiverOffset * target::kWordSize), NE);
   __ ldr(R3, Address(R0, R4), NE);
 
   // Push type arguments & extracted method.
@@ -179,89 +184,97 @@
   // Allocate context.
   {
     Label done, slow_path;
-    __ TryAllocateArray(kContextCid, Context::InstanceSize(1), &slow_path,
+    __ TryAllocateArray(kContextCid, target::Context::InstanceSize(1),
+                        &slow_path,
                         R0,  // instance
                         R1,  // end address
                         R2, R3);
-    __ ldr(R1, Address(THR, Thread::object_null_offset()));
-    __ str(R1, FieldAddress(R0, Context::parent_offset()));
+    __ ldr(R1, Address(THR, target::Thread::object_null_offset()));
+    __ str(R1, FieldAddress(R0, target::Context::parent_offset()));
     __ LoadImmediate(R1, 1);
-    __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
+    __ str(R1, FieldAddress(R0, target::Context::num_variables_offset()));
     __ b(&done);
 
     __ Bind(&slow_path);
 
     __ LoadImmediate(/*num_vars=*/R1, 1);
     __ LoadObject(CODE_REG, context_allocation_stub);
-    __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+    __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
     __ blx(R0);
 
     __ Bind(&done);
   }
 
   // Store receiver in context
-  __ ldr(R1, Address(FP, kWordSize * kReceiverOffset));
-  __ StoreIntoObject(R0, FieldAddress(R0, Context::variable_offset(0)), R1);
+  __ ldr(R1, Address(FP, target::kWordSize * kReceiverOffset));
+  __ StoreIntoObject(R0, FieldAddress(R0, target::Context::variable_offset(0)),
+                     R1);
 
   // Push context.
   __ Push(R0);
 
   // Allocate closure.
   __ LoadObject(CODE_REG, closure_allocation_stub);
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                        Code::EntryKind::kUnchecked)));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kUnchecked)));
   __ blx(R1);
 
   // Populate closure object.
   __ Pop(R1);  // Pop context.
-  __ StoreIntoObject(R0, FieldAddress(R0, Closure::context_offset()), R1);
+  __ StoreIntoObject(R0, FieldAddress(R0, target::Closure::context_offset()),
+                     R1);
   __ PopList(1 << R3 | 1 << R1);  // Pop type arguments & extracted method.
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Closure::function_offset()),
-                              R1);
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Closure::instantiator_type_arguments_offset()), R3);
-  __ LoadObject(R1, Object::empty_type_arguments());
+      R0, FieldAddress(R0, target::Closure::function_offset()), R1);
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Closure::delayed_type_arguments_offset()), R1);
+      R0,
+      FieldAddress(R0, target::Closure::instantiator_type_arguments_offset()),
+      R3);
+  __ LoadObject(R1, EmptyTypeArguments());
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::Closure::delayed_type_arguments_offset()),
+      R1);
 
   __ LeaveStubFrame();
   __ Ret();
 }
 
-void StubCode::GenerateNullErrorSharedWithoutFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/false,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_without_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateNullErrorSharedWithFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateStackOverflowSharedWithoutFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
     Assembler* assembler) {
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
-      Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
+      target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
       /*allow_return=*/true);
 }
 
-void StubCode::GenerateStackOverflowSharedWithFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kStackOverflowRuntimeEntry,
-                     Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/true);
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
+      target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/true);
 }
 
 // Input parameters:
 //   R0 : stop message (const char*).
 // Must preserve all registers.
-void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
+void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
   __ EnterCallRuntimeFrame(0);
   // Call the runtime leaf function. R0 already contains the parameter.
   __ CallRuntime(kPrintStopMessageRuntimeEntry, 1);
@@ -277,22 +290,23 @@
 //   R1 : argc_tag including number of arguments and function kind.
 static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
                                               Address wrapper) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -301,37 +315,37 @@
 #endif
 
   // Mark that the thread is executing native code.
-  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // R0) and align frame before entering the C++ world.
-  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
 
-  // Initialize NativeArguments structure and call native function.
+  // Initialize target::NativeArguments structure and call native function.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, Operand(THR));
 
   // There are no native calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  // Set argc in NativeArguments: R1 already contains argc.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  // Set argc in target::NativeArguments: R1 already contains argc.
 
-  ASSERT(argv_offset == 2 * kWordSize);
-  // Set argv in NativeArguments: R2 already contains argv.
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  // Set argv in target::NativeArguments: R2 already contains argv.
 
-  ASSERT(retval_offset == 3 * kWordSize);
   // Set retval in NativeArgs.
-  __ add(R3, FP, Operand(kCallerSpSlotFromFp * kWordSize));
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ add(R3, FP, Operand(2 * target::kWordSize));
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
   // For now, space is reserved on the stack and we pass a pointer to it.
   __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
-  __ mov(R0, Operand(SP));  // Pass the pointer to the NativeArguments.
+  __ mov(R0, Operand(SP));  // Pass the pointer to the target::NativeArguments.
 
   __ mov(R1, Operand(R9));  // Pass the function entrypoint to call.
 
@@ -341,26 +355,29 @@
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ Ret();
 }
 
-void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallNoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::no_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::no_scope_native_wrapper_entry_point_offset()));
 }
 
-void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::auto_scope_native_wrapper_entry_point_offset()));
 }
 
 // Input parameters:
@@ -369,23 +386,24 @@
 //   R9 : address of the native function to call.
 //   R2 : address of first argument in argument array.
 //   R1 : argc_tag including number of arguments and function kind.
-void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(kWord, FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, FP, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(kWord, R8, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(kWord, R8, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -394,48 +412,49 @@
 #endif
 
   // Mark that the thread is executing native code.
-  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // R0) and align frame before entering the C++ world.
-  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
 
-  // Initialize NativeArguments structure and call native function.
+  // Initialize target::NativeArguments structure and call native function.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, Operand(THR));
 
   // There are no native calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  // Set argc in NativeArguments: R1 already contains argc.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  // Set argc in target::NativeArguments: R1 already contains argc.
 
-  ASSERT(argv_offset == 2 * kWordSize);
-  // Set argv in NativeArguments: R2 already contains argv.
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  // Set argv in target::NativeArguments: R2 already contains argv.
 
-  ASSERT(retval_offset == 3 * kWordSize);
   // Set retval in NativeArgs.
-  __ add(R3, FP, Operand(kCallerSpSlotFromFp * kWordSize));
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ add(R3, FP, Operand(2 * target::kWordSize));
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
   // For now, space is reserved on the stack and we pass a pointer to it.
   __ stm(IA, SP, (1 << R0) | (1 << R1) | (1 << R2) | (1 << R3));
-  __ mov(R0, Operand(SP));  // Pass the pointer to the NativeArguments.
+  __ mov(R0, Operand(SP));  // Pass the pointer to the target::NativeArguments.
 
   // Call native function or redirection via simulator.
   __ blx(R9);
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ Ret();
@@ -443,7 +462,7 @@
 
 // Input parameters:
 //   R4: arguments descriptor array.
-void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallStaticFunctionStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
@@ -457,17 +476,18 @@
   __ LeaveStubFrame();
   // Jump to the dart function.
   __ mov(CODE_REG, Operand(R0));
-  __ Branch(FieldAddress(R0, Code::entry_point_offset()));
+  __ Branch(FieldAddress(R0, target::Code::entry_point_offset()));
 }
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
 // R4: arguments descriptor array.
-void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::fix_callers_target_code_offset()));
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
@@ -481,16 +501,18 @@
   __ LeaveStubFrame();
   // Jump to the dart function.
   __ mov(CODE_REG, Operand(R0));
-  __ Branch(FieldAddress(R0, Code::entry_point_offset()));
+  __ Branch(FieldAddress(R0, target::Code::entry_point_offset()));
 }
 
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
-void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixAllocationStubTargetStub(
+    Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ LoadImmediate(R0, 0);
@@ -502,23 +524,24 @@
   __ LeaveStubFrame();
   // Jump to the dart function.
   __ mov(CODE_REG, Operand(R0));
-  __ Branch(FieldAddress(R0, Code::entry_point_offset()));
+  __ Branch(FieldAddress(R0, target::Code::entry_point_offset()));
 }
 
 // Input parameters:
 //   R2: smi-tagged argument count, may be zero.
-//   FP[kParamEndSlotFromFp + 1]: last argument.
+//   FP[target::frame_layout.param_end_from_fp + 1]: last argument.
 static void PushArrayOfArguments(Assembler* assembler) {
   // Allocate array to store arguments of caller.
-  __ LoadObject(R1, Object::null_object());
+  __ LoadObject(R1, NullObject());
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  __ BranchLink(StubCode::AllocateArray());
+  __ BranchLink(StubCodeAllocateArray());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
-  __ AddImmediate(R1, FP, kParamEndSlotFromFp * kWordSize);
-  __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R1, FP,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
+  __ AddImmediate(R3, R0, target::Array::data_offset() - kHeapObjectTag);
   // Copy arguments from stack to array (starting at the end).
   // R1: address just beyond last argument on stack.
   // R3: address of first argument in array.
@@ -526,11 +549,11 @@
   __ b(&enter);
   Label loop;
   __ Bind(&loop);
-  __ ldr(R8, Address(R1, kWordSize, Address::PreIndex));
+  __ ldr(R8, Address(R1, target::kWordSize, Address::PreIndex));
   // Generational barrier is needed, array is not necessarily in new space.
   __ StoreIntoObject(R0, Address(R3, R2, LSL, 1), R8);
   __ Bind(&enter);
-  __ subs(R2, R2, Operand(Smi::RawValue(1)));  // R2 is Smi.
+  __ subs(R2, R2, Operand(target::ToRawSmi(1)));  // R2 is Smi.
   __ b(&loop, PL);
 }
 
@@ -586,7 +609,7 @@
     if (i == CODE_REG) {
       // Save the original value of CODE_REG pushed before invoking this stub
       // instead of the value used to call this stub.
-      __ ldr(IP, Address(FP, kCallerSpSlotFromFp * kWordSize));
+      __ ldr(IP, Address(FP, 2 * target::kWordSize));
       __ Push(IP);
     } else if (i == SP) {
       // Push(SP) has unpredictable behavior.
@@ -598,7 +621,7 @@
   }
 
   if (TargetCPUFeatures::vfp_supported()) {
-    ASSERT(kFpuRegisterSize == 4 * kWordSize);
+    ASSERT(kFpuRegisterSize == 4 * target::kWordSize);
     if (kNumberOfDRegisters > 16) {
       __ vstmd(DB_W, SP, D16, kNumberOfDRegisters - 16);
       __ vstmd(DB_W, SP, D0, 16);
@@ -619,11 +642,11 @@
 
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1 temporarily.
-    __ ldr(R1, Address(FP, saved_result_slot_from_fp * kWordSize));
+    __ ldr(R1, Address(FP, saved_result_slot_from_fp * target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into R1 temporarily.
-    __ ldr(R1, Address(FP, saved_exception_slot_from_fp * kWordSize));
-    __ ldr(R2, Address(FP, saved_stacktrace_slot_from_fp * kWordSize));
+    __ ldr(R1, Address(FP, saved_exception_slot_from_fp * target::kWordSize));
+    __ ldr(R2, Address(FP, saved_stacktrace_slot_from_fp * target::kWordSize));
   }
 
   __ RestoreCodePointer();
@@ -645,14 +668,14 @@
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1.
     __ ldr(R1, Address(FP, compiler::target::frame_layout.first_local_from_fp *
-                               kWordSize));
+                               target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into R1.
     __ ldr(R1, Address(FP, compiler::target::frame_layout.first_local_from_fp *
-                               kWordSize));
+                               target::kWordSize));
     __ ldr(R2, Address(FP, (compiler::target::frame_layout.first_local_from_fp -
                             1) *
-                               kWordSize));
+                               target::kWordSize));
   }
   // Code above cannot cause GC.
   __ RestoreCodePointer();
@@ -669,7 +692,7 @@
     __ Push(R1);  // Preserve exception, it will be GC-d here.
     __ Push(R2);  // Preserve stacktrace, it will be GC-d here.
   }
-  __ PushObject(Smi::ZoneHandle());  // Space for the result.
+  __ PushObject(NullObject());  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
@@ -687,33 +710,37 @@
 }
 
 // R0: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(IP, kZapCodeReg);
   __ Push(IP);
   // Return address for "call" to deopt stub.
   __ LoadImmediate(LR, kZapReturnAddress);
-  __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
   __ Ret();
 }
 
 // R0: exception, must be preserved
 // R1: stacktrace, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(IP, kZapCodeReg);
   __ Push(IP);
   // Return address for "call" to deopt stub.
   __ LoadImmediate(LR, kZapReturnAddress);
-  __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
   __ Ret();
 }
 
-void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::deoptimize_stub_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::deoptimize_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
   __ Ret();
 }
@@ -723,13 +750,14 @@
   __ Comment("NoSuchMethodDispatch");
   // When lazily generated invocation dispatchers are disabled, the
   // miss-handler may return null.
-  __ CompareObject(R0, Object::null_object());
+  __ CompareObject(R0, NullObject());
   __ b(call_target_function, NE);
   __ EnterStubFrame();
   // Load the receiver.
-  __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
   __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
-  __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize));
+  __ ldr(R8, Address(IP, target::frame_layout.param_end_from_fp *
+                             target::kWordSize));
   __ LoadImmediate(IP, 0);
   __ Push(IP);  // Result slot.
   __ Push(R8);  // Receiver.
@@ -737,9 +765,11 @@
   __ Push(R4);  // Arguments descriptor.
 
   // Adjust arguments count.
-  __ ldr(R3, FieldAddress(R4, ArgumentsDescriptor::type_args_len_offset()));
+  __ ldr(R3,
+         FieldAddress(R4, target::ArgumentsDescriptor::type_args_len_offset()));
   __ cmp(R3, Operand(0));
-  __ AddImmediate(R2, R2, Smi::RawValue(1), NE);  // Include the type arguments.
+  __ AddImmediate(R2, R2, target::ToRawSmi(1),
+                  NE);  // Include the type arguments.
 
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
@@ -751,14 +781,14 @@
   __ Ret();
 }
 
-void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
   __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
   __ ldr(R8, Address(IP, compiler::target::frame_layout.param_end_from_fp *
-                             kWordSize));
+                             target::kWordSize));
 
   // Preserve IC data and arguments descriptor.
   __ PushList((1 << R4) | (1 << R9));
@@ -786,8 +816,8 @@
   }
 
   // Tail-call to target function.
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 }
 
 // Called for inline allocation of arrays.
@@ -796,11 +826,12 @@
 //   R1: array element type (either NULL or an instantiated type).
 //   R2: array length as Smi (must be preserved).
 // The newly allocated object is returned in R0.
-void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
-  // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+  // RoundedAllocationSize(
+  //     (array_length * kwordSize) + target::Array::header_size()).
   __ mov(R3, Operand(R2));  // Array length.
   // Check that length is a positive Smi.
   __ tst(R3, Operand(kSmiTagMask));
@@ -814,7 +845,7 @@
 
   // Check for maximum allowed length.
   const intptr_t max_len =
-      reinterpret_cast<int32_t>(Smi::New(Array::kMaxNewSpaceElements));
+      target::ToRawSmi(target::Array::kMaxNewSpaceElements);
   __ CompareImmediate(R3, max_len);
   __ b(&slow_case, GT);
 
@@ -823,15 +854,16 @@
   NOT_IN_PRODUCT(__ MaybeTraceAllocation(R4, &slow_case));
 
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawArray) + kObjectAlignment - 1;
+      target::Array::header_size() + target::ObjectAlignment::kObjectAlignment -
+      1;
   __ LoadImmediate(R9, fixed_size_plus_alignment_padding);
   __ add(R9, R9, Operand(R3, LSL, 1));  // R3 is a Smi.
   ASSERT(kSmiTagShift == 1);
-  __ bic(R9, R9, Operand(kObjectAlignment - 1));
+  __ bic(R9, R9, Operand(target::ObjectAlignment::kObjectAlignment - 1));
 
   // R9: Allocation size.
   // Potential new object start.
-  __ ldr(R0, Address(THR, Thread::top_offset()));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
   __ adds(NOTFP, R0, Operand(R9));  // Potential next object start.
   __ b(&slow_case, CS);             // Branch if unsigned overflow.
 
@@ -839,14 +871,14 @@
   // R0: potential new object start.
   // NOTFP: potential next object start.
   // R9: allocation size.
-  __ ldr(R3, Address(THR, Thread::end_offset()));
+  __ ldr(R3, Address(THR, target::Thread::end_offset()));
   __ cmp(NOTFP, Operand(R3));
   __ b(&slow_case, CS);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
   NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R3, cid));
-  __ str(NOTFP, Address(THR, Thread::top_offset()));
+  __ str(NOTFP, Address(THR, target::Thread::top_offset()));
   __ add(R0, R0, Operand(kHeapObjectTag));
 
   // Initialize the tags.
@@ -855,30 +887,31 @@
   // NOTFP: new object end address.
   // R9: allocation size.
   {
-    const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
+    const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
 
-    __ CompareImmediate(R9, RawObject::SizeTag::kMaxSizeTag);
+    __ CompareImmediate(R9, target::RawObject::kSizeTagMaxSizeTag);
     __ mov(R8, Operand(R9, LSL, shift), LS);
     __ mov(R8, Operand(0), HI);
 
     // Get the class index and insert it into the tags.
     // R8: size and bit tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
     __ LoadImmediate(TMP, tags);
     __ orr(R8, R8, Operand(TMP));
-    __ str(R8, FieldAddress(R0, Array::tags_offset()));  // Store tags.
+    __ str(R8, FieldAddress(R0, target::Array::tags_offset()));  // Store tags.
   }
 
   // R0: new object start as a tagged pointer.
   // NOTFP: new object end address.
   // Store the type argument field.
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Array::type_arguments_offset()), R1);
+      R0, FieldAddress(R0, target::Array::type_arguments_offset()), R1);
 
   // Set the length field.
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Array::length_offset()), R2);
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::Array::length_offset()), R2);
 
   // Initialize all array elements to raw_null.
   // R0: new object start as a tagged pointer.
@@ -890,9 +923,9 @@
   // R9: allocation size.
   NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R3, R9));
 
-  __ LoadObject(R8, Object::null_object());
+  __ LoadObject(R8, NullObject());
   __ mov(R9, Operand(R8));
-  __ AddImmediate(R4, R0, sizeof(RawArray) - kHeapObjectTag);
+  __ AddImmediate(R4, R0, target::Array::header_size() - kHeapObjectTag);
   __ InitializeFieldsNoBarrier(R0, R4, NOTFP, R8, R9);
   __ Ret();  // Returns the newly allocated object in R0.
   // Unable to allocate the array using the fast inline code, just call
@@ -921,12 +954,12 @@
 //   R1 : arguments descriptor array.
 //   R2 : arguments array.
 //   R3 : current thread.
-void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ Push(LR);  // Marker for the profiler.
   __ EnterFrame((1 << FP) | (1 << LR), 0);
 
   // Push code object to PC marker slot.
-  __ ldr(IP, Address(R3, Thread::invoke_dart_code_stub_offset()));
+  __ ldr(IP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(IP);
 
   // Save new context and C++ ABI callee-saved registers.
@@ -947,44 +980,49 @@
   }
 
   // Save the current VMTag on the stack.
-  __ LoadFromOffset(kWord, R9, THR, Thread::vm_tag_offset());
+  __ LoadFromOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
   __ Push(R9);
 
   // Save top resource and top exit frame info. Use R4-6 as temporary registers.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(kWord, R9, THR, Thread::top_exit_frame_info_offset());
-  __ LoadFromOffset(kWord, R4, THR, Thread::top_resource_offset());
+  __ LoadFromOffset(kWord, R9, THR,
+                    target::Thread::top_exit_frame_info_offset());
+  __ LoadFromOffset(kWord, R4, THR, target::Thread::top_resource_offset());
   __ LoadImmediate(R8, 0);
-  __ StoreToOffset(kWord, R8, THR, Thread::top_resource_offset());
-  __ StoreToOffset(kWord, R8, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R8, THR, target::Thread::top_resource_offset());
+  __ StoreToOffset(kWord, R8, THR,
+                   target::Thread::top_exit_frame_info_offset());
 
-  // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
+  // target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
+  // with the code below.
   __ Push(R4);
 #if defined(TARGET_OS_MACOS) || defined(TARGET_OS_MACOS_IOS)
-  ASSERT(kExitLinkSlotFromEntryFp == -26);
+  ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -26);
 #else
-  ASSERT(kExitLinkSlotFromEntryFp == -27);
+  ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -27);
 #endif
   __ Push(R9);
 
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ LoadImmediate(R9, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(kWord, R9, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R9, THR, target::Thread::vm_tag_offset());
 
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ ldr(R4, Address(R1, VMHandles::kOffsetOfRawPtrInHandle));
 
   // Load number of arguments into R9 and adjust count for type arguments.
-  __ ldr(R3, FieldAddress(R4, ArgumentsDescriptor::type_args_len_offset()));
-  __ ldr(R9, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ ldr(R3,
+         FieldAddress(R4, target::ArgumentsDescriptor::type_args_len_offset()));
+  __ ldr(R9, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
   __ cmp(R3, Operand(0));
-  __ AddImmediate(R9, R9, Smi::RawValue(1), NE);  // Include the type arguments.
+  __ AddImmediate(R9, R9, target::ToRawSmi(1),
+                  NE);  // Include the type arguments.
   __ SmiUntag(R9);
 
   // Compute address of 'arguments array' data area into R2.
   __ ldr(R2, Address(R2, VMHandles::kOffsetOfRawPtrInHandle));
-  __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R2, target::Array::data_offset() - kHeapObjectTag);
 
   // Set up arguments for the Dart call.
   Label push_arguments;
@@ -995,7 +1033,7 @@
   __ Bind(&push_arguments);
   __ ldr(R3, Address(R2));
   __ Push(R3);
-  __ AddImmediate(R2, kWordSize);
+  __ AddImmediate(R2, target::kWordSize);
   __ AddImmediate(R1, 1);
   __ cmp(R1, Operand(R9));
   __ b(&push_arguments, LT);
@@ -1003,27 +1041,30 @@
 
   // Call the Dart code entrypoint.
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
   } else {
     __ LoadImmediate(PP, 0);  // GC safe value into PP.
   }
   __ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle));
-  __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ blx(R0);  // R4 is the arguments descriptor array.
 
   // Get rid of arguments pushed on the stack.
-  __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
+  __ AddImmediate(
+      SP, FP,
+      target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R9 as a temporary register for this.
   __ Pop(R9);
-  __ StoreToOffset(kWord, R9, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R9, THR,
+                   target::Thread::top_exit_frame_info_offset());
   __ Pop(R9);
-  __ StoreToOffset(kWord, R9, THR, Thread::top_resource_offset());
+  __ StoreToOffset(kWord, R9, THR, target::Thread::top_resource_offset());
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
-  __ StoreToOffset(kWord, R4, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R4, THR, target::Thread::vm_tag_offset());
 
   // Restore C++ ABI callee-saved registers.
   if (TargetCPUFeatures::vfp_supported()) {
@@ -1042,7 +1083,8 @@
   __ Ret();
 }
 
-void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
+    Assembler* assembler) {
   __ Unimplemented("Interpreter not yet supported");
 }
 
@@ -1051,17 +1093,18 @@
 //   R1: number of context variables.
 // Output:
 //   R0: new allocated RawContext object.
-void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
     // R1: number of context variables.
     intptr_t fixed_size_plus_alignment_padding =
-        sizeof(RawContext) + kObjectAlignment - 1;
+        target::Context::header_size() +
+        target::ObjectAlignment::kObjectAlignment - 1;
     __ LoadImmediate(R2, fixed_size_plus_alignment_padding);
     __ add(R2, R2, Operand(R1, LSL, 2));
     ASSERT(kSmiTagShift == 1);
-    __ bic(R2, R2, Operand(kObjectAlignment - 1));
+    __ bic(R2, R2, Operand(target::ObjectAlignment::kObjectAlignment - 1));
 
     NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R8, kContextCid));
     NOT_IN_PRODUCT(__ MaybeTraceAllocation(R8, &slow_case));
@@ -1069,14 +1112,14 @@
     // R1: number of context variables.
     // R2: object size.
     const intptr_t cid = kContextCid;
-    __ ldr(R0, Address(THR, Thread::top_offset()));
+    __ ldr(R0, Address(THR, target::Thread::top_offset()));
     __ add(R3, R2, Operand(R0));
     // Check if the allocation fits into the remaining space.
     // R0: potential new object.
     // R1: number of context variables.
     // R2: object size.
     // R3: potential next object start.
-    __ ldr(IP, Address(THR, Thread::end_offset()));
+    __ ldr(IP, Address(THR, target::Thread::end_offset()));
     __ cmp(R3, Operand(IP));
     if (FLAG_use_slow_path) {
       __ b(&slow_case);
@@ -1091,7 +1134,7 @@
     // R2: object size.
     // R3: next object start.
     NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(R4, cid));
-    __ str(R3, Address(THR, Thread::top_offset()));
+    __ str(R3, Address(THR, target::Thread::top_offset()));
     __ add(R0, R0, Operand(kHeapObjectTag));
 
     // Calculate the size tag.
@@ -1100,20 +1143,21 @@
     // R2: object size.
     // R3: next object start.
     // R4: allocation stats address.
-    const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);
     // If no size tag overflow, shift R2 left, else set R2 to zero.
     __ mov(R9, Operand(R2, LSL, shift), LS);
     __ mov(R9, Operand(0), HI);
 
     // Get the class index and insert it into the tags.
     // R9: size and bit tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+
     __ LoadImmediate(IP, tags);
     __ orr(R9, R9, Operand(IP));
-    __ str(R9, FieldAddress(R0, Context::tags_offset()));
+    __ str(R9, FieldAddress(R0, target::Object::tags_offset()));
 
     // Setup up number of context variables field.
     // R0: new object.
@@ -1121,7 +1165,7 @@
     // R2: object size.
     // R3: next object start.
     // R4: allocation stats address.
-    __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
+    __ str(R1, FieldAddress(R0, target::Context::num_variables_offset()));
 
     // Setup the parent field.
     // R0: new object.
@@ -1129,9 +1173,9 @@
     // R2: object size.
     // R3: next object start.
     // R4: allocation stats address.
-    __ LoadObject(R8, Object::null_object());
-    __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Context::parent_offset()),
-                                R8);
+    __ LoadObject(R8, NullObject());
+    __ StoreIntoObjectNoBarrier(
+        R0, FieldAddress(R0, target::Context::parent_offset()), R8);
 
     // Initialize the context variables.
     // R0: new object.
@@ -1141,7 +1185,8 @@
     // R8, R9: raw null.
     // R4: allocation stats address.
     Label loop;
-    __ AddImmediate(NOTFP, R0, Context::variable_offset(0) - kHeapObjectTag);
+    __ AddImmediate(NOTFP, R0,
+                    target::Context::variable_offset(0) - kHeapObjectTag);
     __ InitializeFieldsNoBarrier(R0, NOTFP, R3, R8, R9);
     NOT_IN_PRODUCT(__ IncrementAllocationStatsWithSize(R4, R2));
 
@@ -1167,7 +1212,7 @@
   __ Ret();
 }
 
-void StubCode::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
   RegList saved = (1 << LR) | (1 << kWriteBarrierObjectReg);
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
     if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
@@ -1176,7 +1221,8 @@
     intptr_t start = __ CodeSize();
     __ PushList(saved);
     __ mov(kWriteBarrierObjectReg, Operand(reg));
-    __ ldr(LR, Address(THR, Thread::write_barrier_entry_point_offset()));
+    __ ldr(LR,
+           Address(THR, target::Thread::write_barrier_entry_point_offset()));
     __ blx(LR);
     __ PopList(saved);
     __ bx(LR);
@@ -1200,18 +1246,18 @@
                                            Address stub_code,
                                            bool cards) {
   Label add_to_mark_stack, remember_card;
-  __ tst(R0, Operand(1 << kNewObjectBitPosition));
+  __ tst(R0, Operand(1 << target::ObjectAlignment::kNewObjectBitPosition));
   __ b(&add_to_mark_stack, ZERO);
 
   if (cards) {
-    __ ldr(TMP, FieldAddress(R1, Object::tags_offset()));
-    __ tst(TMP, Operand(1 << RawObject::kCardRememberedBit));
+    __ ldr(TMP, FieldAddress(R1, target::Object::tags_offset()));
+    __ tst(TMP, Operand(1 << target::RawObject::kCardRememberedBit));
     __ b(&remember_card, NOT_ZERO);
   } else {
 #if defined(DEBUG)
     Label ok;
-    __ ldr(TMP, FieldAddress(R1, Object::tags_offset()));
-    __ tst(TMP, Operand(1 << RawObject::kCardRememberedBit));
+    __ ldr(TMP, FieldAddress(R1, target::Object::tags_offset()));
+    __ tst(TMP, Operand(1 << target::RawObject::kCardRememberedBit));
     __ b(&ok, ZERO);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1226,18 +1272,18 @@
 #if !defined(USING_SIMULATOR)
     ASSERT(OS::NumberOfAvailableProcessors() <= 1);
 #endif
-    __ ldr(R2, FieldAddress(R1, Object::tags_offset()));
-    __ bic(R2, R2, Operand(1 << RawObject::kOldAndNotRememberedBit));
-    __ str(R2, FieldAddress(R1, Object::tags_offset()));
+    __ ldr(R2, FieldAddress(R1, target::Object::tags_offset()));
+    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotRememberedBit));
+    __ str(R2, FieldAddress(R1, target::Object::tags_offset()));
   } else {
     // Atomically set the remembered bit of the object header.
-    ASSERT(Object::tags_offset() == 0);
+    ASSERT(target::Object::tags_offset() == 0);
     __ sub(R3, R1, Operand(kHeapObjectTag));
     // R3: Untagged address of header word (ldrex/strex do not support offsets).
     Label retry;
     __ Bind(&retry);
     __ ldrex(R2, R3);
-    __ bic(R2, R2, Operand(1 << RawObject::kOldAndNotRememberedBit));
+    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotRememberedBit));
     __ strex(R4, R2, R3);
     __ cmp(R4, Operand(1));
     __ b(&retry, EQ);
@@ -1245,18 +1291,18 @@
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  __ ldr(R4, Address(THR, Thread::store_buffer_block_offset()));
-  __ ldr(R2, Address(R4, StoreBufferBlock::top_offset()));
-  __ add(R3, R4, Operand(R2, LSL, kWordSizeLog2));
-  __ str(R1, Address(R3, StoreBufferBlock::pointers_offset()));
+  __ ldr(R4, Address(THR, target::Thread::store_buffer_block_offset()));
+  __ ldr(R2, Address(R4, target::StoreBufferBlock::top_offset()));
+  __ add(R3, R4, Operand(R2, LSL, target::kWordSizeLog2));
+  __ str(R1, Address(R3, target::StoreBufferBlock::pointers_offset()));
 
   // Increment top_ and check for overflow.
   // R2: top_.
   // R4: StoreBufferBlock.
   Label overflow;
   __ add(R2, R2, Operand(1));
-  __ str(R2, Address(R4, StoreBufferBlock::top_offset()));
-  __ CompareImmediate(R2, StoreBufferBlock::kSize);
+  __ str(R2, Address(R4, target::StoreBufferBlock::top_offset()));
+  __ CompareImmediate(R2, target::StoreBufferBlock::kSize);
   // Restore values.
   __ PopList((1 << R2) | (1 << R3) | (1 << R4));
   __ b(&overflow, EQ);
@@ -1268,7 +1314,7 @@
 
   __ Push(CODE_REG);
   __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * kWordSize);
+  __ EnterCallRuntimeFrame(0 * target::kWordSize);
   __ mov(R0, Operand(THR));
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
@@ -1285,31 +1331,31 @@
 #if !defined(USING_SIMULATOR)
     ASSERT(OS::NumberOfAvailableProcessors() <= 1);
 #endif
-    __ ldr(R2, FieldAddress(R0, Object::tags_offset()));
-    __ bic(R2, R2, Operand(1 << RawObject::kOldAndNotMarkedBit));
-    __ str(R2, FieldAddress(R0, Object::tags_offset()));
+    __ ldr(R2, FieldAddress(R0, target::Object::tags_offset()));
+    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
+    __ str(R2, FieldAddress(R0, target::Object::tags_offset()));
   } else {
     // Atomically clear kOldAndNotMarkedBit.
-    ASSERT(Object::tags_offset() == 0);
+    ASSERT(target::Object::tags_offset() == 0);
     __ sub(R3, R0, Operand(kHeapObjectTag));
     // R3: Untagged address of header word (ldrex/strex do not support offsets).
     __ Bind(&marking_retry);
     __ ldrex(R2, R3);
-    __ tst(R2, Operand(1 << RawObject::kOldAndNotMarkedBit));
+    __ tst(R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
     __ b(&lost_race, ZERO);
-    __ bic(R2, R2, Operand(1 << RawObject::kOldAndNotMarkedBit));
+    __ bic(R2, R2, Operand(1 << target::RawObject::kOldAndNotMarkedBit));
     __ strex(R4, R2, R3);
     __ cmp(R4, Operand(1));
     __ b(&marking_retry, EQ);
   }
 
-  __ ldr(R4, Address(THR, Thread::marking_stack_block_offset()));
-  __ ldr(R2, Address(R4, MarkingStackBlock::top_offset()));
-  __ add(R3, R4, Operand(R2, LSL, kWordSizeLog2));
-  __ str(R0, Address(R3, MarkingStackBlock::pointers_offset()));
+  __ ldr(R4, Address(THR, target::Thread::marking_stack_block_offset()));
+  __ ldr(R2, Address(R4, target::MarkingStackBlock::top_offset()));
+  __ add(R3, R4, Operand(R2, LSL, target::kWordSizeLog2));
+  __ str(R0, Address(R3, target::MarkingStackBlock::pointers_offset()));
   __ add(R2, R2, Operand(1));
-  __ str(R2, Address(R4, MarkingStackBlock::top_offset()));
-  __ CompareImmediate(R2, MarkingStackBlock::kSize);
+  __ str(R2, Address(R4, target::MarkingStackBlock::top_offset()));
+  __ CompareImmediate(R2, target::MarkingStackBlock::kSize);
   __ PopList((1 << R4) | (1 << R2) | (1 << R3));  // Unspill.
   __ b(&marking_overflow, EQ);
   __ Ret();
@@ -1317,7 +1363,7 @@
   __ Bind(&marking_overflow);
   __ Push(CODE_REG);
   __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * kWordSize);
+  __ EnterCallRuntimeFrame(0 * target::kWordSize);
   __ mov(R0, Operand(THR));
   __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
   __ LeaveCallRuntimeFrame();
@@ -1333,17 +1379,20 @@
 
     // Get card table.
     __ Bind(&remember_card);
-    __ AndImmediate(TMP, R1, kPageMask);                       // HeapPage.
-    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ AndImmediate(TMP, R1, target::kPageMask);  // HeapPage.
+    __ ldr(TMP,
+           Address(TMP, target::HeapPage::card_table_offset()));  // Card table.
     __ cmp(TMP, Operand(0));
     __ b(&remember_card_slow, EQ);
 
     // Dirty the card.
-    __ AndImmediate(TMP, R1, kPageMask);  // HeapPage.
-    __ sub(R9, R9, Operand(TMP));         // Offset in page.
-    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ AndImmediate(TMP, R1, target::kPageMask);  // HeapPage.
+    __ sub(R9, R9, Operand(TMP));                 // Offset in page.
+    __ ldr(TMP,
+           Address(TMP, target::HeapPage::card_table_offset()));  // Card table.
     __ add(TMP, TMP,
-           Operand(R9, LSR, HeapPage::kBytesPerCardLog2));  // Card address.
+           Operand(R9, LSR,
+                   target::HeapPage::kBytesPerCardLog2));  // Card address.
     __ strb(R1,
             Address(TMP, 0));  // Low byte of R0 is non-zero from object tag.
     __ Ret();
@@ -1366,26 +1415,28 @@
   }
 }
 
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+      assembler, Address(THR, target::Thread::write_barrier_code_offset()),
+      false);
 }
 
-void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateArrayWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
+      assembler,
+      Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
 // Input parameters:
 //   LR : return address.
 //   SP + 0 : type arguments object (only if class is parameterized).
-void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
-                                              const Class& cls) {
+void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
+                                                      const Class& cls) {
   // The generated code is different if the class is parameterized.
-  const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
-  ASSERT(!is_cls_parameterized ||
-         (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
+                                      cls) != target::Class::kNoTypeArguments);
 
   const Register kNullReg = R8;
   const Register kOtherNullReg = R9;
@@ -1398,24 +1449,25 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;
-  const intptr_t instance_size = cls.instance_size();
+  const intptr_t instance_size = target::Class::InstanceSize(cls);
   ASSERT(instance_size > 0);
-  ASSERT(instance_size % kObjectAlignment == 0);
+  ASSERT(instance_size % target::ObjectAlignment::kObjectAlignment == 0);
   if (is_cls_parameterized) {
     __ ldr(kTypeArgumentsReg, Address(SP, 0));
   }
-  Isolate* isolate = Isolate::Current();
 
-  __ LoadObject(kNullReg, Object::null_object());
-  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) &&
-      !cls.TraceAllocation(isolate)) {
+  __ LoadObject(kNullReg, NullObject());
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size) &&
+      !target::Class::TraceAllocation(cls)) {
     Label slow_case;
 
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
 
-    RELEASE_ASSERT((Thread::top_offset() + kWordSize) == Thread::end_offset());
-    __ ldrd(kInstanceReg, kEndReg, THR, Thread::top_offset());
+    RELEASE_ASSERT((target::Thread::top_offset() + target::kWordSize) ==
+                   target::Thread::end_offset());
+    __ ldrd(kInstanceReg, kEndReg, THR, target::Thread::top_offset());
     __ AddImmediate(kEndOfInstanceReg, kInstanceReg, instance_size);
     __ cmp(kEndOfInstanceReg, Operand(kEndReg));
     if (FLAG_use_slow_path) {
@@ -1423,29 +1475,29 @@
     } else {
       __ b(&slow_case, CS);  // Unsigned higher or equal.
     }
-    __ str(kEndOfInstanceReg, Address(THR, Thread::top_offset()));
+    __ str(kEndOfInstanceReg, Address(THR, target::Thread::top_offset()));
 
     // Load the address of the allocation stats table. We split up the load
     // and the increment so that the dependent load is not too nearby.
     NOT_IN_PRODUCT(static Register kAllocationStatsReg = R4);
-    NOT_IN_PRODUCT(
-        __ LoadAllocationStatsAddress(kAllocationStatsReg, cls.id()));
+    NOT_IN_PRODUCT(__ LoadAllocationStatsAddress(kAllocationStatsReg,
+                                                 target::Class::GetId(cls)));
 
     // Set the tags.
-    uint32_t tags = 0;
-    tags = RawObject::SizeTag::update(instance_size, tags);
-    ASSERT(cls.id() != kIllegalCid);
-    tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    tags = RawObject::NewBit::update(true, tags);
+    ASSERT(target::Class::GetId(cls) != kIllegalCid);
+    const uint32_t tags = target::MakeTagWordForNewSpaceObject(
+        target::Class::GetId(cls), instance_size);
+
     __ LoadImmediate(R1, tags);
-    __ str(R1, Address(kInstanceReg, Instance::tags_offset()));
+    __ str(R1, Address(kInstanceReg, target::Object::tags_offset()));
     __ add(kInstanceReg, kInstanceReg, Operand(kHeapObjectTag));
 
     // First try inlining the initialization without a loop.
-    if (instance_size < (kInlineInstanceSize * kWordSize)) {
-      intptr_t begin_offset = Instance::NextFieldOffset() - kHeapObjectTag;
+    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
+      intptr_t begin_offset =
+          target::Instance::first_field_offset() - kHeapObjectTag;
       intptr_t end_offset = instance_size - kHeapObjectTag;
-      if ((end_offset - begin_offset) >= (2 * kWordSize)) {
+      if ((end_offset - begin_offset) >= (2 * target::kWordSize)) {
         __ mov(kOtherNullReg, Operand(kNullReg));
       }
       __ InitializeFieldsNoBarrierUnrolled(kInstanceReg, kInstanceReg,
@@ -1453,20 +1505,20 @@
                                            kOtherNullReg);
     } else {
       __ add(R1, kInstanceReg,
-             Operand(Instance::NextFieldOffset() - kHeapObjectTag));
+             Operand(target::Instance::first_field_offset() - kHeapObjectTag));
       __ mov(kOtherNullReg, Operand(kNullReg));
       __ InitializeFieldsNoBarrier(kInstanceReg, R1, kEndOfInstanceReg,
                                    kNullReg, kOtherNullReg);
     }
     if (is_cls_parameterized) {
+      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
       __ StoreIntoObjectNoBarrier(
-          kInstanceReg,
-          FieldAddress(kInstanceReg, cls.type_arguments_field_offset()),
-          kTypeArgumentsReg);
+          kInstanceReg, FieldAddress(kInstanceReg, offset), kTypeArgumentsReg);
     }
 
     // Update allocation stats.
-    NOT_IN_PRODUCT(__ IncrementAllocationStats(kAllocationStatsReg, cls.id()));
+    NOT_IN_PRODUCT(__ IncrementAllocationStats(kAllocationStatsReg,
+                                               target::Class::GetId(cls)));
 
     __ Ret();
     __ Bind(&slow_case);
@@ -1474,13 +1526,15 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
-  __ LoadObject(R1, cls);
+  __ LoadObject(R1, CastHandle<Object>(cls));
   __ PushList(1 << kNullReg | 1 << R1);  // Pushes cls, result slot.
   __ Push(is_cls_parameterized ? kTypeArgumentsReg : kNullReg);
   __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
-  __ ldr(kInstanceReg,
-         Address(SP, 2 * kWordSize));  // Pop result (newly allocated object).
-  __ LeaveDartFrameAndReturn();        // Restores correct SP.
+  __ ldr(
+      kInstanceReg,
+      Address(SP,
+              2 * target::kWordSize));  // Pop result (newly allocated object).
+  __ LeaveDartFrameAndReturn();         // Restores correct SP.
 }
 
 // Called for invoking "dynamic noSuchMethod(Invocation invocation)" function
@@ -1490,13 +1544,15 @@
 //  LR : return address.
 //  SP : address of last argument.
 //  R4: arguments descriptor array.
-void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ ldr(R2, FieldAddress(R4, ArgumentsDescriptor::count_offset()));
+  __ ldr(R2, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
   __ add(IP, FP, Operand(R2, LSL, 1));  // R2 is Smi.
-  __ ldr(R8, Address(IP, kParamEndSlotFromFp * kWordSize));
+  __ ldr(R8, Address(IP, target::frame_layout.param_end_from_fp *
+                             target::kWordSize));
 
   // Push space for the return value.
   // Push the receiver.
@@ -1505,9 +1561,11 @@
   __ PushList((1 << R4) | (1 << R8) | (1 << IP));
 
   // Adjust arguments count.
-  __ ldr(R3, FieldAddress(R4, ArgumentsDescriptor::type_args_len_offset()));
+  __ ldr(R3,
+         FieldAddress(R4, target::ArgumentsDescriptor::type_args_len_offset()));
   __ cmp(R3, Operand(0));
-  __ AddImmediate(R2, R2, Smi::RawValue(1), NE);  // Include the type arguments.
+  __ AddImmediate(R2, R2, target::ToRawSmi(1),
+                  NE);  // Include the type arguments.
 
   // R2: Smi-tagged arguments array length.
   PushArrayOfArguments(assembler);
@@ -1522,7 +1580,8 @@
 //  R9: inline cache data object.
 // Cannot use function object from ICData as it may be the inlined
 // function and not the top-scope function.
-void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
+    Assembler* assembler) {
   Register ic_reg = R9;
   Register func_reg = R8;
   if (FLAG_trace_optimized_ic_calls) {
@@ -1535,23 +1594,27 @@
     __ PopList((1 << R9) | (1 << R8));  // Restore.
     __ LeaveStubFrame();
   }
-  __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset()));
+  __ ldr(NOTFP,
+         FieldAddress(func_reg, target::Function::usage_counter_offset()));
   __ add(NOTFP, NOTFP, Operand(1));
-  __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset()));
+  __ str(NOTFP,
+         FieldAddress(func_reg, target::Function::usage_counter_offset()));
 }
 
 // Loads function into 'temp_reg'.
-void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
-                                             Register temp_reg) {
+void StubCodeCompiler::GenerateUsageCounterIncrement(Assembler* assembler,
+                                                     Register temp_reg) {
   if (FLAG_optimization_counter_threshold >= 0) {
     Register ic_reg = R9;
     Register func_reg = temp_reg;
     ASSERT(temp_reg == R8);
     __ Comment("Increment function counter");
-    __ ldr(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
-    __ ldr(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset()));
+    __ ldr(func_reg, FieldAddress(ic_reg, target::ICData::owner_offset()));
+    __ ldr(NOTFP,
+           FieldAddress(func_reg, target::Function::usage_counter_offset()));
     __ add(NOTFP, NOTFP, Operand(1));
-    __ str(NOTFP, FieldAddress(func_reg, Function::usage_counter_offset()));
+    __ str(NOTFP,
+           FieldAddress(func_reg, target::Function::usage_counter_offset()));
   }
 }
 
@@ -1564,8 +1627,8 @@
                           intptr_t num_args,
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
-  __ ldr(R0, Address(SP, 0 * kWordSize));
-  __ ldr(R1, Address(SP, 1 * kWordSize));
+  __ ldr(R0, Address(SP, 0 * target::kWordSize));
+  __ ldr(R1, Address(SP, 1 * target::kWordSize));
   __ orr(TMP, R0, Operand(R1));
   __ tst(TMP, Operand(kSmiTagMask));
   __ b(not_smi_or_overflow, NE);
@@ -1582,26 +1645,26 @@
     }
     case Token::kEQ: {
       __ cmp(R0, Operand(R1));
-      __ LoadObject(R0, Bool::True(), EQ);
-      __ LoadObject(R0, Bool::False(), NE);
+      __ LoadObject(R0, CastHandle<Object>(TrueObject()), EQ);
+      __ LoadObject(R0, CastHandle<Object>(FalseObject()), NE);
       break;
     }
     default:
       UNIMPLEMENTED();
   }
   // R9: IC data object (preserved).
-  __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
+  __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
   // R8: ic_data_array with check entries: classes and target functions.
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
 // R8: points directly to the first ic data array element.
 #if defined(DEBUG)
   // Check that first entry is for Smi/Smi.
   Label error, ok;
-  const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid));
+  const intptr_t imm_smi_cid = target::ToRawSmi(kSmiCid);
   __ ldr(R1, Address(R8, 0));
   __ CompareImmediate(R1, imm_smi_cid);
   __ b(&error, NE);
-  __ ldr(R1, Address(R8, kWordSize));
+  __ ldr(R1, Address(R8, target::kWordSize));
   __ CompareImmediate(R1, imm_smi_cid);
   __ b(&ok, EQ);
   __ Bind(&error);
@@ -1610,9 +1673,10 @@
 #endif
   if (FLAG_optimization_counter_threshold >= 0) {
     // Update counter, ignore overflow.
-    const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+    const intptr_t count_offset =
+        target::ICData::CountIndexFor(num_args) * target::kWordSize;
     __ LoadFromOffset(kWord, R1, R8, count_offset);
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreIntoSmiField(Address(R8, count_offset), R1);
   }
   __ Ret();
@@ -1628,7 +1692,7 @@
 // - Check if 'num_args' (including receiver) match any IC data group.
 // - Match found -> jump to target.
 // - Match not found -> jump to IC miss.
-void StubCode::GenerateNArgsCheckInlineCacheStub(
+void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
     Assembler* assembler,
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
@@ -1643,9 +1707,9 @@
     Label ok;
     // Check that the IC data array has NumArgsTested() == num_args.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ and_(R8, R8, Operand(ICData::NumArgsTestedMask()));
+    __ ldr(R8, FieldAddress(R9, target::ICData::state_bits_offset()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ and_(R8, R8, Operand(target::ICData::NumArgsTestedMask()));
     __ CompareImmediate(R8, num_args);
     __ b(&ok, EQ);
     __ Stop("Incorrect stub for IC data");
@@ -1658,7 +1722,7 @@
   if (!optimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(R8);
-    __ ldrb(R8, Address(R8, Isolate::single_step_offset()));
+    __ ldrb(R8, Address(R8, target::Isolate::single_step_offset()));
     __ CompareImmediate(R8, 0);
     __ b(&stepping, NE);
     __ Bind(&done_stepping);
@@ -1673,19 +1737,19 @@
 
   __ Comment("Extract ICData initial values and receiver cid");
   // Load arguments descriptor into R4.
-  __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
+  __ 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, ICData::ic_data_offset()));
+  __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
   // R8: ic_data_array with check entries: classes and target functions.
-  const int kIcDataOffset = Array::data_offset() - kHeapObjectTag;
+  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, ArgumentsDescriptor::count_offset()));
-  __ sub(NOTFP, NOTFP, Operand(Smi::RawValue(1)));
+  __ ldr(NOTFP, FieldAddress(R4, target::ArgumentsDescriptor::count_offset()));
+  __ sub(NOTFP, NOTFP, Operand(target::ToRawSmi(1)));
   // NOTFP: argument_count - 1 (smi).
 
   __ Comment("ICData loop");
@@ -1693,7 +1757,7 @@
   __ ldr(R0, Address(SP, NOTFP, LSL, 1));  // NOTFP (argument_count - 1) is Smi.
   __ LoadTaggedClassIdMayBeSmi(R0, R0);
   if (num_args == 2) {
-    __ sub(R1, NOTFP, Operand(Smi::RawValue(1)));
+    __ sub(R1, NOTFP, Operand(target::ToRawSmi(1)));
     __ ldr(R1, Address(SP, R1, LSL, 1));  // R1 (argument_count - 2) is Smi.
     __ LoadTaggedClassIdMayBeSmi(R1, R1);
   }
@@ -1709,7 +1773,7 @@
     __ cmp(R0, Operand(R2));  // Class id match?
     if (num_args == 2) {
       __ b(&update, NE);  // Continue.
-      __ ldr(R2, Address(R8, kIcDataOffset + kWordSize));
+      __ ldr(R2, Address(R8, kIcDataOffset + target::kWordSize));
       __ cmp(R1, Operand(R2));  // Class id match?
     }
     __ b(&found, EQ);  // Break.
@@ -1717,10 +1781,11 @@
     __ Bind(&update);
 
     const intptr_t entry_size =
-        ICData::TestEntryLengthFor(num_args, exactness_check) * kWordSize;
+        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
+        target::kWordSize;
     __ AddImmediate(R8, entry_size);  // Next entry.
 
-    __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));  // Done?
+    __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));  // Done?
     if (unroll == 0) {
       __ b(&loop, NE);
     } else {
@@ -1743,7 +1808,7 @@
   __ PushList((1 << R0) | (1 << R4) | (1 << R9));
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ LoadFromOffset(kWord, IP, NOTFP, -i * kWordSize);
+    __ LoadFromOffset(kWord, IP, NOTFP, -i * target::kWordSize);
     __ Push(IP);
   }
   // Pass IC data object.
@@ -1765,23 +1830,25 @@
 
   __ Bind(&found);
   // R8: pointer to an IC data check group.
-  const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(num_args) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(num_args) * target::kWordSize;
   __ LoadFromOffset(kWord, R0, R8, kIcDataOffset + target_offset);
 
   if (FLAG_optimization_counter_threshold >= 0) {
     __ Comment("Update caller's counter");
     __ LoadFromOffset(kWord, R1, R8, kIcDataOffset + count_offset);
     // Ignore overflow.
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreIntoSmiField(Address(R8, kIcDataOffset + count_offset), R1);
   }
 
   __ Comment("Call target");
   __ Bind(&call_target_function);
   // R0: target function.
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 
 #if !defined(PRODUCT)
   if (!optimized) {
@@ -1807,43 +1874,45 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
                                     kInlineCacheMissHandlerTwoArgsRuntimeEntry,
                                     Token::kILLEGAL);
 }
 
-void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
-void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
-void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
@@ -1851,12 +1920,13 @@
                                     Token::kILLEGAL, true /* optimized */);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
-    Assembler* assembler) {
+void StubCodeCompiler::
+    GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
+        Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
@@ -1867,16 +1937,17 @@
 // Intermediary stub between a static call and its target. ICData contains
 // the target function and the call count.
 // R9: ICData
-void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
 #if defined(DEBUG)
   {
     Label ok;
     // Check that the IC data array has NumArgsTested() == 0.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ ldr(R8, FieldAddress(R9, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ and_(R8, R8, Operand(ICData::NumArgsTestedMask()));
+    __ ldr(R8, FieldAddress(R9, target::ICData::state_bits_offset()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ and_(R8, R8, Operand(target::ICData::NumArgsTestedMask()));
     __ CompareImmediate(R8, 0);
     __ b(&ok, EQ);
     __ Stop("Incorrect IC data for unoptimized static call");
@@ -1888,34 +1959,36 @@
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(R8);
-  __ ldrb(R8, Address(R8, Isolate::single_step_offset()));
+  __ ldrb(R8, Address(R8, target::Isolate::single_step_offset()));
   __ CompareImmediate(R8, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
 #endif
 
   // R9: IC data object (preserved).
-  __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
+  __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
   // R8: ic_data_array with entries: target functions and count.
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: points directly to the first ic data array element.
-  const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(0) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(0) * target::kWordSize;
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Increment count for this call, ignore overflow.
     __ LoadFromOffset(kWord, R1, R8, count_offset);
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreIntoSmiField(Address(R8, count_offset), R1);
   }
 
   // Load arguments descriptor into R4.
-  __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
+  __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ LoadFromOffset(kWord, R0, R8, target_offset);
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 
 #if !defined(PRODUCT)
   __ Bind(&stepping);
@@ -1929,13 +2002,15 @@
 #endif
 }
 
-void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R8);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
@@ -1944,7 +2019,7 @@
 // Stub for compiling a function and jumping to the compiled code.
 // R4: Arguments descriptor.
 // R0: Function.
-void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ PushList((1 << R0) | (1 << R4));  // Preserve arg desc, pass function.
   __ CallRuntime(kCompileFunctionRuntimeEntry, 1);
@@ -1953,16 +2028,16 @@
 
   // When using the interpreter, the function's code may now point to the
   // InterpretCall stub. Make sure R0, R4, and R9 are preserved.
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 }
 
-void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
   __ Unimplemented("Interpreter not yet supported");
 }
 
 // R9: Contains an ICData.
-void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ LoadImmediate(R0, 0);
   // Preserve arguments descriptor and make room for result.
@@ -1971,10 +2046,10 @@
   __ PopList((1 << R0) | (1 << R9));
   __ LeaveStubFrame();
   __ mov(CODE_REG, Operand(R0));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 }
 
-void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ LoadImmediate(R0, 0);
   // Make room for result.
@@ -1982,15 +2057,18 @@
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ PopList((1 << CODE_REG));
   __ LeaveStubFrame();
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 }
 
 // Called only from unoptimized code. All relevant registers have been saved.
-void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDebugStepCheckStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Ret();
+#else
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(R1);
-  __ ldrb(R1, Address(R1, Isolate::single_step_offset()));
+  __ ldrb(R1, Address(R1, target::Isolate::single_step_offset()));
   __ CompareImmediate(R1, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
@@ -2001,6 +2079,7 @@
   __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
   __ LeaveStubFrame();
   __ b(&done_stepping);
+#endif  // defined(PRODUCT)
 }
 
 // Used to check class and type arguments. Arguments passed in registers:
@@ -2008,7 +2087,7 @@
 // R0: instance (must be preserved).
 // R2: instantiator type arguments (only if n >= 4, can be raw_null).
 // R1: function type arguments (only if n >= 4, can be raw_null).
-// R3: SubtypeTestCache.
+// R3: target::SubtypeTestCache.
 //
 // Preserves R0/R2
 //
@@ -2028,7 +2107,7 @@
 
   const Register kNullReg = NOTFP;
 
-  __ LoadObject(kNullReg, Object::null_object());
+  __ LoadObject(kNullReg, NullObject());
 
   // Free up these 2 registers to be used for 6-value test.
   if (n >= 6) {
@@ -2038,8 +2117,9 @@
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ ldr(kCacheReg, FieldAddress(kCacheReg, SubtypeTestCache::cache_offset()));
-  __ AddImmediate(kCacheReg, Array::data_offset() - kHeapObjectTag);
+  __ ldr(kCacheReg,
+         FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
+  __ AddImmediate(kCacheReg, target::Array::data_offset() - kHeapObjectTag);
 
   Label loop, not_closure;
   if (n >= 4) {
@@ -2053,19 +2133,20 @@
   // Closure handling.
   {
     __ ldr(kInstanceCidOrFunction,
-           FieldAddress(kInstanceReg, Closure::function_offset()));
+           FieldAddress(kInstanceReg, target::Closure::function_offset()));
     if (n >= 2) {
-      __ ldr(kInstanceInstantiatorTypeArgumentsReg,
-             FieldAddress(kInstanceReg,
-                          Closure::instantiator_type_arguments_offset()));
+      __ ldr(
+          kInstanceInstantiatorTypeArgumentsReg,
+          FieldAddress(kInstanceReg,
+                       target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
         __ ldr(kInstanceParentFunctionTypeArgumentsReg,
                FieldAddress(kInstanceReg,
-                            Closure::function_type_arguments_offset()));
+                            target::Closure::function_type_arguments_offset()));
         __ ldr(kInstanceDelayedFunctionTypeArgumentsReg,
                FieldAddress(kInstanceReg,
-                            Closure::delayed_type_arguments_offset()));
+                            target::Closure::delayed_type_arguments_offset()));
       }
     }
     __ b(&loop);
@@ -2078,9 +2159,11 @@
       Label has_no_type_arguments;
       __ LoadClassById(R9, kInstanceCidOrFunction);
       __ mov(kInstanceInstantiatorTypeArgumentsReg, Operand(kNullReg));
-      __ ldr(R9, FieldAddress(
-                     R9, Class::type_arguments_field_offset_in_words_offset()));
-      __ CompareImmediate(R9, Class::kNoTypeArguments);
+      __ ldr(R9,
+             FieldAddress(
+                 R9,
+                 target::Class::type_arguments_field_offset_in_words_offset()));
+      __ CompareImmediate(R9, target::Class::kNoTypeArguments);
       __ b(&has_no_type_arguments, EQ);
       __ add(R9, kInstanceReg, Operand(R9, LSL, 2));
       __ ldr(kInstanceInstantiatorTypeArgumentsReg, FieldAddress(R9, 0));
@@ -2099,7 +2182,8 @@
   // Loop header.
   __ Bind(&loop);
   __ ldr(R9, Address(kCacheReg,
-                     kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
+                     target::kWordSize *
+                         target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(R9, Operand(kNullReg));
   __ b(&not_found, EQ);
   __ cmp(R9, Operand(kInstanceCidOrFunction));
@@ -2108,7 +2192,8 @@
   } else {
     __ b(&next_iteration, NE);
     __ ldr(R9, Address(kCacheReg,
-                       kWordSize * SubtypeTestCache::kInstanceTypeArguments));
+                       target::kWordSize *
+                           target::SubtypeTestCache::kInstanceTypeArguments));
     __ cmp(R9, Operand(kInstanceInstantiatorTypeArgumentsReg));
     if (n == 2) {
       __ b(&found, EQ);
@@ -2116,11 +2201,13 @@
       __ b(&next_iteration, NE);
       __ ldr(R9,
              Address(kCacheReg,
-                     kWordSize * SubtypeTestCache::kInstantiatorTypeArguments));
+                     target::kWordSize *
+                         target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ cmp(R9, Operand(kInstantiatorTypeArgumentsReg));
       __ b(&next_iteration, NE);
       __ ldr(R9, Address(kCacheReg,
-                         kWordSize * SubtypeTestCache::kFunctionTypeArguments));
+                         target::kWordSize *
+                             target::SubtypeTestCache::kFunctionTypeArguments));
       __ cmp(R9, Operand(kFunctionTypeArgumentsReg));
       if (n == 4) {
         __ b(&found, EQ);
@@ -2128,31 +2215,30 @@
         ASSERT(n == 6);
         __ b(&next_iteration, NE);
 
-        __ ldr(R9,
-               Address(
-                   kCacheReg,
-                   kWordSize *
-                       SubtypeTestCache::kInstanceParentFunctionTypeArguments));
+        __ ldr(R9, Address(kCacheReg,
+                           target::kWordSize *
+                               target::SubtypeTestCache::
+                                   kInstanceParentFunctionTypeArguments));
         __ cmp(R9, Operand(kInstanceParentFunctionTypeArgumentsReg));
         __ b(&next_iteration, NE);
 
-        __ ldr(
-            R9,
-            Address(
-                kCacheReg,
-                kWordSize *
-                    SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
+        __ ldr(R9, Address(kCacheReg,
+                           target::kWordSize *
+                               target::SubtypeTestCache::
+                                   kInstanceDelayedFunctionTypeArguments));
         __ cmp(R9, Operand(kInstanceDelayedFunctionTypeArgumentsReg));
         __ b(&found, EQ);
       }
     }
   }
   __ Bind(&next_iteration);
-  __ AddImmediate(kCacheReg, kWordSize * SubtypeTestCache::kTestEntryLength);
+  __ AddImmediate(kCacheReg, target::kWordSize *
+                                 target::SubtypeTestCache::kTestEntryLength);
   __ b(&loop);
 
   __ Bind(&found);
-  __ ldr(R1, Address(kCacheReg, kWordSize * SubtypeTestCache::kTestResult));
+  __ ldr(R1, Address(kCacheReg, target::kWordSize *
+                                    target::SubtypeTestCache::kTestResult));
   if (n >= 6) {
     __ PopList(1 << kInstanceParentFunctionTypeArgumentsReg |
                1 << kInstanceDelayedFunctionTypeArgumentsReg);
@@ -2169,22 +2255,22 @@
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype1TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 1);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype2TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 2);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype4TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 4);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype6TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype6TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 6);
 }
 
@@ -2205,85 +2291,38 @@
 //
 // Note of warning: The caller will not populate CODE_REG and we have therefore
 // no access to the pool.
-void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
   Label done;
 
   const Register kInstanceReg = R0;
   // Fast case for 'null'.
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
-  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::slow_type_test_stub_offset()));
+  __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 
   __ Bind(&done);
   __ Ret();
 }
 
-void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
   __ Ret();
 }
 
-void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
   const Register kTypeRefReg = R8;
 
   // We dereference the TypeRef and tail-call to it's type testing stub.
-  __ ldr(kTypeRefReg, FieldAddress(kTypeRefReg, TypeRef::type_offset()));
-  __ ldr(R9, FieldAddress(kTypeRefReg,
-                          AbstractType::type_test_stub_entry_point_offset()));
+  __ ldr(kTypeRefReg,
+         FieldAddress(kTypeRefReg, target::TypeRef::type_offset()));
+  __ ldr(R9, FieldAddress(
+                 kTypeRefReg,
+                 target::AbstractType::type_test_stub_entry_point_offset()));
   __ bx(R9);
 }
 
-void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const Type& type,
-    const Class& type_class) {
-  const Register kInstanceReg = R0;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
-
-  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
-}
-
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
-                                                      HierarchyInfo* hi,
-                                                      const Class& type_class,
-                                                      const TypeArguments& tp,
-                                                      const TypeArguments& ta) {
-  const Register kInstanceReg = R0;
-  const Register kInstanceTypeArguments = NOTFP;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    Label* check_failed) {
-  const Register kInstantiatorTypeArgumentsReg = R2;
-  const Register kFunctionTypeArgumentsReg = R1;
-  const Register kInstanceTypeArguments = NOTFP;
-
-  const Register kClassIdReg = R9;
-  const Register kOwnTypeArgumentValue = TMP;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
-void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
   __ Breakpoint();
 }
 
@@ -2295,14 +2334,14 @@
   const Register kDstTypeReg = R8;
   const Register kSubtypeTestCacheReg = R3;
 
-  __ PushObject(Object::null_object());  // Make room for result.
+  __ PushObject(NullObject());  // Make room for result.
   __ Push(kInstanceReg);
   __ Push(kDstTypeReg);
   __ Push(kInstantiatorTypeArgumentsReg);
   __ Push(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
+  __ PushObject(NullObject());
   __ Push(kSubtypeTestCacheReg);
-  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ PushImmediate(target::ToRawSmi(mode));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);  // mode
   __ Pop(kSubtypeTestCacheReg);
@@ -2314,15 +2353,16 @@
   __ Drop(1);  // Discard return value.
 }
 
-void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
+    Assembler* assembler) {
   const Register kInstanceReg = R0;
   Label done;
 
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
   __ ldr(CODE_REG,
-         Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+         Address(THR, target::Thread::lazy_specialize_type_test_stub_offset()));
   __ EnterStubFrame();
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
   __ LeaveStubFrame();
@@ -2331,7 +2371,7 @@
   __ Ret();
 }
 
-void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
@@ -2344,14 +2384,14 @@
 #ifdef DEBUG
   // Guaranteed by caller.
   Label no_error;
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(NOT_EQUAL, &no_error);
   __ Breakpoint();
   __ Bind(&no_error);
 #endif
 
   // If the subtype-cache is null, it needs to be lazily-created by the runtime.
-  __ CompareObject(kSubtypeTestCacheReg, Object::null_object());
+  __ CompareObject(kSubtypeTestCacheReg, NullObject());
   __ BranchIf(EQUAL, &call_runtime);
 
   const Register kTmp = NOTFP;
@@ -2363,13 +2403,14 @@
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is instantiated/uninstantiated.
-  __ ldrb(kTmp, FieldAddress(kDstTypeReg, Type::type_state_offset()));
-  __ cmp(kTmp, Operand(RawType::kFinalizedInstantiated));
+  __ ldrb(kTmp, FieldAddress(kDstTypeReg, target::Type::type_state_offset()));
+  __ cmp(kTmp,
+         Operand(target::RawAbstractType::kTypeStateFinalizedInstantiated));
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is a function type.
-  __ ldr(kTmp, FieldAddress(kDstTypeReg, Type::signature_offset()));
-  __ CompareObject(kTmp, Object::null_object());
+  __ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
+  __ CompareObject(kTmp, NullObject());
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
@@ -2384,8 +2425,8 @@
   __ Bind(&is_simple_case);
   {
     __ PushList(kRegsToSave);
-    __ BranchLink(StubCode::Subtype2TestCache());
-    __ CompareObject(R1, Bool::True());
+    __ BranchLink(StubCodeSubtype2TestCache());
+    __ CompareObject(R1, CastHandle<Object>(TrueObject()));
     __ PopList(kRegsToSave);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     __ Jump(&call_runtime);
@@ -2394,8 +2435,8 @@
   __ Bind(&is_complex_case);
   {
     __ PushList(kRegsToSave);
-    __ BranchLink(StubCode::Subtype6TestCache());
-    __ CompareObject(R1, Bool::True());
+    __ BranchLink(StubCodeSubtype6TestCache());
+    __ CompareObject(R1, CastHandle<Object>(TrueObject()));
     __ PopList(kRegsToSave);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     // Fall through to runtime_call
@@ -2408,11 +2449,11 @@
   // because we do constant evaluation with default stubs and only install
   // optimized versions before writing out the AOT snapshot.
   // So dynamic/Object/void will run with default stub in constant evaluation.
-  __ CompareObject(kDstTypeReg, Type::dynamic_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(DynamicType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(ObjectType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::void_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(VoidType()));
   __ BranchIf(EQUAL, &done);
 
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
@@ -2423,7 +2464,7 @@
 }
 
 // Return the current stack pointer address, used to do stack alignment checks.
-void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateGetCStackPointerStub(Assembler* assembler) {
   __ mov(R0, Operand(SP));
   __ Ret();
 }
@@ -2435,7 +2476,7 @@
 // R2: frame_pointer.
 // R3: thread.
 // Does not return.
-void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
   ASSERT(kExceptionObjectReg == R0);
   ASSERT(kStackTraceObjectReg == R1);
   __ mov(IP, Operand(R1));   // Copy Stack pointer into IP.
@@ -2445,14 +2486,15 @@
   __ mov(SP, Operand(IP));   // Set Stack pointer.
   // Set the tag.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(kWord, R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::vm_tag_offset());
   // Clear top exit frame.
   __ LoadImmediate(R2, 0);
-  __ StoreToOffset(kWord, R2, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(kWord, R2, THR,
+                   target::Thread::top_exit_frame_info_offset());
   // Restore the pool pointer.
   __ RestoreCodePointer();
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
     __ set_constant_pool_allowed(true);
   } else {
     __ LoadPoolPointer();
@@ -2465,20 +2507,21 @@
 //
 // The arguments are stored in the Thread object.
 // Does not return.
-void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset());
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+  __ LoadFromOffset(kWord, LR, THR, target::Thread::resume_pc_offset());
 
-  ASSERT(Thread::CanLoadFromThread(Object::null_object()));
-  __ LoadFromOffset(kWord, R2, THR,
-                    Thread::OffsetFromThread(Object::null_object()));
+  word offset_from_thread = 0;
+  bool ok = target::CanLoadFromThread(NullObject(), &offset_from_thread);
+  ASSERT(ok);
+  __ LoadFromOffset(kWord, R2, THR, offset_from_thread);
 
   // Exception object.
-  __ LoadFromOffset(kWord, R0, THR, Thread::active_exception_offset());
-  __ StoreToOffset(kWord, R2, THR, Thread::active_exception_offset());
+  __ LoadFromOffset(kWord, R0, THR, target::Thread::active_exception_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::active_exception_offset());
 
   // StackTrace object.
-  __ LoadFromOffset(kWord, R1, THR, Thread::active_stacktrace_offset());
-  __ StoreToOffset(kWord, R2, THR, Thread::active_stacktrace_offset());
+  __ LoadFromOffset(kWord, R1, THR, target::Thread::active_stacktrace_offset());
+  __ StoreToOffset(kWord, R2, THR, target::Thread::active_stacktrace_offset());
 
   __ bx(LR);  // Jump to the exception handler code.
 }
@@ -2486,13 +2529,13 @@
 // Deoptimize a frame on the call stack before rewinding.
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
   // Push zap value instead of CODE_REG.
   __ LoadImmediate(IP, kZapCodeReg);
   __ Push(IP);
 
   // Load the deopt pc into LR.
-  __ LoadFromOffset(kWord, LR, THR, Thread::resume_pc_offset());
+  __ LoadFromOffset(kWord, LR, THR, target::Thread::resume_pc_offset());
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -2505,7 +2548,7 @@
 // Calls to the runtime to optimize the given function.
 // R8: function to be reoptimized.
 // R4: argument descriptor (preserved).
-void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R4);
   __ LoadImmediate(IP, 0);
@@ -2516,8 +2559,8 @@
   __ Pop(R0);  // Get Function object
   __ Pop(R4);  // Restore argument descriptor.
   __ LeaveStubFrame();
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
   __ bkpt(0);
 }
 
@@ -2544,12 +2587,16 @@
   __ b(&done, NE);
 
   // Double values bitwise compare.
-  __ ldr(temp, FieldAddress(left, Double::value_offset() + 0 * kWordSize));
-  __ ldr(IP, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
+  __ ldr(temp, FieldAddress(left, target::Double::value_offset() +
+                                      0 * target::kWordSize));
+  __ ldr(IP, FieldAddress(right, target::Double::value_offset() +
+                                     0 * target::kWordSize));
   __ cmp(temp, Operand(IP));
   __ b(&done, NE);
-  __ ldr(temp, FieldAddress(left, Double::value_offset() + 1 * kWordSize));
-  __ ldr(IP, FieldAddress(right, Double::value_offset() + 1 * kWordSize));
+  __ ldr(temp, FieldAddress(left, target::Double::value_offset() +
+                                      1 * target::kWordSize));
+  __ ldr(IP, FieldAddress(right, target::Double::value_offset() +
+                                     1 * target::kWordSize));
   __ cmp(temp, Operand(IP));
   __ b(&done);
 
@@ -2558,12 +2605,16 @@
   __ b(&reference_compare, NE);
   __ CompareClassId(right, kMintCid, temp);
   __ b(&done, NE);
-  __ ldr(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
-  __ ldr(IP, FieldAddress(right, Mint::value_offset() + 0 * kWordSize));
+  __ ldr(temp, FieldAddress(
+                   left, target::Mint::value_offset() + 0 * target::kWordSize));
+  __ ldr(IP, FieldAddress(
+                 right, target::Mint::value_offset() + 0 * target::kWordSize));
   __ cmp(temp, Operand(IP));
   __ b(&done, NE);
-  __ ldr(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize));
-  __ ldr(IP, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
+  __ ldr(temp, FieldAddress(
+                   left, target::Mint::value_offset() + 1 * target::kWordSize));
+  __ ldr(IP, FieldAddress(
+                 right, target::Mint::value_offset() + 1 * target::kWordSize));
   __ cmp(temp, Operand(IP));
   __ b(&done);
 
@@ -2577,13 +2628,13 @@
 // SP + 4: left operand.
 // SP + 0: right operand.
 // Return Zero condition flag set if equal.
-void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
 #if !defined(PRODUCT)
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(R1);
-  __ ldrb(R1, Address(R1, Isolate::single_step_offset()));
+  __ ldrb(R1, Address(R1, target::Isolate::single_step_offset()));
   __ CompareImmediate(R1, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
@@ -2592,8 +2643,8 @@
   const Register temp = R2;
   const Register left = R1;
   const Register right = R0;
-  __ ldr(left, Address(SP, 1 * kWordSize));
-  __ ldr(right, Address(SP, 0 * kWordSize));
+  __ ldr(left, Address(SP, 1 * target::kWordSize));
+  __ ldr(right, Address(SP, 0 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ Ret();
 
@@ -2612,13 +2663,13 @@
 // SP + 4: left operand.
 // SP + 0: right operand.
 // Return Zero condition flag set if equal.
-void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
   const Register temp = R2;
   const Register left = R1;
   const Register right = R0;
-  __ ldr(left, Address(SP, 1 * kWordSize));
-  __ ldr(right, Address(SP, 0 * kWordSize));
+  __ ldr(left, Address(SP, 1 * target::kWordSize));
+  __ ldr(right, Address(SP, 0 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ Ret();
 }
@@ -2629,16 +2680,16 @@
 // Passed to target:
 //  CODE_REG: target Code
 //  R4: arguments descriptor
-void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   __ LoadTaggedClassIdMayBeSmi(R0, R0);
   // R0: receiver cid as Smi.
-  __ ldr(R2, FieldAddress(R9, MegamorphicCache::buckets_offset()));
-  __ ldr(R1, FieldAddress(R9, MegamorphicCache::mask_offset()));
+  __ ldr(R2, FieldAddress(R9, target::MegamorphicCache::buckets_offset()));
+  __ ldr(R1, FieldAddress(R9, target::MegamorphicCache::mask_offset()));
   // R2: cache buckets array.
   // R1: mask as a smi.
 
   // Compute the table index.
-  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
   // Use reverse substract to multiply with 7 == 8 - 1.
   __ rsb(R3, R0, Operand(R0, LSL, 3));
   // R3: probe.
@@ -2646,7 +2697,7 @@
   __ Bind(&loop);
   __ and_(R3, R3, Operand(R1));
 
-  const intptr_t base = Array::data_offset();
+  const intptr_t base = target::Array::data_offset();
   // R3 is smi tagged, but table entries are two words, so LSL 2.
   Label probe_failed;
   __ add(IP, R2, Operand(R3, LSL, 2));
@@ -2660,17 +2711,19 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address = FieldAddress(IP, base + kWordSize);
+  const auto target_address = FieldAddress(IP, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ ldr(ARGS_DESC_REG,
-           FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset()));
+           FieldAddress(
+               R9, target::MegamorphicCache::arguments_descriptor_offset()));
     __ Branch(target_address);
   } else {
     __ ldr(R0, target_address);
-    __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
+    __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
     __ ldr(ARGS_DESC_REG,
-           FieldAddress(R9, MegamorphicCache::arguments_descriptor_offset()));
-    __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+           FieldAddress(
+               R9, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
   }
 
   // Probe failed, check if it is a miss.
@@ -2680,7 +2733,7 @@
   __ b(&load_target, EQ);  // branch if miss.
 
   // Try next entry in the table.
-  __ AddImmediate(R3, Smi::RawValue(1));
+  __ AddImmediate(R3, target::ToRawSmi(1));
   __ b(&loop);
 }
 
@@ -2690,12 +2743,12 @@
 // Passed to target:
 //  CODE_REG: target Code object
 //  R4: arguments descriptor
-void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(ARGS_DESC_REG,
-         FieldAddress(R9, ICData::arguments_descriptor_offset()));
-  __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+         FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+  __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
   // R1: receiver cid as Smi
@@ -2704,31 +2757,33 @@
   __ ldr(R2, Address(R8, 0));
   __ cmp(R1, Operand(R2));
   __ b(&found, EQ);
-  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
   __ b(&miss, EQ);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ AddImmediate(R8, entry_length);  // Next entry.
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(1) * target::kWordSize;
   __ LoadFromOffset(kWord, R0, R8, target_offset);
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
-  __ Branch(FieldAddress(R0, Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
+  __ Branch(FieldAddress(R0, target::Function::entry_point_offset()));
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
-  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
+  __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 }
 
-void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
-  __ ldr(R8, FieldAddress(R9, ICData::ic_data_offset()));
-  __ ldr(R4, FieldAddress(R9, ICData::arguments_descriptor_offset()));
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+  __ ldr(R8, FieldAddress(R9, target::ICData::entries_offset()));
+  __ ldr(R4, FieldAddress(R9, target::ICData::arguments_descriptor_offset()));
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
   // R1: receiver cid as Smi
@@ -2737,17 +2792,20 @@
   __ ldr(R2, Address(R8, 0));
   __ cmp(R1, Operand(R2));
   __ b(&found, EQ);
-  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
   __ b(&miss, EQ);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ AddImmediate(R8, entry_length);  // Next entry.
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
-  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  const intptr_t code_offset =
+      target::ICData::CodeIndexFor(1) * target::kWordSize;
+  const intptr_t entry_offset =
+      target::ICData::EntryPointIndexFor(1) * target::kWordSize;
   if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ ldr(CODE_REG, Address(R8, code_offset));
   }
@@ -2755,14 +2813,14 @@
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
-  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
-  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
+  __ Branch(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 }
 
 // Called from switchable IC calls.
 //  R0: receiver
 //  R9: UnlinkedCall
-void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
@@ -2777,9 +2835,10 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
   __ Branch(FieldAddress(
-      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic)));
 }
 
 // Called from switchable IC calls.
@@ -2787,19 +2846,22 @@
 //  R9: SingleTargetCache
 // Passed to target:
 //  CODE_REG: target Code object
-void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
   Label miss;
   __ LoadClassIdMayBeSmi(R1, R0);
-  __ ldrh(R2, FieldAddress(R9, SingleTargetCache::lower_limit_offset()));
-  __ ldrh(R3, FieldAddress(R9, SingleTargetCache::upper_limit_offset()));
+  __ ldrh(R2,
+          FieldAddress(R9, target::SingleTargetCache::lower_limit_offset()));
+  __ ldrh(R3,
+          FieldAddress(R9, target::SingleTargetCache::upper_limit_offset()));
 
   __ cmp(R1, Operand(R2));
   __ b(&miss, LT);
   __ cmp(R1, Operand(R3));
   __ b(&miss, GT);
 
-  __ ldr(CODE_REG, FieldAddress(R9, SingleTargetCache::target_offset()));
-  __ Branch(FieldAddress(R9, SingleTargetCache::entry_point_offset()));
+  __ ldr(CODE_REG,
+         FieldAddress(R9, target::SingleTargetCache::target_offset()));
+  __ Branch(FieldAddress(R9, target::SingleTargetCache::entry_point_offset()));
 
   __ Bind(&miss);
   __ EnterStubFrame();
@@ -2815,15 +2877,17 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
   __ Branch(FieldAddress(
-      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic)));
 }
 
 // Called from the monomorphic checked entry.
 //  R0: receiver
-void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset()));
+void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::monomorphic_miss_stub_offset()));
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
@@ -2837,19 +2901,23 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
   __ Branch(FieldAddress(
-      CODE_REG, Code::entry_point_offset(Code::EntryKind::kMonomorphic)));
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kMonomorphic)));
 }
 
-void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
+    Assembler* assembler) {
   __ bkpt(0);
 }
 
-void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
   __ bkpt(0);
 }
 
+}  // namespace compiler
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/stub_code_arm64.cc b/runtime/vm/compiler/stub_code_compiler_arm64.cc
similarity index 66%
rename from runtime/vm/stub_code_arm64.cc
rename to runtime/vm/compiler/stub_code_compiler_arm64.cc
index bca7db2..30acf68 100644
--- a/runtime/vm/stub_code_arm64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_arm64.cc
@@ -1,22 +1,23 @@
-// Copyright (c) 2014, 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.
 
 #include "vm/globals.h"
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/stub_code_compiler.h"
+
 #if defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/class_id.h"
+#include "vm/code_entry_kind.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/constants_arm64.h"
 #include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/runtime_entry.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/tags.h"
-#include "vm/type_testing_stubs.h"
 
 #define __ assembler->
 
@@ -30,6 +31,8 @@
 DECLARE_FLAG(bool, enable_interpreter);
 DECLARE_FLAG(bool, precompiled_mode);
 
+namespace compiler {
+
 // Input parameters:
 //   LR : return address.
 //   SP : address of last argument in argument array.
@@ -37,26 +40,26 @@
 //   SP + 8*R4 : address of return value.
 //   R5 : address of the runtime function to call.
 //   R4 : number of arguments to the call.
-void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
   __ Comment("CallToRuntimeStub");
-  __ ldr(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::call_to_runtime_stub_offset()));
   __ SetPrologueOffset();
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R8, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(R8, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -65,41 +68,42 @@
 #endif
 
   // Mark that the thread is executing VM code.
-  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for arguments and align frame before entering C++ world.
-  // NativeArguments are passed in registers.
+  // target::NativeArguments are passed in registers.
   __ Comment("align stack");
   // Reserve space for arguments.
-  ASSERT(sizeof(NativeArguments) == 4 * kWordSize);
-  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+  ASSERT(target::NativeArguments::StructSize() == 4 * target::kWordSize);
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
 
-  // Pass NativeArguments structure by value and call runtime.
+  // Pass target::NativeArguments structure by value and call runtime.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, THR);
 
   // There are no runtime calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  __ mov(R1, R4);  // Set argc in NativeArguments.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  __ mov(R1, R4);  // Set argc in target::NativeArguments.
 
-  ASSERT(argv_offset == 2 * kWordSize);
+  ASSERT(argv_offset == 2 * target::kWordSize);
   __ add(R2, ZR, Operand(R4, LSL, 3));
   __ add(R2, FP, Operand(R2));  // Compute argv.
-  // Set argv in NativeArguments.
-  __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize);
+  // Set argv in target::NativeArguments.
+  __ AddImmediate(R2,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
 
-  ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, R2, kWordSize);
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ AddImmediate(R3, R2, target::kWordSize);
 
   __ StoreToOffset(R0, SP, thread_offset);
   __ StoreToOffset(R1, SP, argc_tag_offset);
   __ StoreToOffset(R2, SP, argv_offset);
   __ StoreToOffset(R3, SP, retval_offset);
-  __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
+  __ mov(R0, SP);  // Pass the pointer to the target::NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
   // the stack limit to the top of the stack. We cache the stack limit address
@@ -115,20 +119,21 @@
   __ mov(CSP, R25);
 
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Retval is next to 1st argument.
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
 
   // Restore the global object pool after returning from runtime (old space is
   // moving, so the GOP could have been relocated).
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
     __ sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
   }
 
@@ -143,11 +148,12 @@
   __ ret();
 }
 
-void StubCode::GenerateSharedStub(Assembler* assembler,
-                                  bool save_fpu_registers,
-                                  const RuntimeEntry* target,
-                                  intptr_t self_code_stub_offset_from_thread,
-                                  bool allow_return) {
+void StubCodeCompiler::GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   RegisterSet all_registers;
@@ -172,29 +178,21 @@
 
 // R1: The extracted method.
 // R4: The type_arguments_field_offset (or 0)
-void StubCode::GenerateBuildMethodExtractorStub(Assembler* assembler) {
-  Thread* thread = Thread::Current();
-  Zone* Z = thread->zone();
-  ObjectStore* object_store = thread->isolate()->object_store();
-
-  const auto& closure_class =
-      Class::ZoneHandle(Z, object_store->closure_class());
-  const auto& closure_allocation_stub =
-      Code::ZoneHandle(Z, StubCode::GetAllocationStubForClass(closure_class));
-
+void StubCodeCompiler::GenerateBuildMethodExtractorStub(
+    Assembler* assembler,
+    const Object& closure_allocation_stub,
+    const Object& context_allocation_stub) {
   const intptr_t kReceiverOffset =
       compiler::target::frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub = StubCode::AllocateContext();
-
   __ EnterStubFrame();
 
   // Build type_arguments vector (or null)
   Label no_type_args;
-  __ ldr(R3, Address(THR, Thread::object_null_offset()), kDoubleWord);
+  __ ldr(R3, Address(THR, target::Thread::object_null_offset()), kDoubleWord);
   __ cmp(R4, Operand(0));
   __ b(&no_type_args, EQ);
-  __ ldr(R0, Address(FP, kReceiverOffset * kWordSize));
+  __ ldr(R0, Address(FP, kReceiverOffset * target::kWordSize));
   __ ldr(R3, Address(R0, R4));
   __ Bind(&no_type_args);
 
@@ -204,86 +202,94 @@
   // Allocate context.
   {
     Label done, slow_path;
-    __ TryAllocateArray(kContextCid, Context::InstanceSize(1), &slow_path,
+    __ TryAllocateArray(kContextCid, target::Context::InstanceSize(1),
+                        &slow_path,
                         R0,  // instance
                         R1,  // end address
                         R2, R3);
-    __ ldr(R1, Address(THR, Thread::object_null_offset()));
-    __ str(R1, FieldAddress(R0, Context::parent_offset()));
+    __ ldr(R1, Address(THR, target::Thread::object_null_offset()));
+    __ str(R1, FieldAddress(R0, target::Context::parent_offset()));
     __ LoadImmediate(R1, 1);
-    __ str(R1, FieldAddress(R0, Context::num_variables_offset()));
+    __ str(R1, FieldAddress(R0, target::Context::num_variables_offset()));
     __ b(&done);
 
     __ Bind(&slow_path);
 
     __ LoadImmediate(/*num_vars=*/R1, 1);
     __ LoadObject(CODE_REG, context_allocation_stub);
-    __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+    __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
     __ blr(R0);
 
     __ Bind(&done);
   }
 
   // Store receiver in context
-  __ ldr(R1, Address(FP, kWordSize * kReceiverOffset));
-  __ StoreIntoObject(R0, FieldAddress(R0, Context::variable_offset(0)), R1);
+  __ ldr(R1, Address(FP, target::kWordSize * kReceiverOffset));
+  __ StoreIntoObject(R0, FieldAddress(R0, target::Context::variable_offset(0)),
+                     R1);
 
   // Push context.
   __ Push(R0);
 
   // Allocate closure.
   __ LoadObject(CODE_REG, closure_allocation_stub);
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                        Code::EntryKind::kUnchecked)));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kUnchecked)));
   __ blr(R1);
 
   // Populate closure object.
   __ Pop(R1);  // Pop context.
-  __ StoreIntoObject(R0, FieldAddress(R0, Closure::context_offset()), R1);
+  __ StoreIntoObject(R0, FieldAddress(R0, target::Closure::context_offset()),
+                     R1);
   __ PopPair(R3, R1);  // Pop type arguments & extracted method.
-  __ StoreIntoObjectNoBarrier(R0, FieldAddress(R0, Closure::function_offset()),
-                              R1);
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Closure::instantiator_type_arguments_offset()), R3);
-  __ LoadObject(R1, Object::empty_type_arguments());
+      R0, FieldAddress(R0, target::Closure::function_offset()), R1);
   __ StoreIntoObjectNoBarrier(
-      R0, FieldAddress(R0, Closure::delayed_type_arguments_offset()), R1);
+      R0,
+      FieldAddress(R0, target::Closure::instantiator_type_arguments_offset()),
+      R3);
+  __ LoadObject(R1, EmptyTypeArguments());
+  __ StoreIntoObjectNoBarrier(
+      R0, FieldAddress(R0, target::Closure::delayed_type_arguments_offset()),
+      R1);
 
   __ LeaveStubFrame();
   __ Ret();
 }
 
-void StubCode::GenerateNullErrorSharedWithoutFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/false,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_without_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateNullErrorSharedWithFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateStackOverflowSharedWithoutFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
     Assembler* assembler) {
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
-      Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
+      target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
       /*allow_return=*/true);
 }
 
-void StubCode::GenerateStackOverflowSharedWithFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kStackOverflowRuntimeEntry,
-                     Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/true);
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
+      target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/true);
 }
 
-void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
+void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
   __ Stop("GeneratePrintStopMessageStub");
 }
 
@@ -295,22 +301,22 @@
 //   R1 : argc_tag including number of arguments and function kind.
 static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
                                               Address wrapper) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R6, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(R6, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R6, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -319,31 +325,31 @@
 #endif
 
   // Mark that the thread is executing native code.
-  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // R0) and align frame before entering the C++ world.
-  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
 
-  // Initialize NativeArguments structure and call native function.
+  // Initialize target::NativeArguments structure and call native function.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, THR);
 
   // There are no native calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  // Set argc in NativeArguments: R1 already contains argc.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  // Set argc in target::NativeArguments: R1 already contains argc.
 
-  ASSERT(argv_offset == 2 * kWordSize);
-  // Set argv in NativeArguments: R2 already contains argv.
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  // Set argv in target::NativeArguments: R2 already contains argv.
 
   // Set retval in NativeArgs.
-  ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, FP, 2 * kWordSize);
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ AddImmediate(R3, FP, 2 * target::kWordSize);
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
@@ -352,7 +358,7 @@
   __ StoreToOffset(R1, SP, argc_tag_offset);
   __ StoreToOffset(R2, SP, argv_offset);
   __ StoreToOffset(R3, SP, retval_offset);
-  __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
+  __ mov(R0, SP);  // Pass the pointer to the target::NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
   // the stack limit to the top of the stack. We cache the stack limit address
@@ -371,29 +377,32 @@
   __ mov(CSP, R25);
 
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
 }
 
-void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallNoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::no_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::no_scope_native_wrapper_entry_point_offset()));
 }
 
-void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::auto_scope_native_wrapper_entry_point_offset()));
 }
 
 // Input parameters:
@@ -402,23 +411,23 @@
 //   R5 : address of the native function to call.
 //   R2 : address of first argument in argument array.
 //   R1 : argc_tag including number of arguments and function kind.
-void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
 
 #if defined(DEBUG)
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R6, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(R6, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R6, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -427,31 +436,31 @@
 #endif
 
   // Mark that the thread is executing native code.
-  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
 
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // R0) and align frame before entering the C++ world.
-  __ ReserveAlignedFrameSpace(sizeof(NativeArguments));
+  __ ReserveAlignedFrameSpace(target::NativeArguments::StructSize());
 
-  // Initialize NativeArguments structure and call native function.
+  // Initialize target::NativeArguments structure and call native function.
   // Registers R0, R1, R2, and R3 are used.
 
-  ASSERT(thread_offset == 0 * kWordSize);
+  ASSERT(thread_offset == 0 * target::kWordSize);
   // Set thread in NativeArgs.
   __ mov(R0, THR);
 
   // There are no native calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  ASSERT(argc_tag_offset == 1 * kWordSize);
-  // Set argc in NativeArguments: R1 already contains argc.
+  ASSERT(argc_tag_offset == 1 * target::kWordSize);
+  // Set argc in target::NativeArguments: R1 already contains argc.
 
-  ASSERT(argv_offset == 2 * kWordSize);
-  // Set argv in NativeArguments: R2 already contains argv.
+  ASSERT(argv_offset == 2 * target::kWordSize);
+  // Set argv in target::NativeArguments: R2 already contains argv.
 
   // Set retval in NativeArgs.
-  ASSERT(retval_offset == 3 * kWordSize);
-  __ AddImmediate(R3, FP, 2 * kWordSize);
+  ASSERT(retval_offset == 3 * target::kWordSize);
+  __ AddImmediate(R3, FP, 2 * target::kWordSize);
 
   // Passing the structure by value as in runtime calls would require changing
   // Dart API for native functions.
@@ -460,7 +469,7 @@
   __ StoreToOffset(R1, SP, argc_tag_offset);
   __ StoreToOffset(R2, SP, argv_offset);
   __ StoreToOffset(R3, SP, retval_offset);
-  __ mov(R0, SP);  // Pass the pointer to the NativeArguments.
+  __ mov(R0, SP);  // Pass the pointer to the target::NativeArguments.
 
   // We are entering runtime code, so the C stack pointer must be restored from
   // the stack limit to the top of the stack. We cache the stack limit address
@@ -476,14 +485,15 @@
   __ mov(CSP, R25);
 
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
@@ -491,7 +501,7 @@
 
 // Input parameters:
 //   R4: arguments descriptor array.
-void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallStaticFunctionStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
@@ -505,18 +515,19 @@
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
+  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
   __ br(R0);
 }
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
 // R4: arguments descriptor array.
-void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ ldr(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::fix_callers_target_code_offset()));
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
@@ -530,17 +541,19 @@
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
+  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
   __ br(R0);
 }
 
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
-void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixAllocationStubTargetStub(
+    Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ ldr(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ Push(ZR);
@@ -550,25 +563,26 @@
   // Remove the stub frame.
   __ LeaveStubFrame();
   // Jump to the dart function.
-  __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
+  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
   __ br(R0);
 }
 
 // Input parameters:
 //   R2: smi-tagged argument count, may be zero.
-//   FP[kParamEndSlotFromFp + 1]: last argument.
+//   FP[target::frame_layout.param_end_from_fp + 1]: last argument.
 static void PushArrayOfArguments(Assembler* assembler) {
   // Allocate array to store arguments of caller.
-  __ LoadObject(R1, Object::null_object());
+  __ LoadObject(R1, NullObject());
   // R1: null element type for raw Array.
   // R2: smi-tagged argument count, may be zero.
-  __ BranchLink(StubCode::AllocateArray());
+  __ BranchLink(StubCodeAllocateArray());
   // R0: newly allocated array.
   // R2: smi-tagged argument count, may be zero (was preserved by the stub).
   __ Push(R0);  // Array is in R0 and on top of stack.
   __ add(R1, FP, Operand(R2, LSL, 2));
-  __ AddImmediate(R1, kParamEndSlotFromFp * kWordSize);
-  __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R1,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
+  __ AddImmediate(R3, R0, target::Array::data_offset() - kHeapObjectTag);
   // R1: address of first argument on stack.
   // R3: address of first argument in array.
 
@@ -577,10 +591,10 @@
   __ b(&loop_exit, LE);
   __ Bind(&loop);
   __ ldr(R7, Address(R1));
-  __ AddImmediate(R1, -kWordSize);
-  __ AddImmediate(R3, kWordSize);
-  __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1));
-  __ str(R7, Address(R3, -kWordSize));
+  __ AddImmediate(R1, -target::kWordSize);
+  __ AddImmediate(R3, target::kWordSize);
+  __ AddImmediateSetFlags(R2, R2, -target::ToRawSmi(1));
+  __ str(R7, Address(R3, -target::kWordSize));
   __ b(&loop, GE);
   __ Bind(&loop_exit);
 }
@@ -638,10 +652,10 @@
       // Save the original value of CODE_REG pushed before invoking this stub
       // instead of the value used to call this stub.
       COMPILE_ASSERT(R25 > CODE_REG);
-      __ ldr(R25, Address(FP, 2 * kWordSize));
-      __ str(R25, Address(SP, -1 * kWordSize, Address::PreIndex));
+      __ ldr(R25, Address(FP, 2 * target::kWordSize));
+      __ str(R25, Address(SP, -1 * target::kWordSize, Address::PreIndex));
     } else {
-      __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
+      __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
     }
   }
 
@@ -660,11 +674,12 @@
 
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1 temporarily.
-    __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * kWordSize);
+    __ LoadFromOffset(R1, FP, saved_result_slot_from_fp * target::kWordSize);
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into R1 temporarily.
-    __ LoadFromOffset(R1, FP, saved_exception_slot_from_fp * kWordSize);
-    __ LoadFromOffset(R2, FP, saved_stacktrace_slot_from_fp * kWordSize);
+    __ LoadFromOffset(R1, FP, saved_exception_slot_from_fp * target::kWordSize);
+    __ LoadFromOffset(R2, FP,
+                      saved_stacktrace_slot_from_fp * target::kWordSize);
   }
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -688,14 +703,16 @@
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into R1.
     __ LoadFromOffset(
-        R1, FP, compiler::target::frame_layout.first_local_from_fp * kWordSize);
+        R1, FP,
+        compiler::target::frame_layout.first_local_from_fp * target::kWordSize);
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into R1.
     __ LoadFromOffset(
-        R1, FP, compiler::target::frame_layout.first_local_from_fp * kWordSize);
-    __ LoadFromOffset(
-        R2, FP,
-        (compiler::target::frame_layout.first_local_from_fp - 1) * kWordSize);
+        R1, FP,
+        compiler::target::frame_layout.first_local_from_fp * target::kWordSize);
+    __ LoadFromOffset(R2, FP,
+                      (compiler::target::frame_layout.first_local_from_fp - 1) *
+                          target::kWordSize);
   }
   // Code above cannot cause GC.
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -733,33 +750,37 @@
 }
 
 // R0: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(TMP, kZapCodeReg);
   __ Push(TMP);
   // Return address for "call" to deopt stub.
   __ LoadImmediate(LR, kZapReturnAddress);
-  __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
   __ ret();
 }
 
 // R0: exception, must be preserved
 // R1: stacktrace, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ LoadImmediate(TMP, kZapCodeReg);
   __ Push(TMP);
   // Return address for "call" to deopt stub.
   __ LoadImmediate(LR, kZapReturnAddress);
-  __ ldr(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset()));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
   __ ret();
 }
 
-void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
   __ Push(CODE_REG);
-  __ ldr(CODE_REG, Address(THR, Thread::deoptimize_stub_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::deoptimize_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
   __ ret();
 }
@@ -769,21 +790,23 @@
   __ Comment("NoSuchMethodDispatch");
   // When lazily generated invocation dispatchers are disabled, the
   // miss-handler may return null.
-  __ CompareObject(R0, Object::null_object());
+  __ CompareObject(R0, NullObject());
   __ b(call_target_function, NE);
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
+  __ LoadFromOffset(R6, TMP,
+                    target::frame_layout.param_end_from_fp * target::kWordSize);
   __ Push(ZR);  // Result slot.
   __ Push(R6);  // Receiver.
   __ Push(R5);  // ICData/MegamorphicCache.
   __ Push(R4);  // Arguments descriptor.
 
   // Adjust arguments count.
-  __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+  __ LoadFieldFromOffset(R3, R4,
+                         target::ArgumentsDescriptor::type_args_len_offset());
   __ AddImmediate(TMP, R2, 1);  // Include the type arguments.
   __ cmp(R3, Operand(0));
   __ csinc(R2, R2, TMP, EQ);  // R2 <- (R3 == 0) ? R2 : TMP + 1 (R2 : R2 + 2).
@@ -798,14 +821,15 @@
   __ ret();
 }
 
-void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
   __ LoadFromOffset(
-      R6, TMP, compiler::target::frame_layout.param_end_from_fp * kWordSize);
+      R6, TMP,
+      compiler::target::frame_layout.param_end_from_fp * target::kWordSize);
 
   // Preserve IC data and arguments descriptor.
   __ Push(R5);
@@ -838,8 +862,8 @@
   }
 
   // Tail-call to target function.
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-  __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
+  __ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
   __ br(R2);
 }
 
@@ -850,11 +874,12 @@
 //   R1: array element type (either NULL or an instantiated type).
 // NOTE: R2 cannot be clobbered here as the caller relies on it being saved.
 // The newly allocated object is returned in R0.
-void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
-  // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+  // RoundedAllocationSize(
+  //     (array_length * kwordSize) + target::Array::header_size()).
   // Assert that length is a Smi.
   __ tsti(R2, Immediate(kSmiTagMask));
   if (FLAG_use_slow_path) {
@@ -867,7 +892,7 @@
 
   // Check for maximum allowed length.
   const intptr_t max_len =
-      reinterpret_cast<intptr_t>(Smi::New(Array::kMaxNewSpaceElements));
+      target::ToRawSmi(target::Array::kMaxNewSpaceElements);
   __ CompareImmediate(R2, max_len);
   __ b(&slow_case, GT);
 
@@ -878,13 +903,14 @@
   // Load new object start and calculate next object start.
   // R1: array element type.
   // R2: array length as Smi.
-  __ ldr(R0, Address(THR, Thread::top_offset()));
+  __ ldr(R0, Address(THR, target::Thread::top_offset()));
   intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawArray) + kObjectAlignment - 1;
+      target::Array::header_size() + target::ObjectAlignment::kObjectAlignment -
+      1;
   __ LoadImmediate(R3, fixed_size_plus_alignment_padding);
   __ add(R3, R3, Operand(R2, LSL, 2));  // R2 is Smi.
   ASSERT(kSmiTagShift == 1);
-  __ andi(R3, R3, Immediate(~(kObjectAlignment - 1)));
+  __ andi(R3, R3, Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));
   // R0: potential new object start.
   // R3: object size in bytes.
   __ adds(R7, R3, Operand(R0));
@@ -896,7 +922,7 @@
   // R2: array length as Smi.
   // R3: array size.
   // R7: potential next object start.
-  __ LoadFromOffset(TMP, THR, Thread::end_offset());
+  __ LoadFromOffset(TMP, THR, target::Thread::end_offset());
   __ CompareRegisters(R7, TMP);
   __ b(&slow_case, CS);  // Branch if unsigned higher or equal.
 
@@ -905,7 +931,7 @@
   // R0: potential new object start.
   // R3: array size.
   // R7: potential next object start.
-  __ str(R7, Address(THR, Thread::top_offset()));
+  __ str(R7, Address(THR, target::Thread::top_offset()));
   __ add(R0, R0, Operand(kHeapObjectTag));
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R3));
 
@@ -916,46 +942,48 @@
   // R7: new object end address.
 
   // Store the type argument field.
-  __ StoreIntoObjectOffsetNoBarrier(R0, Array::type_arguments_offset(), R1);
+  __ StoreIntoObjectOffsetNoBarrier(R0, target::Array::type_arguments_offset(),
+                                    R1);
 
   // Set the length field.
-  __ StoreIntoObjectOffsetNoBarrier(R0, Array::length_offset(), R2);
+  __ StoreIntoObjectOffsetNoBarrier(R0, target::Array::length_offset(), R2);
 
   // Calculate the size tag.
   // R0: new object start as a tagged pointer.
   // R2: array length as Smi.
   // R3: array size.
   // R7: new object end address.
-  const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
-  __ CompareImmediate(R3, RawObject::SizeTag::kMaxSizeTag);
+  const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                         target::ObjectAlignment::kObjectAlignmentLog2;
+  __ CompareImmediate(R3, target::RawObject::kSizeTagMaxSizeTag);
   // If no size tag overflow, shift R1 left, else set R1 to zero.
   __ LslImmediate(TMP, R3, shift);
   __ csel(R1, TMP, R1, LS);
   __ csel(R1, ZR, R1, HI);
 
   // Get the class index and insert it into the tags.
-  uint32_t tags = 0;
-  tags = RawObject::ClassIdTag::update(cid, tags);
-  tags = RawObject::NewBit::update(true, tags);
+  const uint32_t tags =
+      target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+
   __ LoadImmediate(TMP, tags);
   __ orr(R1, R1, Operand(TMP));
-  __ StoreFieldToOffset(R1, R0, Array::tags_offset());
+  __ StoreFieldToOffset(R1, R0, target::Array::tags_offset());
 
   // Initialize all array elements to raw_null.
   // R0: new object start as a tagged pointer.
   // R7: new object end address.
   // R2: array length as Smi.
-  __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R1, R0, target::Array::data_offset() - kHeapObjectTag);
   // R1: iterator which initially points to the start of the variable
   // data area to be initialized.
-  __ LoadObject(TMP, Object::null_object());
+  __ LoadObject(TMP, NullObject());
   Label loop, done;
   __ Bind(&loop);
   // TODO(cshapiro): StoreIntoObjectNoBarrier
   __ CompareRegisters(R1, R7);
   __ b(&done, CS);
   __ str(TMP, Address(R1));  // Store if unsigned lower.
-  __ AddImmediate(R1, kWordSize);
+  __ AddImmediate(R1, target::kWordSize);
   __ b(&loop);  // Loop until R1 == R7.
   __ Bind(&done);
 
@@ -991,7 +1019,7 @@
 //   R1 : arguments descriptor array.
 //   R2 : arguments array.
 //   R3 : current thread.
-void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ Comment("InvokeDartCodeStub");
 
   // Copy the C stack pointer (R31) into the stack pointer we'll actually use
@@ -1001,7 +1029,7 @@
   __ EnterFrame(0);
 
   // Push code object to PC marker slot.
-  __ ldr(TMP, Address(R3, Thread::invoke_dart_code_stub_offset()));
+  __ ldr(TMP, Address(R3, target::Thread::invoke_dart_code_stub_offset()));
   __ Push(TMP);
 
   // Save the callee-saved registers.
@@ -1010,7 +1038,7 @@
     // We use str instead of the Push macro because we will be pushing the PP
     // register when it is not holding a pool-pointer since we are coming from
     // C++ code.
-    __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
+    __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
   }
 
   // Save the bottom 64-bits of callee-saved V registers.
@@ -1024,34 +1052,37 @@
     __ mov(THR, R3);
   }
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Save the current VMTag on the stack.
-  __ LoadFromOffset(R4, THR, Thread::vm_tag_offset());
+  __ LoadFromOffset(R4, THR, target::Thread::vm_tag_offset());
   __ Push(R4);
 
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
-  __ StoreToOffset(ZR, THR, Thread::top_resource_offset());
+  __ LoadFromOffset(R6, THR, target::Thread::top_resource_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_resource_offset());
   __ Push(R6);
-  __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset());
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
-  // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
-  ASSERT(kExitLinkSlotFromEntryFp == -22);
+  __ LoadFromOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+  // target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
+  // with the code below.
+  ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -22);
   __ Push(R6);
 
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ LoadImmediate(R6, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R6, THR, target::Thread::vm_tag_offset());
 
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle);
 
   // Load number of arguments into R5 and adjust count for type arguments.
-  __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset());
-  __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+  __ LoadFieldFromOffset(R5, R4, target::ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R3, R4,
+                         target::ArgumentsDescriptor::type_args_len_offset());
   __ AddImmediate(TMP, R5, 1);  // Include the type arguments.
   __ cmp(R3, Operand(0));
   __ csinc(R5, R5, TMP, EQ);  // R5 <- (R3 == 0) ? R5 : TMP + 1 (R5 : R5 + 2).
@@ -1059,7 +1090,7 @@
 
   // Compute address of 'arguments array' data area into R2.
   __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle);
-  __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R2, target::Array::data_offset() - kHeapObjectTag);
 
   // Set up arguments for the Dart call.
   Label push_arguments;
@@ -1071,40 +1102,42 @@
   __ ldr(R3, Address(R2));
   __ Push(R3);
   __ add(R1, R1, Operand(1));
-  __ add(R2, R2, Operand(kWordSize));
+  __ add(R2, R2, Operand(target::kWordSize));
   __ cmp(R1, Operand(R5));
   __ b(&push_arguments, LT);
   __ Bind(&done_push_arguments);
 
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
     __ sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
   } else {
     // We now load the pool pointer(PP) with a GC safe value as we are about to
     // invoke dart code. We don't need a real object pool here.
     // Smi zero does not work because ARM64 assumes PP to be untagged.
-    __ LoadObject(PP, Object::null_object());
+    __ LoadObject(PP, NullObject());
   }
 
   // Call the Dart code entrypoint.
   __ ldr(CODE_REG, Address(R0, VMHandles::kOffsetOfRawPtrInHandle));
-  __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ blr(R0);  // R4 is the arguments descriptor array.
   __ Comment("InvokeDartCodeStub return");
 
   // Get rid of arguments pushed on the stack.
-  __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
+  __ AddImmediate(
+      SP, FP,
+      target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R6 as a temporary register for this.
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_resource_offset());
+  __ StoreToOffset(R6, THR, target::Thread::top_resource_offset());
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
-  __ StoreToOffset(R4, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
   // Restore the bottom 64-bits of callee-saved V registers.
   for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
@@ -1119,7 +1152,7 @@
     // register when it is not holding a pool-pointer since we are returning to
     // C++ code. We also skip the dart stack pointer SP, since we are still
     // using it as the stack pointer.
-    __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
+    __ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
   }
 
   // Restore the frame pointer and C stack pointer and return.
@@ -1136,7 +1169,8 @@
 //   R1 : arguments raw descriptor array.
 //   R2 : address of first argument.
 //   R3 : current thread.
-void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
+    Assembler* assembler) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   __ Stop("Not using interpreter");
 #else
@@ -1148,7 +1182,8 @@
 
   // Push code object to PC marker slot.
   __ ldr(TMP,
-         Address(R3, Thread::invoke_dart_code_from_bytecode_stub_offset()));
+         Address(R3,
+                 target::Thread::invoke_dart_code_from_bytecode_stub_offset()));
   __ Push(TMP);
 
   // Save the callee-saved registers.
@@ -1157,7 +1192,7 @@
     // We use str instead of the Push macro because we will be pushing the PP
     // register when it is not holding a pool-pointer since we are coming from
     // C++ code.
-    __ str(r, Address(SP, -1 * kWordSize, Address::PreIndex));
+    __ str(r, Address(SP, -1 * target::kWordSize, Address::PreIndex));
   }
 
   // Save the bottom 64-bits of callee-saved V registers.
@@ -1171,34 +1206,37 @@
     __ mov(THR, R3);
   }
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Save the current VMTag on the stack.
-  __ LoadFromOffset(R4, THR, Thread::vm_tag_offset());
+  __ LoadFromOffset(R4, THR, target::Thread::vm_tag_offset());
   __ Push(R4);
 
   // Save top resource and top exit frame info. Use R6 as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ LoadFromOffset(R6, THR, Thread::top_resource_offset());
-  __ StoreToOffset(ZR, THR, Thread::top_resource_offset());
+  __ LoadFromOffset(R6, THR, target::Thread::top_resource_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_resource_offset());
   __ Push(R6);
-  __ LoadFromOffset(R6, THR, Thread::top_exit_frame_info_offset());
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
-  // kExitLinkSlotFromEntryFp must be kept in sync with the code below.
-  ASSERT(kExitLinkSlotFromEntryFp == -22);
+  __ LoadFromOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
+  // target::frame_layout.exit_link_slot_from_entry_fp must be kept in sync
+  // with the code below.
+  ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -22);
   __ Push(R6);
 
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
   __ LoadImmediate(R6, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R6, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R6, THR, target::Thread::vm_tag_offset());
 
   // Load arguments descriptor array into R4, which is passed to Dart code.
   __ mov(R4, R1);
 
   // Load number of arguments into R5 and adjust count for type arguments.
-  __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset());
-  __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+  __ LoadFieldFromOffset(R5, R4, target::ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R3, R4,
+                         target::ArgumentsDescriptor::type_args_len_offset());
   __ AddImmediate(TMP, R5, 1);  // Include the type arguments.
   __ cmp(R3, Operand(0));
   __ csinc(R5, R5, TMP, EQ);  // R5 <- (R3 == 0) ? R5 : TMP + 1 (R5 : R5 + 2).
@@ -1215,7 +1253,7 @@
   __ ldr(R3, Address(R2));
   __ Push(R3);
   __ add(R1, R1, Operand(1));
-  __ add(R2, R2, Operand(kWordSize));
+  __ add(R2, R2, Operand(target::kWordSize));
   __ cmp(R1, Operand(R5));
   __ b(&push_arguments, LT);
   __ Bind(&done_push_arguments);
@@ -1223,26 +1261,28 @@
   // We now load the pool pointer(PP) with a GC safe value as we are about to
   // invoke dart code. We don't need a real object pool here.
   // Smi zero does not work because ARM64 assumes PP to be untagged.
-  __ LoadObject(PP, Object::null_object());
+  __ LoadObject(PP, NullObject());
 
   // Call the Dart code entrypoint.
   __ mov(CODE_REG, R0);
-  __ ldr(R0, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(R0, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ blr(R0);  // R4 is the arguments descriptor array.
 
   // Get rid of arguments pushed on the stack.
-  __ AddImmediate(SP, FP, kExitLinkSlotFromEntryFp * kWordSize);
+  __ AddImmediate(
+      SP, FP,
+      target::frame_layout.exit_link_slot_from_entry_fp * target::kWordSize);
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure. Uses R6 as a temporary register for this.
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(R6, THR, target::Thread::top_exit_frame_info_offset());
   __ Pop(R6);
-  __ StoreToOffset(R6, THR, Thread::top_resource_offset());
+  __ StoreToOffset(R6, THR, target::Thread::top_resource_offset());
 
   // Restore the current VMTag from the stack.
   __ Pop(R4);
-  __ StoreToOffset(R4, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R4, THR, target::Thread::vm_tag_offset());
 
   // Restore the bottom 64-bits of callee-saved V registers.
   for (int i = kAbiLastPreservedFpuReg; i >= kAbiFirstPreservedFpuReg; i--) {
@@ -1257,7 +1297,7 @@
     // register when it is not holding a pool-pointer since we are returning to
     // C++ code. We also skip the dart stack pointer SP, since we are still
     // using it as the stack pointer.
-    __ ldr(r, Address(SP, 1 * kWordSize, Address::PostIndex));
+    __ ldr(r, Address(SP, 1 * target::kWordSize, Address::PostIndex));
   }
 
   // Restore the frame pointer and C stack pointer and return.
@@ -1273,31 +1313,33 @@
 //   R1: number of context variables.
 // Output:
 //   R0: new allocated RawContext object.
-void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
     // R1: number of context variables.
     intptr_t fixed_size_plus_alignment_padding =
-        sizeof(RawContext) + kObjectAlignment - 1;
+        target::Context::header_size() +
+        target::ObjectAlignment::kObjectAlignment - 1;
     __ LoadImmediate(R2, fixed_size_plus_alignment_padding);
     __ add(R2, R2, Operand(R1, LSL, 3));
     ASSERT(kSmiTagShift == 1);
-    __ andi(R2, R2, Immediate(~(kObjectAlignment - 1)));
+    __ andi(R2, R2,
+            Immediate(~(target::ObjectAlignment::kObjectAlignment - 1)));
 
     NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, R4, &slow_case));
     // Now allocate the object.
     // R1: number of context variables.
     // R2: object size.
     const intptr_t cid = kContextCid;
-    __ ldr(R0, Address(THR, Thread::top_offset()));
+    __ ldr(R0, Address(THR, target::Thread::top_offset()));
     __ add(R3, R2, Operand(R0));
     // Check if the allocation fits into the remaining space.
     // R0: potential new object.
     // R1: number of context variables.
     // R2: object size.
     // R3: potential next object start.
-    __ ldr(TMP, Address(THR, Thread::end_offset()));
+    __ ldr(TMP, Address(THR, target::Thread::end_offset()));
     __ CompareRegisters(R3, TMP);
     if (FLAG_use_slow_path) {
       __ b(&slow_case);
@@ -1311,7 +1353,7 @@
     // R1: number of context variables.
     // R2: object size.
     // R3: next object start.
-    __ str(R3, Address(THR, Thread::top_offset()));
+    __ str(R3, Address(THR, target::Thread::top_offset()));
     __ add(R0, R0, Operand(kHeapObjectTag));
     NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, R2));
 
@@ -1319,8 +1361,9 @@
     // R0: new object.
     // R1: number of context variables.
     // R2: object size.
-    const intptr_t shift = RawObject::kSizeTagPos - kObjectAlignmentLog2;
-    __ CompareImmediate(R2, RawObject::SizeTag::kMaxSizeTag);
+    const intptr_t shift = target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2;
+    __ CompareImmediate(R2, target::RawObject::kSizeTagMaxSizeTag);
     // If no size tag overflow, shift R2 left, else set R2 to zero.
     __ LslImmediate(TMP, R2, shift);
     __ csel(R2, TMP, R2, LS);
@@ -1328,30 +1371,31 @@
 
     // Get the class index and insert it into the tags.
     // R2: size and bit tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    const uint32_t tags =
+        target::MakeTagWordForNewSpaceObject(cid, /*instance_size=*/0);
+
     __ LoadImmediate(TMP, tags);
     __ orr(R2, R2, Operand(TMP));
-    __ StoreFieldToOffset(R2, R0, Context::tags_offset());
+    __ StoreFieldToOffset(R2, R0, target::Object::tags_offset());
 
     // Setup up number of context variables field.
     // R0: new object.
     // R1: number of context variables as integer value (not object).
-    __ StoreFieldToOffset(R1, R0, Context::num_variables_offset());
+    __ StoreFieldToOffset(R1, R0, target::Context::num_variables_offset());
 
     // Setup the parent field.
     // R0: new object.
     // R1: number of context variables.
-    __ LoadObject(R2, Object::null_object());
-    __ StoreFieldToOffset(R2, R0, Context::parent_offset());
+    __ LoadObject(R2, NullObject());
+    __ StoreFieldToOffset(R2, R0, target::Context::parent_offset());
 
     // Initialize the context variables.
     // R0: new object.
     // R1: number of context variables.
     // R2: raw null.
     Label loop, done;
-    __ AddImmediate(R3, R0, Context::variable_offset(0) - kHeapObjectTag);
+    __ AddImmediate(R3, R0,
+                    target::Context::variable_offset(0) - kHeapObjectTag);
     __ Bind(&loop);
     __ subs(R1, R1, Operand(1));
     __ b(&done, MI);
@@ -1370,7 +1414,7 @@
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ SmiTag(R1);
-  __ PushObject(Object::null_object());
+  __ PushObject(NullObject());
   __ Push(R1);
   __ CallRuntime(kAllocateContextRuntimeEntry, 1);  // Allocate context.
   __ Drop(1);  // Pop number of context variables argument.
@@ -1381,7 +1425,7 @@
   __ ret();
 }
 
-void StubCode::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
     if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
 
@@ -1390,7 +1434,8 @@
     __ Push(LR);
     __ Push(kWriteBarrierObjectReg);
     __ mov(kWriteBarrierObjectReg, reg);
-    __ ldr(LR, Address(THR, Thread::write_barrier_entry_point_offset()));
+    __ ldr(LR,
+           Address(THR, target::Thread::write_barrier_entry_point_offset()));
     __ blr(LR);
     __ Pop(kWriteBarrierObjectReg);
     __ Pop(LR);
@@ -1415,16 +1460,17 @@
                                            Address stub_code,
                                            bool cards) {
   Label add_to_mark_stack, remember_card;
-  __ tbz(&add_to_mark_stack, R0, kNewObjectBitPosition);
+  __ tbz(&add_to_mark_stack, R0,
+         target::ObjectAlignment::kNewObjectBitPosition);
 
   if (cards) {
-    __ LoadFieldFromOffset(TMP, R1, Object::tags_offset(), kWord);
-    __ tbnz(&remember_card, TMP, RawObject::kCardRememberedBit);
+    __ LoadFieldFromOffset(TMP, R1, target::Object::tags_offset(), kWord);
+    __ tbnz(&remember_card, TMP, target::RawObject::kCardRememberedBit);
   } else {
 #if defined(DEBUG)
     Label ok;
-    __ LoadFieldFromOffset(TMP, R1, Object::tags_offset(), kWord);
-    __ tbz(&ok, TMP, RawObject::kCardRememberedBit);
+    __ LoadFieldFromOffset(TMP, R1, target::Object::tags_offset(), kWord);
+    __ tbz(&ok, TMP, target::RawObject::kCardRememberedBit);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
 #endif
@@ -1436,7 +1482,7 @@
   __ Push(R4);
 
   // Atomically set the remembered bit of the object header.
-  ASSERT(Object::tags_offset() == 0);
+  ASSERT(target::Object::tags_offset() == 0);
   __ sub(R3, R1, Operand(kHeapObjectTag));
   // R3: Untagged address of header word (ldxr/stxr do not support offsets).
   // Note that we use 32 bit operations here to match the size of the
@@ -1444,24 +1490,26 @@
   Label retry;
   __ Bind(&retry);
   __ ldxr(R2, R3, kWord);
-  __ AndImmediate(R2, R2, ~(1 << RawObject::kOldAndNotRememberedBit));
+  __ AndImmediate(R2, R2, ~(1 << target::RawObject::kOldAndNotRememberedBit));
   __ stxr(R4, R2, R3, kWord);
   __ cbnz(&retry, R4);
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
-  __ LoadFromOffset(R4, THR, Thread::store_buffer_block_offset());
-  __ LoadFromOffset(R2, R4, StoreBufferBlock::top_offset(), kUnsignedWord);
-  __ add(R3, R4, Operand(R2, LSL, kWordSizeLog2));
-  __ StoreToOffset(R1, R3, StoreBufferBlock::pointers_offset());
+  __ LoadFromOffset(R4, THR, target::Thread::store_buffer_block_offset());
+  __ LoadFromOffset(R2, R4, target::StoreBufferBlock::top_offset(),
+                    kUnsignedWord);
+  __ add(R3, R4, Operand(R2, LSL, target::kWordSizeLog2));
+  __ StoreToOffset(R1, R3, target::StoreBufferBlock::pointers_offset());
 
   // Increment top_ and check for overflow.
   // R2: top_.
   // R4: StoreBufferBlock.
   Label overflow;
   __ add(R2, R2, Operand(1));
-  __ StoreToOffset(R2, R4, StoreBufferBlock::top_offset(), kUnsignedWord);
-  __ CompareImmediate(R2, StoreBufferBlock::kSize);
+  __ StoreToOffset(R2, R4, target::StoreBufferBlock::top_offset(),
+                   kUnsignedWord);
+  __ CompareImmediate(R2, target::StoreBufferBlock::kSize);
   // Restore values.
   __ Pop(R4);
   __ Pop(R3);
@@ -1475,7 +1523,7 @@
 
   __ Push(CODE_REG);
   __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * kWordSize);
+  __ EnterCallRuntimeFrame(0 * target::kWordSize);
   __ mov(R0, THR);
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
@@ -1492,23 +1540,25 @@
   // Note that we use 32 bit operations here to match the size of the
   // background sweeper which is also manipulating this 32 bit word.
   Label marking_retry, lost_race, marking_overflow;
-  ASSERT(Object::tags_offset() == 0);
+  ASSERT(target::Object::tags_offset() == 0);
   __ sub(R3, R0, Operand(kHeapObjectTag));
   // R3: Untagged address of header word (ldxr/stxr do not support offsets).
   __ Bind(&marking_retry);
   __ ldxr(R2, R3, kWord);
-  __ tbz(&lost_race, R2, RawObject::kOldAndNotMarkedBit);
-  __ AndImmediate(R2, R2, ~(1 << RawObject::kOldAndNotMarkedBit));
+  __ tbz(&lost_race, R2, target::RawObject::kOldAndNotMarkedBit);
+  __ AndImmediate(R2, R2, ~(1 << target::RawObject::kOldAndNotMarkedBit));
   __ stxr(R4, R2, R3, kWord);
   __ cbnz(&marking_retry, R4);
 
-  __ LoadFromOffset(R4, THR, Thread::marking_stack_block_offset());
-  __ LoadFromOffset(R2, R4, MarkingStackBlock::top_offset(), kUnsignedWord);
-  __ add(R3, R4, Operand(R2, LSL, kWordSizeLog2));
-  __ StoreToOffset(R0, R3, MarkingStackBlock::pointers_offset());
+  __ LoadFromOffset(R4, THR, target::Thread::marking_stack_block_offset());
+  __ LoadFromOffset(R2, R4, target::MarkingStackBlock::top_offset(),
+                    kUnsignedWord);
+  __ add(R3, R4, Operand(R2, LSL, target::kWordSizeLog2));
+  __ StoreToOffset(R0, R3, target::MarkingStackBlock::pointers_offset());
   __ add(R2, R2, Operand(1));
-  __ StoreToOffset(R2, R4, MarkingStackBlock::top_offset(), kUnsignedWord);
-  __ CompareImmediate(R2, MarkingStackBlock::kSize);
+  __ StoreToOffset(R2, R4, target::MarkingStackBlock::top_offset(),
+                   kUnsignedWord);
+  __ CompareImmediate(R2, target::MarkingStackBlock::kSize);
   __ Pop(R4);  // Unspill.
   __ Pop(R3);  // Unspill.
   __ Pop(R2);  // Unspill.
@@ -1518,7 +1568,7 @@
   __ Bind(&marking_overflow);
   __ Push(CODE_REG);
   __ ldr(CODE_REG, stub_code);
-  __ EnterCallRuntimeFrame(0 * kWordSize);
+  __ EnterCallRuntimeFrame(0 * target::kWordSize);
   __ mov(R0, THR);
   __ CallRuntime(kMarkingStackBlockProcessRuntimeEntry, 1);
   __ LeaveCallRuntimeFrame();
@@ -1536,16 +1586,19 @@
 
     // Get card table.
     __ Bind(&remember_card);
-    __ AndImmediate(TMP, R1, kPageMask);                       // HeapPage.
-    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ AndImmediate(TMP, R1, target::kPageMask);  // HeapPage.
+    __ ldr(TMP,
+           Address(TMP, target::HeapPage::card_table_offset()));  // Card table.
     __ cbz(&remember_card_slow, TMP);
 
     // Dirty the card.
-    __ AndImmediate(TMP, R1, kPageMask);  // HeapPage.
-    __ sub(R25, R25, Operand(TMP));       // Offset in page.
-    __ ldr(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ AndImmediate(TMP, R1, target::kPageMask);  // HeapPage.
+    __ sub(R25, R25, Operand(TMP));               // Offset in page.
+    __ ldr(TMP,
+           Address(TMP, target::HeapPage::card_table_offset()));  // Card table.
     __ add(TMP, TMP,
-           Operand(R25, LSR, HeapPage::kBytesPerCardLog2));  // Card address.
+           Operand(R25, LSR,
+                   target::HeapPage::kBytesPerCardLog2));  // Card address.
     __ str(R1, Address(TMP, 0),
            kUnsignedByte);  // Low byte of R1 is non-zero from object tag.
     __ ret();
@@ -1566,26 +1619,28 @@
   }
 }
 
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+      assembler, Address(THR, target::Thread::write_barrier_code_offset()),
+      false);
 }
 
-void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateArrayWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
+      assembler,
+      Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
 // Input parameters:
 //   LR : return address.
 //   SP + 0 : type arguments object (only if class is parameterized).
-void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
-                                              const Class& cls) {
+void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
+                                                      const Class& cls) {
   // The generated code is different if the class is parameterized.
-  const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
-  ASSERT(!is_cls_parameterized ||
-         (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
+                                      cls) != target::Class::kNoTypeArguments);
 
   const Register kTypeArgumentsReg = R1;
   const Register kInstanceReg = R0;
@@ -1597,47 +1652,49 @@
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;
-  const intptr_t instance_size = cls.instance_size();
+  const intptr_t instance_size = target::Class::InstanceSize(cls);
   ASSERT(instance_size > 0);
   if (is_cls_parameterized) {
     __ ldr(kTypeArgumentsReg, Address(SP));
   }
-  Isolate* isolate = Isolate::Current();
 
-  __ LoadObject(kNullReg, Object::null_object());
-  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) &&
-      !cls.TraceAllocation(isolate)) {
+  __ LoadObject(kNullReg, NullObject());
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size) &&
+      !target::Class::TraceAllocation(cls)) {
     Label slow_case;
     // Allocate the object & initialize header word.
     __ TryAllocate(cls, &slow_case, kInstanceReg, kTopReg,
                    /*tag_result=*/false);
 
     // Initialize the remaining words of the object.
-    if (instance_size < (kInlineInstanceSize * kWordSize)) {
-      intptr_t current_offset = Instance::NextFieldOffset();
-      while ((current_offset + kWordSize) < instance_size) {
+    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
+      intptr_t current_offset = target::Instance::first_field_offset();
+      while ((current_offset + target::kWordSize) < instance_size) {
         __ stp(kNullReg, kNullReg,
                Address(kInstanceReg, current_offset, Address::PairOffset));
-        current_offset += 2 * kWordSize;
+        current_offset += 2 * target::kWordSize;
       }
       while (current_offset < instance_size) {
         __ str(kNullReg, Address(kInstanceReg, current_offset));
-        current_offset += kWordSize;
+        current_offset += target::kWordSize;
       }
     } else {
-      __ AddImmediate(kTempReg, kInstanceReg, Instance::NextFieldOffset());
+      __ AddImmediate(kTempReg, kInstanceReg,
+                      target::Instance::first_field_offset());
       Label done, init_loop;
       __ Bind(&init_loop);
       __ CompareRegisters(kTempReg, kTopReg);
       __ b(&done, CS);
-      __ str(kNullReg, Address(kTempReg, kWordSize, Address::PostIndex));
+      __ str(kNullReg,
+             Address(kTempReg, target::kWordSize, Address::PostIndex));
       __ b(&init_loop);
 
       __ Bind(&done);
     }
     if (is_cls_parameterized) {
-      __ StoreToOffset(kTypeArgumentsReg, kInstanceReg,
-                       cls.type_arguments_field_offset());
+      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
+      __ StoreToOffset(kTypeArgumentsReg, kInstanceReg, offset);
     }
     __ add(kInstanceReg, kInstanceReg, Operand(kHeapObjectTag));
     __ ret();
@@ -1649,13 +1706,15 @@
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();  // Uses pool pointer to pass cls to runtime.
-  __ LoadObject(R0, cls);
+  __ LoadObject(R0, CastHandle<Object>(cls));
   __ PushPair(R0, kNullReg);  // Pushes cls, result slot.
   __ Push(is_cls_parameterized ? kTypeArgumentsReg : kNullReg);
   __ CallRuntime(kAllocateObjectRuntimeEntry, 2);  // Allocate object.
-  __ ldr(kInstanceReg,
-         Address(SP, 2 * kWordSize));  // Pop result (newly allocated object).
-  __ LeaveStubFrame();                 // Restores correct SP.
+  __ ldr(
+      kInstanceReg,
+      Address(SP,
+              2 * target::kWordSize));  // Pop result (newly allocated object).
+  __ LeaveStubFrame();                  // Restores correct SP.
   __ ret();
 }
 
@@ -1666,13 +1725,15 @@
 //  LR : return address.
 //  SP : address of last argument.
 //  R4: arguments descriptor array.
-void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::count_offset());
   __ add(TMP, FP, Operand(R2, LSL, 2));  // R2 is Smi.
-  __ LoadFromOffset(R6, TMP, kParamEndSlotFromFp * kWordSize);
+  __ LoadFromOffset(R6, TMP,
+                    target::frame_layout.param_end_from_fp * target::kWordSize);
 
   // Push space for the return value.
   // Push the receiver.
@@ -1682,7 +1743,8 @@
   __ Push(R4);
 
   // Adjust arguments count.
-  __ LoadFieldFromOffset(R3, R4, ArgumentsDescriptor::type_args_len_offset());
+  __ LoadFieldFromOffset(R3, R4,
+                         target::ArgumentsDescriptor::type_args_len_offset());
   __ AddImmediate(TMP, R2, 1);  // Include the type arguments.
   __ cmp(R3, Operand(0));
   __ csinc(R2, R2, TMP, EQ);  // R2 <- (R3 == 0) ? R2 : TMP + 1 (R2 : R2 + 2).
@@ -1700,7 +1762,8 @@
 //  R5: inline cache data object.
 // Cannot use function object from ICData as it may be the inlined
 // function and not the top-scope function.
-void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
+    Assembler* assembler) {
   Register ic_reg = R5;
   Register func_reg = R6;
   if (FLAG_trace_optimized_ic_calls) {
@@ -1715,25 +1778,27 @@
     __ Pop(R6);  // Restore.
     __ LeaveStubFrame();
   }
-  __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), kWord);
+  __ LoadFieldFromOffset(R7, func_reg, target::Function::usage_counter_offset(),
+                         kWord);
   __ add(R7, R7, Operand(1));
-  __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), kWord);
+  __ StoreFieldToOffset(R7, func_reg, target::Function::usage_counter_offset(),
+                        kWord);
 }
 
 // Loads function into 'temp_reg'.
-void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
-                                             Register temp_reg) {
+void StubCodeCompiler::GenerateUsageCounterIncrement(Assembler* assembler,
+                                                     Register temp_reg) {
   if (FLAG_optimization_counter_threshold >= 0) {
     Register ic_reg = R5;
     Register func_reg = temp_reg;
     ASSERT(temp_reg == R6);
     __ Comment("Increment function counter");
-    __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset());
-    __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(),
-                           kWord);
+    __ LoadFieldFromOffset(func_reg, ic_reg, target::ICData::owner_offset());
+    __ LoadFieldFromOffset(R7, func_reg,
+                           target::Function::usage_counter_offset(), kWord);
     __ AddImmediate(R7, 1);
-    __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(),
-                          kWord);
+    __ StoreFieldToOffset(R7, func_reg,
+                          target::Function::usage_counter_offset(), kWord);
   }
 }
 
@@ -1746,8 +1811,8 @@
                           intptr_t num_args,
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
-  __ ldr(R0, Address(SP, +0 * kWordSize));  // Right.
-  __ ldr(R1, Address(SP, +1 * kWordSize));  // Left.
+  __ ldr(R0, Address(SP, +0 * target::kWordSize));  // Right.
+  __ ldr(R1, Address(SP, +1 * target::kWordSize));  // Left.
   __ orr(TMP, R0, Operand(R1));
   __ BranchIfNotSmi(TMP, not_smi_or_overflow);
   switch (kind) {
@@ -1763,8 +1828,8 @@
     }
     case Token::kEQ: {
       __ CompareRegisters(R0, R1);
-      __ LoadObject(R0, Bool::True());
-      __ LoadObject(R1, Bool::False());
+      __ LoadObject(R0, CastHandle<Object>(TrueObject()));
+      __ LoadObject(R1, CastHandle<Object>(FalseObject()));
       __ csel(R0, R1, R0, NE);
       break;
     }
@@ -1773,18 +1838,18 @@
   }
 
   // R5: IC data object (preserved).
-  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
+  __ LoadFieldFromOffset(R6, R5, target::ICData::entries_offset());
   // R6: ic_data_array with check entries: classes and target functions.
-  __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R6, target::Array::data_offset() - kHeapObjectTag);
 // R6: points directly to the first ic data array element.
 #if defined(DEBUG)
   // Check that first entry is for Smi/Smi.
   Label error, ok;
-  const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid));
+  const intptr_t imm_smi_cid = target::ToRawSmi(kSmiCid);
   __ ldr(R1, Address(R6, 0));
   __ CompareImmediate(R1, imm_smi_cid);
   __ b(&error, NE);
-  __ ldr(R1, Address(R6, kWordSize));
+  __ ldr(R1, Address(R6, target::kWordSize));
   __ CompareImmediate(R1, imm_smi_cid);
   __ b(&ok, EQ);
   __ Bind(&error);
@@ -1792,10 +1857,11 @@
   __ Bind(&ok);
 #endif
   if (FLAG_optimization_counter_threshold >= 0) {
-    const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+    const intptr_t count_offset =
+        target::ICData::CountIndexFor(num_args) * target::kWordSize;
     // Update counter, ignore overflow.
     __ LoadFromOffset(R1, R6, count_offset);
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreToOffset(R1, R6, count_offset);
   }
 
@@ -1812,7 +1878,7 @@
 // - Check if 'num_args' (including receiver) match any IC data group.
 // - Match found -> jump to target.
 // - Match not found -> jump to IC miss.
-void StubCode::GenerateNArgsCheckInlineCacheStub(
+void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
     Assembler* assembler,
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
@@ -1826,10 +1892,11 @@
     Label ok;
     // Check that the IC data array has NumArgsTested() == num_args.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
+    __ LoadFromOffset(R6, R5,
+                      target::ICData::state_bits_offset() - kHeapObjectTag,
                       kUnsignedWord);
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andi(R6, R6, Immediate(target::ICData::NumArgsTestedMask()));
     __ CompareImmediate(R6, num_args);
     __ b(&ok, EQ);
     __ Stop("Incorrect stub for IC data");
@@ -1842,7 +1909,8 @@
   if (!optimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(R6);
-    __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte);
+    __ LoadFromOffset(R6, R6, target::Isolate::single_step_offset(),
+                      kUnsignedByte);
     __ CompareRegisters(R6, ZR);
     __ b(&stepping, NE);
     __ Bind(&done_stepping);
@@ -1857,18 +1925,18 @@
 
   __ Comment("Extract ICData initial values and receiver cid");
   // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
+  __ 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, ICData::ic_data_offset());
+  __ LoadFieldFromOffset(R6, R5, target::ICData::entries_offset());
   // R6: ic_data_array with check entries: classes and target functions.
-  __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag);
+  __ 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, ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R7, R4, target::ArgumentsDescriptor::count_offset());
   __ SmiUntag(R7);  // Untag so we can use the LSL 3 addressing mode.
   __ sub(R7, R7, Operand(1));
 
@@ -1895,7 +1963,7 @@
     __ CompareRegisters(R0, R2);  // Class id match?
     if (num_args == 2) {
       __ b(&update, NE);  // Continue.
-      __ LoadFromOffset(R2, R6, kWordSize);
+      __ LoadFromOffset(R2, R6, target::kWordSize);
       __ CompareRegisters(R1, R2);  // Class id match?
     }
     __ b(&found, EQ);  // Break.
@@ -1903,10 +1971,11 @@
     __ Bind(&update);
 
     const intptr_t entry_size =
-        ICData::TestEntryLengthFor(num_args, exactness_check) * kWordSize;
+        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
+        target::kWordSize;
     __ AddImmediate(R6, entry_size);  // Next entry.
 
-    __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));  // Done?
+    __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));  // Done?
     if (unroll == 0) {
       __ b(&loop, NE);
     } else {
@@ -1932,7 +2001,7 @@
   __ Push(ZR);
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ LoadFromOffset(TMP, R7, -i * kWordSize);
+    __ LoadFromOffset(TMP, R7, -i * target::kWordSize);
     __ Push(TMP);
   }
   // Pass IC data object.
@@ -1957,22 +2026,24 @@
   __ Bind(&found);
   __ Comment("Update caller's counter");
   // R6: pointer to an IC data check group.
-  const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(num_args) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(num_args) * target::kWordSize;
   __ LoadFromOffset(R0, R6, target_offset);
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Update counter, ignore overflow.
     __ LoadFromOffset(R1, R6, count_offset);
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreToOffset(R1, R6, count_offset);
   }
 
   __ Comment("Call target");
   __ Bind(&call_target_function);
   // R0: target function.
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-  __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
+  __ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
   __ br(R2);
 
 #if !defined(PRODUCT)
@@ -1999,43 +2070,45 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
                                     kInlineCacheMissHandlerTwoArgsRuntimeEntry,
                                     Token::kILLEGAL);
 }
 
-void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
-void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
-void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
@@ -2043,12 +2116,13 @@
                                     Token::kILLEGAL, true /* optimized */);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
-    Assembler* assembler) {
+void StubCodeCompiler::
+    GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
+        Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
@@ -2056,17 +2130,19 @@
                                     Token::kILLEGAL, true /* optimized */);
 }
 
-void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
 #if defined(DEBUG)
   {
     Label ok;
     // Check that the IC data array has NumArgsTested() == 0.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
+    __ LoadFromOffset(R6, R5,
+                      target::ICData::state_bits_offset() - kHeapObjectTag,
                       kUnsignedWord);
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andi(R6, R6, Immediate(target::ICData::NumArgsTestedMask()));
     __ CompareImmediate(R6, 0);
     __ b(&ok, EQ);
     __ Stop("Incorrect IC data for unoptimized static call");
@@ -2078,34 +2154,37 @@
 #if !defined(PRODUCT)
   Label stepping, done_stepping;
   __ LoadIsolate(R6);
-  __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte);
+  __ LoadFromOffset(R6, R6, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
   __ CompareImmediate(R6, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
 #endif
 
   // R5: IC data object (preserved).
-  __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset());
+  __ LoadFieldFromOffset(R6, R5, target::ICData::entries_offset());
   // R6: ic_data_array with entries: target functions and count.
-  __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag);
+  __ AddImmediate(R6, target::Array::data_offset() - kHeapObjectTag);
   // R6: points directly to the first ic data array element.
-  const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(0) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(0) * target::kWordSize;
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Increment count for this call, ignore overflow.
     __ LoadFromOffset(R1, R6, count_offset);
-    __ adds(R1, R1, Operand(Smi::RawValue(1)));
+    __ adds(R1, R1, Operand(target::ToRawSmi(1)));
     __ StoreToOffset(R1, R6, count_offset);
   }
 
   // Load arguments descriptor into R4.
-  __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset());
+  __ LoadFieldFromOffset(R4, R5, target::ICData::arguments_descriptor_offset());
 
   // Get function and call it, if possible.
   __ LoadFromOffset(R0, R6, target_offset);
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-  __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
+  __ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
   __ br(R2);
 
 #if !defined(PRODUCT)
@@ -2120,13 +2199,15 @@
 #endif
 }
 
-void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, R6);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
@@ -2135,7 +2216,7 @@
 // Stub for compiling a function and jumping to the compiled code.
 // R4: Arguments descriptor.
 // R0: Function.
-void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
   // Preserve arg desc.
   __ EnterStubFrame();
   __ Push(R4);  // Save arg. desc.
@@ -2147,15 +2228,15 @@
 
   // When using the interpreter, the function's code may now point to the
   // InterpretCall stub. Make sure R0, R4, and R5 are preserved.
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-  __ LoadFieldFromOffset(R2, R0, Function::entry_point_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
+  __ LoadFieldFromOffset(R2, R0, target::Function::entry_point_offset());
   __ br(R2);
 }
 
 // Stub for interpreting a function call.
 // R4: Arguments descriptor.
 // R0: Function.
-void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   __ Stop("Not using interpreter")
 #else
@@ -2166,7 +2247,7 @@
   {
     Label ok;
     // Check that we are always entering from Dart code.
-    __ LoadFromOffset(R8, THR, Thread::vm_tag_offset());
+    __ LoadFromOffset(R8, THR, target::Thread::vm_tag_offset());
     __ CompareImmediate(R8, VMTag::kDartCompiledTagId);
     __ b(&ok, EQ);
     __ Stop("Not coming from Dart code.");
@@ -2175,22 +2256,24 @@
 #endif
 
   // Adjust arguments count for type arguments vector.
-  __ LoadFieldFromOffset(R2, R4, ArgumentsDescriptor::count_offset());
+  __ LoadFieldFromOffset(R2, R4, target::ArgumentsDescriptor::count_offset());
   __ SmiUntag(R2);
-  __ LoadFieldFromOffset(R1, R4, ArgumentsDescriptor::type_args_len_offset());
+  __ LoadFieldFromOffset(R1, R4,
+                         target::ArgumentsDescriptor::type_args_len_offset());
   __ cmp(R1, Operand(0));
   __ csinc(R2, R2, R2, EQ);  // R2 <- (R1 == 0) ? R2 : R2 + 1.
 
   // Compute argv.
   __ add(R3, ZR, Operand(R2, LSL, 3));
   __ add(R3, FP, Operand(R3));
-  __ AddImmediate(R3, kParamEndSlotFromFp * kWordSize);
+  __ AddImmediate(R3,
+                  target::frame_layout.param_end_from_fp * target::kWordSize);
 
   // Indicate decreasing memory addresses of arguments with negative argc.
   __ neg(R2, R2);
 
   // Align frame before entering C++ world. No shadow stack space required.
-  __ ReserveAlignedFrameSpace(0 * kWordSize);
+  __ ReserveAlignedFrameSpace(0 * target::kWordSize);
 
   // Pass arguments in registers.
   // R0: Function.
@@ -2201,11 +2284,12 @@
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ StoreToOffset(FP, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(FP, THR, target::Thread::top_exit_frame_info_offset());
 
   // Mark that the thread is executing VM code.
-  __ LoadFromOffset(R5, THR, Thread::interpret_call_entry_point_offset());
-  __ StoreToOffset(R5, THR, Thread::vm_tag_offset());
+  __ LoadFromOffset(R5, THR,
+                    target::Thread::interpret_call_entry_point_offset());
+  __ StoreToOffset(R5, THR, target::Thread::vm_tag_offset());
 
   // We are entering runtime code, so the C stack pointer must be restored from
   // the stack limit to the top of the stack. We cache the stack limit address
@@ -2220,14 +2304,15 @@
   __ mov(CSP, R25);
 
   // Refresh write barrier mask.
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
 
   // Mark that the thread is executing Dart code.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
 
   // Reset exit frame information in Isolate structure.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
 
   __ LeaveStubFrame();
   __ ret();
@@ -2235,7 +2320,7 @@
 }
 
 // R5: Contains an ICData.
-void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R5);
   __ Push(ZR);  // Space for result.
@@ -2243,30 +2328,33 @@
   __ Pop(CODE_REG);
   __ Pop(R5);
   __ LeaveStubFrame();
-  __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
+  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
   __ br(R0);
 }
 
-void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(ZR);  // Space for result.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ Pop(CODE_REG);
   __ LeaveStubFrame();
-  __ LoadFieldFromOffset(R0, CODE_REG, Code::entry_point_offset());
+  __ LoadFieldFromOffset(R0, CODE_REG, target::Code::entry_point_offset());
   __ br(R0);
 }
 
 // Called only from unoptimized code. All relevant registers have been saved.
-void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDebugStepCheckStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ ret();
+#else
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(R1);
-  __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
+  __ LoadFromOffset(R1, R1, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
   __ CompareImmediate(R1, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
-
   __ ret();
 
   __ Bind(&stepping);
@@ -2274,6 +2362,7 @@
   __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
   __ LeaveStubFrame();
   __ b(&done_stepping);
+#endif  // defined(PRODUCT)
 }
 
 // Used to check class and type arguments. Arguments passed in registers:
@@ -2281,7 +2370,7 @@
 // R0: instance (must be preserved).
 // R1: instantiator type arguments (only if n == 4, can be raw_null).
 // R2: function type arguments (only if n == 4, can be raw_null).
-// R3: SubtypeTestCache.
+// R3: target::SubtypeTestCache.
 //
 // Preserves R0/R2/R8.
 //
@@ -2301,12 +2390,13 @@
 
   const Register kNullReg = R7;
 
-  __ LoadObject(kNullReg, Object::null_object());
+  __ LoadObject(kNullReg, NullObject());
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ ldr(kCacheReg, FieldAddress(kCacheReg, SubtypeTestCache::cache_offset()));
-  __ AddImmediate(kCacheReg, Array::data_offset() - kHeapObjectTag);
+  __ ldr(kCacheReg,
+         FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
+  __ AddImmediate(kCacheReg, target::Array::data_offset() - kHeapObjectTag);
 
   Label loop, not_closure;
   if (n >= 4) {
@@ -2320,19 +2410,20 @@
   // Closure handling.
   {
     __ ldr(kInstanceCidOrFunction,
-           FieldAddress(kInstanceReg, Closure::function_offset()));
+           FieldAddress(kInstanceReg, target::Closure::function_offset()));
     if (n >= 2) {
-      __ ldr(kInstanceInstantiatorTypeArgumentsReg,
-             FieldAddress(kInstanceReg,
-                          Closure::instantiator_type_arguments_offset()));
+      __ ldr(
+          kInstanceInstantiatorTypeArgumentsReg,
+          FieldAddress(kInstanceReg,
+                       target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
         __ ldr(kInstanceParentFunctionTypeArgumentsReg,
                FieldAddress(kInstanceReg,
-                            Closure::function_type_arguments_offset()));
+                            target::Closure::function_type_arguments_offset()));
         __ ldr(kInstanceDelayedFunctionTypeArgumentsReg,
                FieldAddress(kInstanceReg,
-                            Closure::delayed_type_arguments_offset()));
+                            target::Closure::delayed_type_arguments_offset()));
       }
     }
     __ b(&loop);
@@ -2350,8 +2441,9 @@
       __ LoadClassById(R5, kInstanceCidOrFunction);
       __ mov(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
       __ LoadFieldFromOffset(
-          R5, R5, Class::type_arguments_field_offset_in_words_offset(), kWord);
-      __ CompareImmediate(R5, Class::kNoTypeArguments);
+          R5, R5, target::Class::type_arguments_field_offset_in_words_offset(),
+          kWord);
+      __ CompareImmediate(R5, target::Class::kNoTypeArguments);
       __ b(&has_no_type_arguments, EQ);
       __ add(R5, kInstanceReg, Operand(R5, LSL, 3));
       __ ldr(kInstanceInstantiatorTypeArgumentsReg, FieldAddress(R5, 0));
@@ -2369,7 +2461,8 @@
   // Loop header
   __ Bind(&loop);
   __ ldr(R5, Address(kCacheReg,
-                     kWordSize * SubtypeTestCache::kInstanceClassIdOrFunction));
+                     target::kWordSize *
+                         target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmp(R5, Operand(kNullReg));
   __ b(&not_found, EQ);
   __ cmp(R5, Operand(kInstanceCidOrFunction));
@@ -2378,7 +2471,8 @@
   } else {
     __ b(&next_iteration, NE);
     __ ldr(R5, Address(kCacheReg,
-                       kWordSize * SubtypeTestCache::kInstanceTypeArguments));
+                       target::kWordSize *
+                           target::SubtypeTestCache::kInstanceTypeArguments));
     __ cmp(R5, Operand(kInstanceInstantiatorTypeArgumentsReg));
     if (n == 2) {
       __ b(&found, EQ);
@@ -2386,11 +2480,13 @@
       __ b(&next_iteration, NE);
       __ ldr(R5,
              Address(kCacheReg,
-                     kWordSize * SubtypeTestCache::kInstantiatorTypeArguments));
+                     target::kWordSize *
+                         target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ cmp(R5, Operand(kInstantiatorTypeArgumentsReg));
       __ b(&next_iteration, NE);
       __ ldr(R5, Address(kCacheReg,
-                         kWordSize * SubtypeTestCache::kFunctionTypeArguments));
+                         target::kWordSize *
+                             target::SubtypeTestCache::kFunctionTypeArguments));
       __ cmp(R5, Operand(kFunctionTypeArgumentsReg));
       if (n == 4) {
         __ b(&found, EQ);
@@ -2398,31 +2494,30 @@
         ASSERT(n == 6);
         __ b(&next_iteration, NE);
 
-        __ ldr(R5,
-               Address(
-                   kCacheReg,
-                   kWordSize *
-                       SubtypeTestCache::kInstanceParentFunctionTypeArguments));
+        __ ldr(R5, Address(kCacheReg,
+                           target::kWordSize *
+                               target::SubtypeTestCache::
+                                   kInstanceParentFunctionTypeArguments));
         __ cmp(R5, Operand(kInstanceParentFunctionTypeArgumentsReg));
         __ b(&next_iteration, NE);
 
-        __ ldr(
-            R5,
-            Address(
-                kCacheReg,
-                kWordSize *
-                    SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
+        __ ldr(R5, Address(kCacheReg,
+                           target::kWordSize *
+                               target::SubtypeTestCache::
+                                   kInstanceDelayedFunctionTypeArguments));
         __ cmp(R5, Operand(kInstanceDelayedFunctionTypeArgumentsReg));
         __ b(&found, EQ);
       }
     }
   }
   __ Bind(&next_iteration);
-  __ AddImmediate(kCacheReg, kWordSize * SubtypeTestCache::kTestEntryLength);
+  __ AddImmediate(kCacheReg, target::kWordSize *
+                                 target::SubtypeTestCache::kTestEntryLength);
   __ b(&loop);
 
   __ Bind(&found);
-  __ ldr(R1, Address(kCacheReg, kWordSize * SubtypeTestCache::kTestResult));
+  __ ldr(R1, Address(kCacheReg, target::kWordSize *
+                                    target::SubtypeTestCache::kTestResult));
   __ ret();
 
   __ Bind(&not_found);
@@ -2431,22 +2526,22 @@
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype1TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 1);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype2TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 2);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype4TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 4);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype6TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype6TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 6);
 }
 
@@ -2467,100 +2562,52 @@
 //
 // Note of warning: The caller will not populate CODE_REG and we have therefore
 // no access to the pool.
-void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
   Label done;
 
   const Register kInstanceReg = R0;
   const Register kDstTypeReg = R8;
 
   // Fast case for 'null'.
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
   // Fast case for 'int'.
   Label not_smi;
   __ BranchIfNotSmi(kInstanceReg, &not_smi);
-  __ CompareObject(kDstTypeReg, Object::ZoneHandle(Type::IntType()));
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(IntType()));
   __ BranchIf(EQUAL, &done);
   __ Bind(&not_smi);
 
   // Tail call the [SubtypeTestCache]-based implementation.
-  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ ldr(R9, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(THR, target::Thread::slow_type_test_stub_offset()));
+  __ ldr(R9, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ br(R9);
 
   __ Bind(&done);
   __ Ret();
 }
 
-void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
   __ Ret();
 }
 
-void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
   const Register kTypeRefReg = R8;
 
   // We dereference the TypeRef and tail-call to it's type testing stub.
-  __ ldr(kTypeRefReg, FieldAddress(kTypeRefReg, TypeRef::type_offset()));
-  __ ldr(R9, FieldAddress(kTypeRefReg,
-                          AbstractType::type_test_stub_entry_point_offset()));
+  __ ldr(kTypeRefReg,
+         FieldAddress(kTypeRefReg, target::TypeRef::type_offset()));
+  __ ldr(R9, FieldAddress(
+                 kTypeRefReg,
+                 target::AbstractType::type_test_stub_entry_point_offset()));
   __ br(R9);
 }
 
-void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
   __ Breakpoint();
 }
 
-void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const Type& type,
-    const Class& type_class) {
-  const Register kInstanceReg = R0;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
-
-  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ ldr(R9, FieldAddress(CODE_REG, Code::entry_point_offset()));
-  __ br(R9);
-}
-
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
-                                                      HierarchyInfo* hi,
-                                                      const Class& type_class,
-                                                      const TypeArguments& tp,
-                                                      const TypeArguments& ta) {
-  const Register kInstanceReg = R0;
-  const Register kInstanceTypeArguments = R7;
-  const Register kClassIdReg = R9;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    Label* check_failed) {
-  const Register kInstantiatorTypeArgumentsReg = R1;
-  const Register kFunctionTypeArgumentsReg = R2;
-  const Register kInstanceTypeArguments = R7;
-
-  const Register kClassIdReg = R9;
-  const Register kOwnTypeArgumentValue = TMP;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
 static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
                                             TypeCheckMode mode) {
   const Register kInstanceReg = R0;
@@ -2570,14 +2617,14 @@
   const Register kSubtypeTestCacheReg = R3;
   const Register kDstTypeReg = R8;
 
-  __ PushObject(Object::null_object());  // Make room for result.
+  __ PushObject(NullObject());  // Make room for result.
   __ Push(kInstanceReg);
   __ Push(kDstTypeReg);
   __ Push(kInstantiatorTypeArgumentsReg);
   __ Push(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
+  __ PushObject(NullObject());
   __ Push(kSubtypeTestCacheReg);
-  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ PushImmediate(target::ToRawSmi(mode));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);  // mode
   __ Pop(kSubtypeTestCacheReg);
@@ -2589,15 +2636,16 @@
   __ Drop(1);  // Discard return value.
 }
 
-void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
+    Assembler* assembler) {
   const Register kInstanceReg = R0;
   Label done;
 
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
   __ ldr(CODE_REG,
-         Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+         Address(THR, target::Thread::lazy_specialize_type_test_stub_offset()));
   __ EnterStubFrame();
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
   __ LeaveStubFrame();
@@ -2606,7 +2654,7 @@
   __ Ret();
 }
 
-void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = R0;
@@ -2619,14 +2667,14 @@
 #ifdef DEBUG
   // Guaranteed by caller.
   Label no_error;
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(NOT_EQUAL, &no_error);
   __ Breakpoint();
   __ Bind(&no_error);
 #endif
 
   // If the subtype-cache is null, it needs to be lazily-created by the runtime.
-  __ CompareObject(kSubtypeTestCacheReg, Object::null_object());
+  __ CompareObject(kSubtypeTestCacheReg, NullObject());
   __ BranchIf(EQUAL, &call_runtime);
 
   const Register kTmp = R9;
@@ -2638,13 +2686,15 @@
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is instantiated/uninstantiated.
-  __ ldr(kTmp, FieldAddress(kDstTypeReg, Type::type_state_offset()), kByte);
-  __ cmp(kTmp, Operand(RawType::kFinalizedInstantiated));
+  __ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::type_state_offset()),
+         kByte);
+  __ cmp(kTmp,
+         Operand(target::RawAbstractType::kTypeStateFinalizedInstantiated));
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is a function type.
-  __ ldr(kTmp, FieldAddress(kDstTypeReg, Type::signature_offset()));
-  __ CompareObject(kTmp, Object::null_object());
+  __ ldr(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
+  __ CompareObject(kTmp, NullObject());
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
@@ -2655,8 +2705,8 @@
   __ Bind(&is_simple_case);
   {
     __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
-    __ BranchLink(StubCode::Subtype2TestCache());
-    __ CompareObject(R1, Bool::True());
+    __ BranchLink(StubCodeSubtype2TestCache());
+    __ CompareObject(R1, CastHandle<Object>(TrueObject()));
     __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     __ Jump(&call_runtime);
@@ -2665,8 +2715,8 @@
   __ Bind(&is_complex_case);
   {
     __ PushPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
-    __ BranchLink(StubCode::Subtype6TestCache());
-    __ CompareObject(R1, Bool::True());
+    __ BranchLink(StubCodeSubtype6TestCache());
+    __ CompareObject(R1, CastHandle<Object>(TrueObject()));
     __ PopPair(kInstantiatorTypeArgumentsReg, kSubtypeTestCacheReg);
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     // Fall through to runtime_call
@@ -2679,11 +2729,11 @@
   // because we do constant evaluation with default stubs and only install
   // optimized versions before writing out the AOT snapshot.
   // So dynamic/Object/void will run with default stub in constant evaluation.
-  __ CompareObject(kDstTypeReg, Type::dynamic_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(DynamicType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(ObjectType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::void_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(VoidType()));
   __ BranchIf(EQUAL, &done);
 
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
@@ -2693,7 +2743,7 @@
   __ Ret();
 }
 
-void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateGetCStackPointerStub(Assembler* assembler) {
   __ mov(R0, CSP);
   __ ret();
 }
@@ -2705,23 +2755,24 @@
 // R2: frame_pointer.
 // R3: thread.
 // Does not return.
-void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
   ASSERT(kExceptionObjectReg == R0);
   ASSERT(kStackTraceObjectReg == R1);
   __ mov(LR, R0);  // Program counter.
   __ mov(SP, R1);  // Stack pointer.
   __ mov(FP, R2);  // Frame_pointer.
   __ mov(THR, R3);
-  __ ldr(BARRIER_MASK, Address(THR, Thread::write_barrier_mask_offset()));
+  __ ldr(BARRIER_MASK,
+         Address(THR, target::Thread::write_barrier_mask_offset()));
   // Set the tag.
   __ LoadImmediate(R2, VMTag::kDartCompiledTagId);
-  __ StoreToOffset(R2, THR, Thread::vm_tag_offset());
+  __ StoreToOffset(R2, THR, target::Thread::vm_tag_offset());
   // Clear top exit frame.
-  __ StoreToOffset(ZR, THR, Thread::top_exit_frame_info_offset());
+  __ StoreToOffset(ZR, THR, target::Thread::top_exit_frame_info_offset());
   // Restore the pool pointer.
   __ RestoreCodePointer();
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ ldr(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ ldr(PP, Address(THR, target::Thread::global_object_pool_offset()));
     __ sub(PP, PP, Operand(kHeapObjectTag));  // Pool in PP is untagged!
   } else {
     __ LoadPoolPointer();
@@ -2734,19 +2785,21 @@
 //
 // The arguments are stored in the Thread object.
 // Does not return.
-void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ LoadFromOffset(LR, THR, Thread::resume_pc_offset());
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
 
-  ASSERT(Thread::CanLoadFromThread(Object::null_object()));
-  __ LoadFromOffset(R2, THR, Thread::OffsetFromThread(Object::null_object()));
+  word offset_from_thread = 0;
+  bool ok = target::CanLoadFromThread(NullObject(), &offset_from_thread);
+  ASSERT(ok);
+  __ LoadFromOffset(R2, THR, offset_from_thread);
 
   // Exception object.
-  __ LoadFromOffset(R0, THR, Thread::active_exception_offset());
-  __ StoreToOffset(R2, THR, Thread::active_exception_offset());
+  __ LoadFromOffset(R0, THR, target::Thread::active_exception_offset());
+  __ StoreToOffset(R2, THR, target::Thread::active_exception_offset());
 
   // StackTrace object.
-  __ LoadFromOffset(R1, THR, Thread::active_stacktrace_offset());
-  __ StoreToOffset(R2, THR, Thread::active_stacktrace_offset());
+  __ LoadFromOffset(R1, THR, target::Thread::active_stacktrace_offset());
+  __ StoreToOffset(R2, THR, target::Thread::active_stacktrace_offset());
 
   __ ret();  // Jump to the exception handler code.
 }
@@ -2754,13 +2807,13 @@
 // Deoptimize a frame on the call stack before rewinding.
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
   // Push zap value instead of CODE_REG.
   __ LoadImmediate(TMP, kZapCodeReg);
   __ Push(TMP);
 
   // Load the deopt pc into LR.
-  __ LoadFromOffset(LR, THR, Thread::resume_pc_offset());
+  __ LoadFromOffset(LR, THR, target::Thread::resume_pc_offset());
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -2773,7 +2826,7 @@
 // Calls to the runtime to optimize the given function.
 // R6: function to be re-optimized.
 // R4: argument descriptor (preserved).
-void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R4);
   // Setup space on stack for the return value.
@@ -2783,8 +2836,8 @@
   __ Pop(R0);  // Discard argument.
   __ Pop(R0);  // Get Function object
   __ Pop(R4);  // Restore argument descriptor.
-  __ LoadFieldFromOffset(CODE_REG, R0, Function::code_offset());
-  __ LoadFieldFromOffset(R1, R0, Function::entry_point_offset());
+  __ LoadFieldFromOffset(CODE_REG, R0, target::Function::code_offset());
+  __ LoadFieldFromOffset(R1, R0, target::Function::entry_point_offset());
   __ LeaveStubFrame();
   __ br(R1);
   __ brk(0);
@@ -2810,8 +2863,8 @@
   __ b(&done, NE);
 
   // Double values bitwise compare.
-  __ LoadFieldFromOffset(left, left, Double::value_offset());
-  __ LoadFieldFromOffset(right, right, Double::value_offset());
+  __ LoadFieldFromOffset(left, left, target::Double::value_offset());
+  __ LoadFieldFromOffset(right, right, target::Double::value_offset());
   __ b(&reference_compare);
 
   __ Bind(&check_mint);
@@ -2819,8 +2872,8 @@
   __ b(&reference_compare, NE);
   __ CompareClassId(right, kMintCid);
   __ b(&done, NE);
-  __ LoadFieldFromOffset(left, left, Mint::value_offset());
-  __ LoadFieldFromOffset(right, right, Mint::value_offset());
+  __ LoadFieldFromOffset(left, left, target::Mint::value_offset());
+  __ LoadFieldFromOffset(right, right, target::Mint::value_offset());
 
   __ Bind(&reference_compare);
   __ CompareRegisters(left, right);
@@ -2832,13 +2885,14 @@
 // SP + 4: left operand.
 // SP + 0: right operand.
 // Return Zero condition flag set if equal.
-void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
 #if !defined(PRODUCT)
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(R1);
-  __ LoadFromOffset(R1, R1, Isolate::single_step_offset(), kUnsignedByte);
+  __ LoadFromOffset(R1, R1, target::Isolate::single_step_offset(),
+                    kUnsignedByte);
   __ CompareImmediate(R1, 0);
   __ b(&stepping, NE);
   __ Bind(&done_stepping);
@@ -2846,8 +2900,8 @@
 
   const Register left = R1;
   const Register right = R0;
-  __ LoadFromOffset(left, SP, 1 * kWordSize);
-  __ LoadFromOffset(right, SP, 0 * kWordSize);
+  __ LoadFromOffset(left, SP, 1 * target::kWordSize);
+  __ LoadFromOffset(right, SP, 0 * target::kWordSize);
   GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 
@@ -2866,12 +2920,12 @@
 // SP + 4: left operand.
 // SP + 0: right operand.
 // Return Zero condition flag set if equal.
-void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
   const Register left = R1;
   const Register right = R0;
-  __ LoadFromOffset(left, SP, 1 * kWordSize);
-  __ LoadFromOffset(right, SP, 0 * kWordSize);
+  __ LoadFromOffset(left, SP, 1 * target::kWordSize);
+  __ LoadFromOffset(right, SP, 0 * target::kWordSize);
   GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 }
@@ -2882,7 +2936,7 @@
 // Passed to target:
 //  CODE_REG: target Code
 //  R4: arguments descriptor
-void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   // Jump if receiver is a smi.
   Label smi_case;
   __ BranchIfSmi(R0, &smi_case);
@@ -2892,8 +2946,8 @@
 
   Label cid_loaded;
   __ Bind(&cid_loaded);
-  __ ldr(R2, FieldAddress(R5, MegamorphicCache::buckets_offset()));
-  __ ldr(R1, FieldAddress(R5, MegamorphicCache::mask_offset()));
+  __ ldr(R2, FieldAddress(R5, target::MegamorphicCache::buckets_offset()));
+  __ ldr(R1, FieldAddress(R5, target::MegamorphicCache::mask_offset()));
   // R2: cache buckets array.
   // R1: mask as a smi.
 
@@ -2902,7 +2956,7 @@
   // R0: class ID of the receiver (smi).
 
   // Compute the table index.
-  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
   // Use lsl and sub to multiply with 7 == 8 - 1.
   __ LslImmediate(R3, R0, 3);
   __ sub(R3, R3, Operand(R0));
@@ -2911,7 +2965,7 @@
   __ Bind(&loop);
   __ and_(R3, R3, Operand(R1));
 
-  const intptr_t base = Array::data_offset();
+  const intptr_t base = target::Array::data_offset();
   // R3 is smi tagged, but table entries are 16 bytes, so LSL 3.
   __ add(TMP, R2, Operand(R3, LSL, 3));
   __ ldr(R6, FieldAddress(TMP, base));
@@ -2925,17 +2979,19 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address = FieldAddress(TMP, base + kWordSize);
+  const auto target_address = FieldAddress(TMP, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ ldr(R1, target_address);
     __ ldr(ARGS_DESC_REG,
-           FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset()));
+           FieldAddress(
+               R5, target::MegamorphicCache::arguments_descriptor_offset()));
   } else {
     __ ldr(R0, target_address);
-    __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
+    __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
     __ ldr(ARGS_DESC_REG,
-           FieldAddress(R5, MegamorphicCache::arguments_descriptor_offset()));
-    __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
+           FieldAddress(
+               R5, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
   }
   __ br(R1);
 
@@ -2946,7 +3002,7 @@
   __ b(&load_target, EQ);  // branch if miss.
 
   // Try next extry in the table.
-  __ AddImmediate(R3, Smi::RawValue(1));
+  __ AddImmediate(R3, target::ToRawSmi(1));
   __ b(&loop);
 
   // Load cid for the Smi case.
@@ -2961,12 +3017,12 @@
 // Passed to target:
 //  CODE_REG: target Code object
 //  R4: arguments descriptor
-void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
   __ ldr(ARGS_DESC_REG,
-         FieldAddress(R5, ICData::arguments_descriptor_offset()));
-  __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+         FieldAddress(R5, target::ICData::arguments_descriptor_offset()));
+  __ ldr(R8, FieldAddress(R5, target::ICData::entries_offset()));
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
   // R1: receiver cid as Smi
@@ -2975,33 +3031,35 @@
   __ ldr(R2, Address(R8, 0));
   __ cmp(R1, Operand(R2));
   __ b(&found, EQ);
-  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
   __ b(&miss, EQ);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ AddImmediate(R8, entry_length);  // Next entry.
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(1) * target::kWordSize;
   __ ldr(R0, Address(R8, target_offset));
-  __ ldr(R1, FieldAddress(R0, Function::entry_point_offset()));
-  __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset()));
+  __ ldr(R1, FieldAddress(R0, target::Function::entry_point_offset()));
+  __ ldr(CODE_REG, FieldAddress(R0, target::Function::code_offset()));
   __ br(R1);
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
-  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ br(R1);
 }
 
-void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
-  __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset()));
-  __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset()));
-  __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag);
+  __ ldr(R8, FieldAddress(R5, target::ICData::entries_offset()));
+  __ ldr(R4, FieldAddress(R5, target::ICData::arguments_descriptor_offset()));
+  __ AddImmediate(R8, target::Array::data_offset() - kHeapObjectTag);
   // R8: first IC entry
   __ LoadTaggedClassIdMayBeSmi(R1, R0);
   // R1: receiver cid as Smi
@@ -3010,17 +3068,20 @@
   __ ldr(R2, Address(R8, 0));
   __ cmp(R1, Operand(R2));
   __ b(&found, EQ);
-  __ CompareImmediate(R2, Smi::RawValue(kIllegalCid));
+  __ CompareImmediate(R2, target::ToRawSmi(kIllegalCid));
   __ b(&miss, EQ);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ AddImmediate(R8, entry_length);  // Next entry.
   __ b(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
-  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  const intptr_t code_offset =
+      target::ICData::CodeIndexFor(1) * target::kWordSize;
+  const intptr_t entry_offset =
+      target::ICData::EntryPointIndexFor(1) * target::kWordSize;
   __ ldr(R1, Address(R8, entry_offset));
   if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ ldr(CODE_REG, Address(R8, code_offset));
@@ -3029,15 +3090,15 @@
 
   __ Bind(&miss);
   __ LoadIsolate(R2);
-  __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset()));
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ ldr(CODE_REG, Address(R2, target::Isolate::ic_miss_code_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ br(R1);
 }
 
 // Called from switchable IC calls.
 //  R0: receiver
 //  R5: SingleTargetCache
-void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
@@ -3051,9 +3112,10 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                        Code::EntryKind::kMonomorphic)));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kMonomorphic)));
   __ br(R1);
 }
 
@@ -3062,12 +3124,12 @@
 //  R5: SingleTargetCache
 // Passed to target:
 //  CODE_REG: target Code object
-void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
   Label miss;
   __ LoadClassIdMayBeSmi(R1, R0);
-  __ ldr(R2, FieldAddress(R5, SingleTargetCache::lower_limit_offset()),
+  __ ldr(R2, FieldAddress(R5, target::SingleTargetCache::lower_limit_offset()),
          kUnsignedHalfword);
-  __ ldr(R3, FieldAddress(R5, SingleTargetCache::upper_limit_offset()),
+  __ ldr(R3, FieldAddress(R5, target::SingleTargetCache::upper_limit_offset()),
          kUnsignedHalfword);
 
   __ cmp(R1, Operand(R2));
@@ -3075,8 +3137,9 @@
   __ cmp(R1, Operand(R3));
   __ b(&miss, GT);
 
-  __ ldr(R1, FieldAddress(R5, SingleTargetCache::entry_point_offset()));
-  __ ldr(CODE_REG, FieldAddress(R5, SingleTargetCache::target_offset()));
+  __ ldr(R1, FieldAddress(R5, target::SingleTargetCache::entry_point_offset()));
+  __ ldr(CODE_REG,
+         FieldAddress(R5, target::SingleTargetCache::target_offset()));
   __ br(R1);
 
   __ Bind(&miss);
@@ -3092,16 +3155,18 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                        Code::EntryKind::kMonomorphic)));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kMonomorphic)));
   __ br(R1);
 }
 
 // Called from the monomorphic checked entry.
 //  R0: receiver
-void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ ldr(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset()));
+void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::monomorphic_miss_stub_offset()));
   __ EnterStubFrame();
   __ Push(R0);  // Preserve receiver.
 
@@ -3114,20 +3179,24 @@
   __ Pop(R0);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ ldr(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                        Code::EntryKind::kMonomorphic)));
+  __ ldr(CODE_REG,
+         Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ ldr(R1, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                        CodeEntryKind::kMonomorphic)));
   __ br(R1);
 }
 
-void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
+    Assembler* assembler) {
   __ brk(0);
 }
 
-void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
   __ brk(0);
 }
 
+}  // namespace compiler
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/compiler/stub_code_compiler_dbc.cc b/runtime/vm/compiler/stub_code_compiler_dbc.cc
new file mode 100644
index 0000000..f303ad4
--- /dev/null
+++ b/runtime/vm/compiler/stub_code_compiler_dbc.cc
@@ -0,0 +1,143 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+#if defined(TARGET_ARCH_DBC)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
+#include "vm/compiler/jit/compiler.h"
+#include "vm/cpu.h"
+#include "vm/dart_entry.h"
+#include "vm/heap/heap.h"
+#include "vm/instructions.h"
+#include "vm/object_store.h"
+#include "vm/runtime_entry.h"
+#include "vm/stack_frame.h"
+#include "vm/stub_code.h"
+#include "vm/tags.h"
+
+#define __ assembler->
+
+namespace dart {
+
+DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
+DEFINE_FLAG(bool,
+            use_slow_path,
+            false,
+            "Set to true for debugging & verifying the slow paths.");
+
+namespace compiler {
+
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
+  __ Compile();
+}
+
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
+  __ NoSuchMethod();
+}
+
+// Not executed, but used as a stack marker when calling
+// DRT_OptimizeInvokedFunction.
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// Not executed, but used as a sentinel in Simulator::JumpToFrame.
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
+  __ DeoptRewind();
+}
+
+// TODO(vegorov) Don't generate this stub.
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(vegorov) Don't generate these stubs.
+void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
+                                                      const Class& cls) {
+  __ Trap();
+}
+
+// TODO(vegorov) Don't generate this stub.
+void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// These deoptimization stubs are only used to populate stack frames
+// with something meaningful to make sure GC can scan the stack during
+// the last phase of deoptimization which materializes objects.
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
+    Assembler* assembler) {
+  __ Trap();
+}
+
+// TODO(kustermann): Don't generate this stub.
+void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
+    Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
+  __ Trap();
+}
+
+void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
+    Assembler* assembler) {
+  __ Trap();
+}
+
+}  // namespace compiler
+
+}  // namespace dart
+
+#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/stub_code_ia32.cc b/runtime/vm/compiler/stub_code_compiler_ia32.cc
similarity index 67%
rename from runtime/vm/stub_code_ia32.cc
rename to runtime/vm/compiler/stub_code_compiler_ia32.cc
index fdefce3..0fe7e81 100644
--- a/runtime/vm/stub_code_ia32.cc
+++ b/runtime/vm/compiler/stub_code_compiler_ia32.cc
@@ -1,21 +1,22 @@
-// Copyright (c) 2013, 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.
 
 #include "vm/globals.h"
+
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/stub_code_compiler.h"
+
 #if defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/class_id.h"
+#include "vm/code_entry_kind.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
-#include "vm/heap/scavenger.h"
+#include "vm/compiler/backend/locations.h"
+#include "vm/constants_ia32.h"
 #include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/resolver.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/tags.h"
 
 #define __ assembler->
@@ -28,7 +29,7 @@
             false,
             "Set to true for debugging & verifying the slow paths.");
 
-#define INT32_SIZEOF(x) static_cast<int32_t>(sizeof(x))
+namespace compiler {
 
 // Input parameters:
 //   ESP : points to return address.
@@ -38,18 +39,19 @@
 //   ECX : address of the runtime function to call.
 //   EDX : number of arguments to the call.
 // Must preserve callee saved registers EDI and EBX.
-void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
-  __ movl(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
+  __ movl(CODE_REG,
+          Address(THR, target::Thread::call_to_runtime_stub_offset()));
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   {
@@ -66,7 +68,9 @@
   __ movl(Assembler::VMTagAddress(), ECX);
 
   // Reserve space for arguments and align frame before entering C++ world.
-  __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments)));
+  __ AddImmediate(
+      ESP,
+      Immediate(-static_cast<int32_t>(target::NativeArguments::StructSize())));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
@@ -77,16 +81,20 @@
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
   __ movl(Address(ESP, argc_tag_offset), EDX);  // Set argc in NativeArguments.
   // Compute argv.
-  __ leal(EAX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize));
-  __ movl(Address(ESP, argv_offset), EAX);    // Set argv in NativeArguments.
-  __ addl(EAX, Immediate(1 * kWordSize));     // Retval is next to 1st argument.
+  __ leal(EAX,
+          Address(EBP, EDX, TIMES_4,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
+  __ movl(Address(ESP, argv_offset), EAX);  // Set argv in NativeArguments.
+  __ addl(EAX,
+          Immediate(1 * target::kWordSize));  // Retval is next to 1st argument.
   __ movl(Address(ESP, retval_offset), EAX);  // Set retval in NativeArguments.
   __ call(ECX);
 
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveFrame();
 
@@ -99,21 +107,23 @@
   __ ret();
 }
 
-void StubCode::GenerateNullErrorSharedWithoutFPURegsStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
   __ Breakpoint();
 }
 
-void StubCode::GenerateNullErrorSharedWithFPURegsStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
   __ Breakpoint();
 }
 
-void StubCode::GenerateStackOverflowSharedWithoutFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
     Assembler* assembler) {
   // TODO(sjindel): implement.
   __ Breakpoint();
 }
 
-void StubCode::GenerateStackOverflowSharedWithFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
     Assembler* assembler) {
   // TODO(sjindel): implement.
   __ Breakpoint();
@@ -123,8 +133,8 @@
 //   ESP : points to return address.
 //   EAX : stop message (const char*).
 // Must preserve all registers, except EAX.
-void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
-  __ EnterCallRuntimeFrame(1 * kWordSize);
+void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
+  __ EnterCallRuntimeFrame(1 * target::kWordSize);
   __ movl(Address(ESP, 0), EAX);
   __ CallRuntime(kPrintStopMessageRuntimeEntry, 1);
   __ LeaveCallRuntimeFrame();
@@ -138,23 +148,23 @@
 //   ECX : address of the native function to call.
 //   EDX : argc_tag including number of arguments and function kind.
 static void GenerateCallNativeWithWrapperStub(Assembler* assembler,
-                                              ExternalLabel* wrapper) {
+                                              Address wrapper_address) {
   const intptr_t native_args_struct_offset =
-      NativeEntry::kNumCallWrapperArguments * kWordSize;
+      target::NativeEntry::kNumCallWrapperArguments * target::kWordSize;
   const intptr_t thread_offset =
-      NativeArguments::thread_offset() + native_args_struct_offset;
+      target::NativeArguments::thread_offset() + native_args_struct_offset;
   const intptr_t argc_tag_offset =
-      NativeArguments::argc_tag_offset() + native_args_struct_offset;
+      target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
   const intptr_t argv_offset =
-      NativeArguments::argv_offset() + native_args_struct_offset;
+      target::NativeArguments::argv_offset() + native_args_struct_offset;
   const intptr_t retval_offset =
-      NativeArguments::retval_offset() + native_args_struct_offset;
+      target::NativeArguments::retval_offset() + native_args_struct_offset;
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to dart VM code.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   {
@@ -173,8 +183,10 @@
   // Reserve space for the native arguments structure, the outgoing parameters
   // (pointer to the native arguments structure, the C function entry point)
   // and align frame before entering the C++ world.
-  __ AddImmediate(ESP,
-                  Immediate(-INT32_SIZEOF(NativeArguments) - (2 * kWordSize)));
+  __ AddImmediate(
+      ESP,
+      Immediate(-static_cast<int32_t>(target::NativeArguments::StructSize()) -
+                (2 * target::kWordSize)));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
@@ -183,31 +195,39 @@
   __ movl(Address(ESP, thread_offset), THR);    // Set thread in NativeArgs.
   __ movl(Address(ESP, argc_tag_offset), EDX);  // Set argc in NativeArguments.
   __ movl(Address(ESP, argv_offset), EAX);      // Set argv in NativeArguments.
-  __ leal(EAX, Address(EBP, 2 * kWordSize));    // Compute return value addr.
+  __ leal(EAX,
+          Address(EBP, 2 * target::kWordSize));  // Compute return value addr.
   __ movl(Address(ESP, retval_offset), EAX);  // Set retval in NativeArguments.
-  __ leal(EAX, Address(ESP, 2 * kWordSize));  // Pointer to the NativeArguments.
+  __ leal(
+      EAX,
+      Address(ESP, 2 * target::kWordSize));  // Pointer to the NativeArguments.
   __ movl(Address(ESP, 0), EAX);  // Pass the pointer to the NativeArguments.
 
-  __ movl(Address(ESP, kWordSize), ECX);  // Function to call.
-  __ call(wrapper);
+  __ movl(Address(ESP, target::kWordSize), ECX);  // Function to call.
+  __ call(wrapper_address);
 
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveFrame();
   __ ret();
 }
 
-void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
-  ExternalLabel wrapper(NativeEntry::NoScopeNativeCallWrapperEntry());
-  GenerateCallNativeWithWrapperStub(assembler, &wrapper);
+void StubCodeCompiler::GenerateCallNoScopeNativeStub(Assembler* assembler) {
+  GenerateCallNativeWithWrapperStub(
+      assembler,
+      Address(THR,
+              target::Thread::no_scope_native_wrapper_entry_point_offset()));
 }
 
-void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
-  ExternalLabel wrapper(NativeEntry::AutoScopeNativeCallWrapperEntry());
-  GenerateCallNativeWithWrapperStub(assembler, &wrapper);
+void StubCodeCompiler::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
+  GenerateCallNativeWithWrapperStub(
+      assembler,
+      Address(THR,
+              target::Thread::auto_scope_native_wrapper_entry_point_offset()));
 }
 
 // Input parameters:
@@ -216,22 +236,22 @@
 //   EAX : address of first argument in argument array.
 //   ECX : address of the native function to call.
 //   EDX : argc_tag including number of arguments and function kind.
-void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
-  const intptr_t native_args_struct_offset = kWordSize;
+void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
+  const intptr_t native_args_struct_offset = target::kWordSize;
   const intptr_t thread_offset =
-      NativeArguments::thread_offset() + native_args_struct_offset;
+      target::NativeArguments::thread_offset() + native_args_struct_offset;
   const intptr_t argc_tag_offset =
-      NativeArguments::argc_tag_offset() + native_args_struct_offset;
+      target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
   const intptr_t argv_offset =
-      NativeArguments::argv_offset() + native_args_struct_offset;
+      target::NativeArguments::argv_offset() + native_args_struct_offset;
   const intptr_t retval_offset =
-      NativeArguments::retval_offset() + native_args_struct_offset;
+      target::NativeArguments::retval_offset() + native_args_struct_offset;
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to dart VM code.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), EBP);
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()), EBP);
 
 #if defined(DEBUG)
   {
@@ -250,7 +270,10 @@
   // Reserve space for the native arguments structure, the outgoing parameter
   // (pointer to the native arguments structure) and align frame before
   // entering the C++ world.
-  __ AddImmediate(ESP, Immediate(-INT32_SIZEOF(NativeArguments) - kWordSize));
+  __ AddImmediate(
+      ESP,
+      Immediate(-static_cast<int32_t>(target::NativeArguments::StructSize()) -
+                target::kWordSize));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andl(ESP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
@@ -259,16 +282,19 @@
   __ movl(Address(ESP, thread_offset), THR);    // Set thread in NativeArgs.
   __ movl(Address(ESP, argc_tag_offset), EDX);  // Set argc in NativeArguments.
   __ movl(Address(ESP, argv_offset), EAX);      // Set argv in NativeArguments.
-  __ leal(EAX, Address(EBP, 2 * kWordSize));    // Compute return value addr.
+  __ leal(EAX,
+          Address(EBP, 2 * target::kWordSize));  // Compute return value addr.
   __ movl(Address(ESP, retval_offset), EAX);  // Set retval in NativeArguments.
-  __ leal(EAX, Address(ESP, kWordSize));      // Pointer to the NativeArguments.
+  __ leal(EAX,
+          Address(ESP, target::kWordSize));  // Pointer to the NativeArguments.
   __ movl(Address(ESP, 0), EAX);  // Pass the pointer to the NativeArguments.
   __ call(ECX);
 
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveFrame();
   __ ret();
@@ -276,7 +302,7 @@
 
 // Input parameters:
 //   EDX: arguments descriptor array.
-void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallStaticFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushl(EDX);           // Preserve arguments descriptor array.
   __ pushl(Immediate(0));  // Setup space on stack for return value.
@@ -286,14 +312,14 @@
   // Remove the stub frame as we are about to jump to the dart function.
   __ LeaveFrame();
 
-  __ movl(ECX, FieldAddress(EAX, Code::entry_point_offset()));
+  __ movl(ECX, FieldAddress(EAX, target::Code::entry_point_offset()));
   __ jmp(ECX);
 }
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
 // EDX: arguments descriptor array.
-void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
   __ EnterStubFrame();
@@ -302,7 +328,7 @@
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   __ popl(EAX);  // Get Code object.
   __ popl(EDX);  // Restore arguments descriptor array.
-  __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
+  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
   __ LeaveFrame();
   __ jmp(EAX);
   __ int3();
@@ -310,12 +336,13 @@
 
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
-void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixAllocationStubTargetStub(
+    Assembler* assembler) {
   __ EnterStubFrame();
   __ pushl(Immediate(0));  // Setup space on stack for return value.
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   __ popl(EAX);  // Get Code object.
-  __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
+  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
   __ LeaveFrame();
   __ jmp(EAX);
   __ int3();
@@ -323,20 +350,21 @@
 
 // Input parameters:
 //   EDX: smi-tagged argument count, may be zero.
-//   EBP[kParamEndSlotFromFp + 1]: last argument.
+//   EBP[target::frame_layout.param_end_from_fp + 1]: last argument.
 // Uses EAX, EBX, ECX, EDX, EDI.
 static void PushArrayOfArguments(Assembler* assembler) {
   // Allocate array to store arguments of caller.
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
   __ movl(ECX, raw_null);  // Null element type for raw Array.
-  __ Call(StubCode::AllocateArray());
+  __ Call(StubCodeAllocateArray());
   __ SmiUntag(EDX);
   // EAX: newly allocated array.
   // EDX: length of the array (was preserved by the stub).
   __ pushl(EAX);  // Array is in EAX and on top of stack.
-  __ leal(EBX, Address(EBP, EDX, TIMES_4, kParamEndSlotFromFp * kWordSize));
-  __ leal(ECX, FieldAddress(EAX, Array::data_offset()));
+  __ leal(EBX,
+          Address(EBP, EDX, TIMES_4,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
+  __ leal(ECX, FieldAddress(EAX, target::Array::data_offset()));
   // EBX: address of first argument on stack.
   // ECX: address of first argument in array.
   Label loop, loop_condition;
@@ -345,8 +373,8 @@
   __ movl(EDI, Address(EBX, 0));
   // Generational barrier is needed, array is not necessarily in new space.
   __ StoreIntoObject(EAX, Address(ECX, 0), EDI);
-  __ AddImmediate(ECX, Immediate(kWordSize));
-  __ AddImmediate(EBX, Immediate(-kWordSize));
+  __ AddImmediate(ECX, Immediate(target::kWordSize));
+  __ AddImmediate(EBX, Immediate(-target::kWordSize));
   __ Bind(&loop_condition);
   __ decl(EDX);
   __ j(POSITIVE, &loop, Assembler::kNearJump);
@@ -397,7 +425,7 @@
     if (i == CODE_REG) {
       // Save the original value of CODE_REG pushed before invoking this stub
       // instead of the value used to call this stub.
-      __ pushl(Address(EBP, 2 * kWordSize));
+      __ pushl(Address(EBP, 2 * target::kWordSize));
     } else {
       __ pushl(static_cast<Register>(i));
     }
@@ -411,21 +439,24 @@
   }
 
   __ movl(ECX, ESP);  // Preserve saved registers block.
-  __ ReserveAlignedFrameSpace(2 * kWordSize);
-  __ movl(Address(ESP, 0 * kWordSize), ECX);  // Start of register block.
+  __ ReserveAlignedFrameSpace(2 * target::kWordSize);
+  __ movl(Address(ESP, 0 * target::kWordSize),
+          ECX);  // Start of register block.
   bool is_lazy =
       (kind == kLazyDeoptFromReturn) || (kind == kLazyDeoptFromThrow);
-  __ movl(Address(ESP, 1 * kWordSize), Immediate(is_lazy ? 1 : 0));
+  __ movl(Address(ESP, 1 * target::kWordSize), Immediate(is_lazy ? 1 : 0));
   __ CallRuntime(kDeoptimizeCopyFrameRuntimeEntry, 2);
   // Result (EAX) is stack-size (FP - SP) in bytes.
 
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into EBX temporarily.
-    __ movl(EBX, Address(EBP, saved_result_slot_from_fp * kWordSize));
+    __ movl(EBX, Address(EBP, saved_result_slot_from_fp * target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into EBX temporarily.
-    __ movl(EBX, Address(EBP, saved_exception_slot_from_fp * kWordSize));
-    __ movl(ECX, Address(EBP, saved_stacktrace_slot_from_fp * kWordSize));
+    __ movl(EBX,
+            Address(EBP, saved_exception_slot_from_fp * target::kWordSize));
+    __ movl(ECX,
+            Address(EBP, saved_stacktrace_slot_from_fp * target::kWordSize));
   }
 
   __ LeaveFrame();
@@ -442,23 +473,23 @@
     __ pushl(EBX);  // Preserve exception as first local.
     __ pushl(ECX);  // Preserve stacktrace as first local.
   }
-  __ ReserveAlignedFrameSpace(1 * kWordSize);
+  __ ReserveAlignedFrameSpace(1 * target::kWordSize);
   __ movl(Address(ESP, 0), EBP);  // Pass last FP as parameter on stack.
   __ CallRuntime(kDeoptimizeFillFrameRuntimeEntry, 1);
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into EBX.
     __ movl(EBX,
             Address(EBP, compiler::target::frame_layout.first_local_from_fp *
-                             kWordSize));
+                             target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into EBX.
     __ movl(EBX,
             Address(EBP, compiler::target::frame_layout.first_local_from_fp *
-                             kWordSize));
+                             target::kWordSize));
     __ movl(
         ECX,
         Address(EBP, (compiler::target::frame_layout.first_local_from_fp - 1) *
-                         kWordSize));
+                         target::kWordSize));
   }
   // Code above cannot cause GC.
   __ LeaveFrame();
@@ -473,7 +504,7 @@
     __ pushl(EBX);  // Preserve exception, it will be GC-d here.
     __ pushl(ECX);  // Preserve stacktrace, it will be GC-d here.
   }
-  __ pushl(Immediate(Smi::RawValue(0)));  // Space for the result.
+  __ pushl(Immediate(target::ToRawSmi(0)));  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
@@ -494,7 +525,8 @@
 }
 
 // EAX: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
   // Return address for "call" to deopt stub.
   __ pushl(Immediate(kZapReturnAddress));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
@@ -503,14 +535,15 @@
 
 // EAX: exception, must be preserved
 // EDX: stacktrace, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
   // Return address for "call" to deopt stub.
   __ pushl(Immediate(kZapReturnAddress));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
   __ ret();
 }
 
-void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
   __ ret();
 }
@@ -520,27 +553,28 @@
   __ Comment("NoSuchMethodDispatch");
   // When lazily generated invocation dispatchers are disabled, the
   // miss-handler may return null.
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
   __ cmpl(EAX, raw_null);
   __ j(NOT_EQUAL, call_target_function);
   __ EnterStubFrame();
   // Load the receiver.
-  __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ movl(EAX, Address(EBP, EDI, TIMES_HALF_WORD_SIZE,
-                       kParamEndSlotFromFp * kWordSize));
+  __ movl(EDI, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
+  __ movl(EAX,
+          Address(EBP, EDI, TIMES_HALF_WORD_SIZE,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
   __ pushl(Immediate(0));  // Setup space on stack for result.
   __ pushl(EAX);           // Receiver.
   __ pushl(ECX);           // ICData/MegamorphicCache.
   __ pushl(EDX);           // Arguments descriptor array.
 
   // Adjust arguments count.
-  __ cmpl(FieldAddress(EDX, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ cmpl(
+      FieldAddress(EDX, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   __ movl(EDX, EDI);
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addl(EDX, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addl(EDX, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
 
   // EDX: Smi-tagged arguments array length.
@@ -553,14 +587,14 @@
   __ ret();
 }
 
-void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Load the receiver into EAX.  The argument count in the arguments
   // descriptor in EDX is a smi.
-  __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  __ movl(EAX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
   // Two words (saved fp, stub's pc marker) in the stack above the return
   // address.
-  __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * kWordSize));
+  __ movl(EAX, Address(ESP, EAX, TIMES_2, 2 * target::kWordSize));
   // Preserve IC data and arguments descriptor.
   __ pushl(ECX);
   __ pushl(EDX);
@@ -585,7 +619,7 @@
     __ Bind(&call_target_function);
   }
 
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EBX);
 }
 
@@ -595,11 +629,12 @@
 //   ECX : array element type (either NULL or an instantiated type).
 // Uses EAX, EBX, ECX, EDI  as temporary registers.
 // The newly allocated object is returned in EAX.
-void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
-  // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+  // RoundedAllocationSize(
+  //     (array_length * kwordSize) + target::Array::header_size()).
   // Assert that length is a Smi.
   __ testl(EDX, Immediate(kSmiTagMask));
 
@@ -612,8 +647,8 @@
   __ j(LESS, &slow_case);
 
   // Check for maximum allowed length.
-  const Immediate& max_len = Immediate(
-      reinterpret_cast<int32_t>(Smi::New(Array::kMaxNewSpaceElements)));
+  const Immediate& max_len =
+      Immediate(target::ToRawSmi(target::Array::kMaxNewSpaceElements));
   __ cmpl(EDX, max_len);
   __ j(GREATER, &slow_case);
 
@@ -621,18 +656,19 @@
       __ MaybeTraceAllocation(kArrayCid, EAX, &slow_case, Assembler::kFarJump));
 
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawArray) + kObjectAlignment - 1;
+      target::Array::header_size() + target::ObjectAlignment::kObjectAlignment -
+      1;
   // EDX is Smi.
   __ leal(EBX, Address(EDX, TIMES_2, fixed_size_plus_alignment_padding));
   ASSERT(kSmiTagShift == 1);
-  __ andl(EBX, Immediate(-kObjectAlignment));
+  __ andl(EBX, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
   // ECX: array element type.
   // EDX: array length as Smi.
   // EBX: allocation size.
 
   const intptr_t cid = kArrayCid;
-  __ movl(EAX, Address(THR, Thread::top_offset()));
+  __ movl(EAX, Address(THR, target::Thread::top_offset()));
   __ addl(EBX, EAX);
   __ j(CARRY, &slow_case);
 
@@ -641,12 +677,12 @@
   // EBX: potential next object start.
   // ECX: array element type.
   // EDX: array length as Smi).
-  __ cmpl(EBX, Address(THR, Thread::end_offset()));
+  __ cmpl(EBX, Address(THR, target::Thread::end_offset()));
   __ j(ABOVE_EQUAL, &slow_case);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movl(Address(THR, Thread::top_offset()), EBX);
+  __ movl(Address(THR, target::Thread::top_offset()), EBX);
   __ subl(EBX, EAX);
   __ addl(EAX, Immediate(kHeapObjectTag));
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, EBX, EDI));
@@ -659,9 +695,10 @@
   {
     Label size_tag_overflow, done;
     __ movl(EDI, EBX);
-    __ cmpl(EDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
+    __ cmpl(EDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shll(EDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+    __ shll(EDI, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
     __ Bind(&size_tag_overflow);
@@ -669,11 +706,9 @@
     __ Bind(&done);
 
     // Get the class index and insert it into the tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    uint32_t tags = target::MakeTagWordForNewSpaceObject(cid, 0);
     __ orl(EDI, Immediate(tags));
-    __ movl(FieldAddress(EAX, Array::tags_offset()), EDI);  // Tags.
+    __ movl(FieldAddress(EAX, target::Object::tags_offset()), EDI);  // Tags.
   }
   // EAX: new object start as a tagged pointer.
   // EBX: allocation size.
@@ -682,11 +717,11 @@
   // Store the type argument field.
   // No generational barrier needed, since we store into a new object.
   __ StoreIntoObjectNoBarrier(
-      EAX, FieldAddress(EAX, Array::type_arguments_offset()), ECX);
+      EAX, FieldAddress(EAX, target::Array::type_arguments_offset()), ECX);
 
   // Set the length field.
-  __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, Array::length_offset()),
-                              EDX);
+  __ StoreIntoObjectNoBarrier(
+      EAX, FieldAddress(EAX, target::Array::length_offset()), EDX);
 
   // Initialize all array elements to raw_null.
   // EAX: new object start as a tagged pointer.
@@ -696,15 +731,15 @@
   // ECX: array element type.
   // EDX: array length as Smi.
   __ leal(EBX, FieldAddress(EAX, EBX, TIMES_1, 0));
-  __ leal(EDI, FieldAddress(EAX, sizeof(RawArray)));
+  __ leal(EDI, FieldAddress(EAX, target::Array::header_size()));
   Label done;
   Label init_loop;
   __ Bind(&init_loop);
   __ cmpl(EDI, EBX);
   __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
   // No generational barrier needed, since we are storing null.
-  __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), Object::null_object());
-  __ addl(EDI, Immediate(kWordSize));
+  __ StoreIntoObjectNoBarrier(EAX, Address(EDI, 0), NullObject());
+  __ addl(EDI, Immediate(target::kWordSize));
   __ jmp(&init_loop, Assembler::kNearJump);
   __ Bind(&done);
   __ ret();  // returns the newly allocated object in EAX.
@@ -734,18 +769,18 @@
 //   ESP + 12 : arguments array.
 //   ESP + 16 : current thread.
 // Uses EAX, EDX, ECX, EDI as temporary registers.
-void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
-  const intptr_t kTargetCodeOffset = 3 * kWordSize;
-  const intptr_t kArgumentsDescOffset = 4 * kWordSize;
-  const intptr_t kArgumentsOffset = 5 * kWordSize;
-  const intptr_t kThreadOffset = 6 * kWordSize;
+void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
+  const intptr_t kTargetCodeOffset = 3 * target::kWordSize;
+  const intptr_t kArgumentsDescOffset = 4 * target::kWordSize;
+  const intptr_t kArgumentsOffset = 5 * target::kWordSize;
+  const intptr_t kThreadOffset = 6 * target::kWordSize;
 
   __ pushl(Address(ESP, 0));  // Marker for the profiler.
   __ EnterFrame(0);
 
   // Push code object to PC marker slot.
   __ movl(EAX, Address(EBP, kThreadOffset));
-  __ pushl(Address(EAX, Thread::invoke_dart_code_stub_offset()));
+  __ pushl(Address(EAX, target::Thread::invoke_dart_code_stub_offset()));
 
   // Save C++ ABI callee-saved registers.
   __ pushl(EBX);
@@ -761,15 +796,16 @@
 
   // Save top resource and top exit frame info. Use EDX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ movl(EDX, Address(THR, Thread::top_resource_offset()));
+  __ movl(EDX, Address(THR, target::Thread::top_resource_offset()));
   __ pushl(EDX);
-  __ movl(Address(THR, Thread::top_resource_offset()), Immediate(0));
-  // The constant kExitLinkSlotFromEntryFp must be kept in sync with the
-  // code below.
-  ASSERT(kExitLinkSlotFromEntryFp == -7);
-  __ movl(EDX, Address(THR, Thread::top_exit_frame_info_offset()));
+  __ movl(Address(THR, target::Thread::top_resource_offset()), Immediate(0));
+  // The constant target::frame_layout.exit_link_slot_from_entry_fp must be
+  // kept in sync with the code below.
+  ASSERT(target::frame_layout.exit_link_slot_from_entry_fp == -7);
+  __ movl(EDX, Address(THR, target::Thread::top_exit_frame_info_offset()));
   __ pushl(EDX);
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
@@ -780,12 +816,13 @@
   __ movl(EDX, Address(EDX, VMHandles::kOffsetOfRawPtrInHandle));
 
   // Load number of arguments into EBX and adjust count for type arguments.
-  __ movl(EBX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ cmpl(FieldAddress(EDX, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ movl(EBX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
+  __ cmpl(
+      FieldAddress(EDX, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addl(EBX, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addl(EBX, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
   // Save number of arguments as Smi on stack, replacing ArgumentsDesc.
   __ movl(Address(EBP, kArgumentsDescOffset), EBX);
@@ -801,7 +838,7 @@
   // Compute address of 'arguments array' data area into EDI.
   __ movl(EDI, Address(EBP, kArgumentsOffset));
   __ movl(EDI, Address(EDI, VMHandles::kOffsetOfRawPtrInHandle));
-  __ leal(EDI, FieldAddress(EDI, Array::data_offset()));
+  __ leal(EDI, FieldAddress(EDI, target::Array::data_offset()));
 
   __ Bind(&push_arguments);
   __ movl(ECX, Address(EDI, EAX, TIMES_4, 0));
@@ -814,7 +851,7 @@
   // Call the dart code entrypoint.
   __ movl(EAX, Address(EBP, kTargetCodeOffset));
   __ movl(EAX, Address(EAX, VMHandles::kOffsetOfRawPtrInHandle));
-  __ call(FieldAddress(EAX, Code::entry_point_offset()));
+  __ call(FieldAddress(EAX, target::Code::entry_point_offset()));
 
   // Read the saved number of passed arguments as Smi.
   __ movl(EDX, Address(EBP, kArgumentsDescOffset));
@@ -823,8 +860,8 @@
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure.
-  __ popl(Address(THR, Thread::top_exit_frame_info_offset()));
-  __ popl(Address(THR, Thread::top_resource_offset()));
+  __ popl(Address(THR, target::Thread::top_exit_frame_info_offset()));
+  __ popl(Address(THR, target::Thread::top_resource_offset()));
 
   // Restore the current VMTag from the stack.
   __ popl(Assembler::VMTagAddress());
@@ -841,7 +878,8 @@
   __ ret();
 }
 
-void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
+    Assembler* assembler) {
   __ Unimplemented("Interpreter not yet supported");
 }
 
@@ -851,15 +889,16 @@
 // Output:
 // EAX: new allocated RawContext object.
 // EBX and EDX are destroyed.
-void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
     // EDX: number of context variables.
     intptr_t fixed_size_plus_alignment_padding =
-        (sizeof(RawContext) + kObjectAlignment - 1);
+        (target::Context::header_size() +
+         target::ObjectAlignment::kObjectAlignment - 1);
     __ leal(EBX, Address(EDX, TIMES_4, fixed_size_plus_alignment_padding));
-    __ andl(EBX, Immediate(-kObjectAlignment));
+    __ andl(EBX, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
     NOT_IN_PRODUCT(__ MaybeTraceAllocation(kContextCid, EAX, &slow_case,
                                            Assembler::kFarJump));
@@ -867,13 +906,13 @@
     // Now allocate the object.
     // EDX: number of context variables.
     const intptr_t cid = kContextCid;
-    __ movl(EAX, Address(THR, Thread::top_offset()));
+    __ movl(EAX, Address(THR, target::Thread::top_offset()));
     __ addl(EBX, EAX);
     // Check if the allocation fits into the remaining space.
     // EAX: potential new object.
     // EBX: potential next object start.
     // EDX: number of context variables.
-    __ cmpl(EBX, Address(THR, Thread::end_offset()));
+    __ cmpl(EBX, Address(THR, target::Thread::end_offset()));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
@@ -890,7 +929,7 @@
     // EAX: new object.
     // EBX: next object start.
     // EDX: number of context variables.
-    __ movl(Address(THR, Thread::top_offset()), EBX);
+    __ movl(Address(THR, target::Thread::top_offset()), EBX);
     // EBX: Size of allocation in bytes.
     __ subl(EBX, EAX);
     __ addl(EAX, Immediate(kHeapObjectTag));
@@ -903,10 +942,11 @@
     {
       Label size_tag_overflow, done;
       __ leal(EBX, Address(EDX, TIMES_4, fixed_size_plus_alignment_padding));
-      __ andl(EBX, Immediate(-kObjectAlignment));
-      __ cmpl(EBX, Immediate(RawObject::SizeTag::kMaxSizeTag));
+      __ andl(EBX, Immediate(-target::ObjectAlignment::kObjectAlignment));
+      __ cmpl(EBX, Immediate(target::RawObject::kSizeTagMaxSizeTag));
       __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-      __ shll(EBX, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+      __ shll(EBX, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                             target::ObjectAlignment::kObjectAlignmentLog2));
       __ jmp(&done);
 
       __ Bind(&size_tag_overflow);
@@ -917,39 +957,36 @@
       // EAX: new object.
       // EDX: number of context variables.
       // EBX: size and bit tags.
-      uint32_t tags = 0;
-      tags = RawObject::ClassIdTag::update(cid, tags);
-      tags = RawObject::NewBit::update(true, tags);
+      uint32_t tags = target::MakeTagWordForNewSpaceObject(cid, 0);
       __ orl(EBX, Immediate(tags));
-      __ movl(FieldAddress(EAX, Context::tags_offset()), EBX);  // Tags.
+      __ movl(FieldAddress(EAX, target::Object::tags_offset()), EBX);  // Tags.
     }
 
     // Setup up number of context variables field.
     // EAX: new object.
     // EDX: number of context variables as integer value (not object).
-    __ movl(FieldAddress(EAX, Context::num_variables_offset()), EDX);
+    __ movl(FieldAddress(EAX, target::Context::num_variables_offset()), EDX);
 
     // Setup the parent field.
     // EAX: new object.
     // EDX: number of context variables.
     // No generational barrier needed, since we are storing null.
-    __ StoreIntoObjectNoBarrier(EAX,
-                                FieldAddress(EAX, Context::parent_offset()),
-                                Object::null_object());
+    __ StoreIntoObjectNoBarrier(
+        EAX, FieldAddress(EAX, target::Context::parent_offset()), NullObject());
 
     // Initialize the context variables.
     // EAX: new object.
     // EDX: number of context variables.
     {
       Label loop, entry;
-      __ leal(EBX, FieldAddress(EAX, Context::variable_offset(0)));
+      __ leal(EBX, FieldAddress(EAX, target::Context::variable_offset(0)));
 
       __ jmp(&entry, Assembler::kNearJump);
       __ Bind(&loop);
       __ decl(EDX);
       // No generational barrier needed, since we are storing null.
       __ StoreIntoObjectNoBarrier(EAX, Address(EBX, EDX, TIMES_4, 0),
-                                  Object::null_object());
+                                  NullObject());
       __ Bind(&entry);
       __ cmpl(EDX, Immediate(0));
       __ j(NOT_EQUAL, &loop, Assembler::kNearJump);
@@ -976,7 +1013,7 @@
   __ ret();
 }
 
-void StubCode::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
   // Not used on IA32.
   __ Breakpoint();
 }
@@ -1003,8 +1040,8 @@
   // store buffer if the object is in the store buffer already.
   // Spilled: EAX, ECX
   // EDX: Address being stored
-  __ movl(EAX, FieldAddress(EDX, Object::tags_offset()));
-  __ testl(EAX, Immediate(1 << RawObject::kOldAndNotRememberedBit));
+  __ movl(EAX, FieldAddress(EDX, target::Object::tags_offset()));
+  __ testl(EAX, Immediate(1 << target::RawObject::kOldAndNotRememberedBit));
   __ j(NOT_EQUAL, &add_to_buffer, Assembler::kNearJump);
   __ popl(ECX);
   __ popl(EAX);
@@ -1017,12 +1054,12 @@
 
   if (cards) {
     // Check if this object is using remembered cards.
-    __ testl(EAX, Immediate(1 << RawObject::kCardRememberedBit));
+    __ testl(EAX, Immediate(1 << target::RawObject::kCardRememberedBit));
     __ j(NOT_EQUAL, &remember_card, Assembler::kFarJump);  // Unlikely.
   } else {
 #if defined(DEBUG)
     Label ok;
-    __ testl(EAX, Immediate(1 << RawObject::kCardRememberedBit));
+    __ testl(EAX, Immediate(1 << target::RawObject::kCardRememberedBit));
     __ j(ZERO, &ok, Assembler::kFarJump);  // Unlikely.
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1031,16 +1068,18 @@
 
   // lock+andl is an atomic read-modify-write.
   __ lock();
-  __ andl(FieldAddress(EDX, Object::tags_offset()),
-          Immediate(~(1 << RawObject::kOldAndNotRememberedBit)));
+  __ andl(FieldAddress(EDX, target::Object::tags_offset()),
+          Immediate(~(1 << target::RawObject::kOldAndNotRememberedBit)));
 
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
   // Spilled: EAX, ECX
   // EDX: Address being stored
-  __ movl(EAX, Address(THR, Thread::store_buffer_block_offset()));
-  __ movl(ECX, Address(EAX, StoreBufferBlock::top_offset()));
-  __ movl(Address(EAX, ECX, TIMES_4, StoreBufferBlock::pointers_offset()), EDX);
+  __ movl(EAX, Address(THR, target::Thread::store_buffer_block_offset()));
+  __ movl(ECX, Address(EAX, target::StoreBufferBlock::top_offset()));
+  __ movl(
+      Address(EAX, ECX, TIMES_4, target::StoreBufferBlock::pointers_offset()),
+      EDX);
 
   // Increment top_ and check for overflow.
   // Spilled: EAX, ECX
@@ -1048,8 +1087,8 @@
   // EAX: StoreBufferBlock
   Label overflow;
   __ incl(ECX);
-  __ movl(Address(EAX, StoreBufferBlock::top_offset()), ECX);
-  __ cmpl(ECX, Immediate(StoreBufferBlock::kSize));
+  __ movl(Address(EAX, target::StoreBufferBlock::top_offset()), ECX);
+  __ cmpl(ECX, Immediate(target::StoreBufferBlock::kSize));
   // Restore values.
   // Spilled: EAX, ECX
   __ popl(ECX);
@@ -1061,7 +1100,7 @@
   __ Bind(&overflow);
   // Setup frame, push callee-saved registers.
 
-  __ EnterCallRuntimeFrame(1 * kWordSize);
+  __ EnterCallRuntimeFrame(1 * target::kWordSize);
   __ movl(Address(ESP, 0), THR);  // Push the thread as the only argument.
   __ CallRuntime(kStoreBufferBlockProcessRuntimeEntry, 1);
   // Restore callee-saved registers, tear down frame.
@@ -1073,16 +1112,19 @@
 
     // Get card table.
     __ Bind(&remember_card);
-    __ movl(EAX, EDX);                   // Object.
-    __ andl(EAX, Immediate(kPageMask));  // HeapPage.
-    __ cmpl(Address(EAX, HeapPage::card_table_offset()), Immediate(0));
+    __ movl(EAX, EDX);                           // Object.
+    __ andl(EAX, Immediate(target::kPageMask));  // HeapPage.
+    __ cmpl(Address(EAX, target::HeapPage::card_table_offset()), Immediate(0));
     __ j(EQUAL, &remember_card_slow, Assembler::kNearJump);
 
     // Dirty the card.
     __ subl(EDI, EAX);  // Offset in page.
-    __ movl(EAX, Address(EAX, HeapPage::card_table_offset()));  // Card table.
+    __ movl(
+        EAX,
+        Address(EAX, target::HeapPage::card_table_offset()));  // Card table.
     __ shrl(EDI,
-            Immediate(HeapPage::kBytesPerCardLog2));  // Index in card table.
+            Immediate(
+                target::HeapPage::kBytesPerCardLog2));  // Index in card table.
     __ movb(Address(EAX, EDI, TIMES_1, 0), Immediate(1));
     __ popl(ECX);
     __ popl(EAX);
@@ -1090,9 +1132,9 @@
 
     // Card table not yet allocated.
     __ Bind(&remember_card_slow);
-    __ EnterCallRuntimeFrame(2 * kWordSize);
-    __ movl(Address(ESP, 0 * kWordSize), EDX);  // Object
-    __ movl(Address(ESP, 1 * kWordSize), EDI);  // Slot
+    __ EnterCallRuntimeFrame(2 * target::kWordSize);
+    __ movl(Address(ESP, 0 * target::kWordSize), EDX);  // Object
+    __ movl(Address(ESP, 1 * target::kWordSize), EDI);  // Slot
     __ CallRuntime(kRememberCardRuntimeEntry, 2);
     __ LeaveCallRuntimeFrame();
     __ popl(ECX);
@@ -1101,14 +1143,16 @@
   }
 }
 
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+      assembler, Address(THR, target::Thread::write_barrier_code_offset()),
+      false);
 }
 
-void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateArrayWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
+      assembler,
+      Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
@@ -1118,56 +1162,53 @@
 // Uses EAX, EBX, ECX, EDX, EDI as temporary registers.
 // Returns patch_code_pc offset where patching code for disabling the stub
 // has been generated (similar to regularly generated Dart code).
-void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
-                                              const Class& cls) {
-  const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
+                                                      const Class& cls) {
+  const intptr_t kObjectTypeArgumentsOffset = 1 * target::kWordSize;
+  const Immediate& raw_null = Immediate(target::ToRawPointer(NullObject()));
   // The generated code is different if the class is parameterized.
-  const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
-  ASSERT(!is_cls_parameterized ||
-         (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
+                                      cls) != target::Class::kNoTypeArguments);
   // kInlineInstanceSize is a constant used as a threshold for determining
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;  // In words.
-  const intptr_t instance_size = cls.instance_size();
+  const intptr_t instance_size = target::Class::InstanceSize(cls);
   ASSERT(instance_size > 0);
   if (is_cls_parameterized) {
     __ movl(EDX, Address(ESP, kObjectTypeArgumentsOffset));
     // EDX: instantiated type arguments.
   }
-  Isolate* isolate = Isolate::Current();
-  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) &&
-      !cls.TraceAllocation(isolate)) {
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size) &&
+      !target::Class::TraceAllocation(cls)) {
     Label slow_case;
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // EDX: instantiated type arguments (if is_cls_parameterized).
-    __ movl(EAX, Address(THR, Thread::top_offset()));
+    __ movl(EAX, Address(THR, target::Thread::top_offset()));
     __ leal(EBX, Address(EAX, instance_size));
     // Check if the allocation fits into the remaining space.
     // EAX: potential new object start.
     // EBX: potential next object start.
-    __ cmpl(EBX, Address(THR, Thread::end_offset()));
+    __ cmpl(EBX, Address(THR, target::Thread::end_offset()));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
       __ j(ABOVE_EQUAL, &slow_case);
     }
-    __ movl(Address(THR, Thread::top_offset()), EBX);
-    NOT_IN_PRODUCT(__ UpdateAllocationStats(cls.id(), ECX));
+    __ movl(Address(THR, target::Thread::top_offset()), EBX);
+    NOT_IN_PRODUCT(__ UpdateAllocationStats(target::Class::GetId(cls), ECX));
 
     // EAX: new object start (untagged).
     // EBX: next object start.
     // EDX: new object type arguments (if is_cls_parameterized).
     // Set the tags.
-    uint32_t tags = 0;
-    tags = RawObject::SizeTag::update(instance_size, tags);
-    ASSERT(cls.id() != kIllegalCid);
-    tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    tags = RawObject::NewBit::update(true, tags);
-    __ movl(Address(EAX, Instance::tags_offset()), Immediate(tags));
+    ASSERT(target::Class::GetId(cls) != kIllegalCid);
+    uint32_t tags = target::MakeTagWordForNewSpaceObject(
+        target::Class::GetId(cls), instance_size);
+    __ movl(Address(EAX, target::Object::tags_offset()), Immediate(tags));
     __ addl(EAX, Immediate(kHeapObjectTag));
 
     // Initialize the remaining words of the object.
@@ -1176,16 +1217,17 @@
     // EBX: next object start.
     // EDX: new object type arguments (if is_cls_parameterized).
     // First try inlining the initialization without a loop.
-    if (instance_size < (kInlineInstanceSize * kWordSize)) {
+    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
       // Check if the object contains any non-header fields.
       // Small objects are initialized using a consecutive set of writes.
-      for (intptr_t current_offset = Instance::NextFieldOffset();
-           current_offset < instance_size; current_offset += kWordSize) {
+      for (intptr_t current_offset = target::Instance::first_field_offset();
+           current_offset < instance_size;
+           current_offset += target::kWordSize) {
         __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, current_offset),
-                                    Object::null_object());
+                                    NullObject());
       }
     } else {
-      __ leal(ECX, FieldAddress(EAX, Instance::NextFieldOffset()));
+      __ leal(ECX, FieldAddress(EAX, target::Instance::first_field_offset()));
       // Loop until the whole object is initialized.
       // EAX: new object (tagged).
       // EBX: next object start.
@@ -1196,8 +1238,8 @@
       __ Bind(&init_loop);
       __ cmpl(ECX, EBX);
       __ j(ABOVE_EQUAL, &done, Assembler::kNearJump);
-      __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), Object::null_object());
-      __ addl(ECX, Immediate(kWordSize));
+      __ StoreIntoObjectNoBarrier(EAX, Address(ECX, 0), NullObject());
+      __ addl(ECX, Immediate(target::kWordSize));
       __ jmp(&init_loop, Assembler::kNearJump);
       __ Bind(&done);
     }
@@ -1205,7 +1247,7 @@
       // EAX: new object (tagged).
       // EDX: new object type arguments.
       // Set the type arguments in the new object.
-      intptr_t offset = cls.type_arguments_field_offset();
+      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
       __ StoreIntoObjectNoBarrier(EAX, FieldAddress(EAX, offset), EDX);
     }
     // Done allocating and initializing the instance.
@@ -1220,7 +1262,8 @@
   // calling into the runtime.
   __ EnterStubFrame();
   __ pushl(raw_null);  // Setup space on stack for return value.
-  __ PushObject(cls);  // Push class of object to be allocated.
+  __ PushObject(
+      CastHandle<Object>(cls));  // Push class of object to be allocated.
   if (is_cls_parameterized) {
     __ pushl(EDX);  // Push type arguments of object to be allocated.
   } else {
@@ -1244,24 +1287,28 @@
 //   ESP + 4 : address of last argument.
 //   EDX : arguments descriptor array.
 // Uses EAX, EBX, EDI as temporary registers.
-void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ movl(EDI, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
-  __ movl(EAX, Address(EBP, EDI, TIMES_2, kParamEndSlotFromFp * kWordSize));
+  __ movl(EDI, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
+  __ movl(EAX,
+          Address(EBP, EDI, TIMES_2,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
 
   __ pushl(Immediate(0));  // Setup space on stack for result from noSuchMethod.
   __ pushl(EAX);           // Receiver.
   __ pushl(EDX);           // Arguments descriptor array.
 
   // Adjust arguments count.
-  __ cmpl(FieldAddress(EDX, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ cmpl(
+      FieldAddress(EDX, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   __ movl(EDX, EDI);
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addl(EDX, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addl(EDX, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
 
   // EDX: Smi-tagged arguments array length.
@@ -1275,7 +1322,8 @@
 
 // Cannot use function object from ICData as it may be the inlined
 // function and not the top-scope function.
-void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
+    Assembler* assembler) {
   Register ic_reg = ECX;
   Register func_reg = EBX;
   if (FLAG_trace_optimized_ic_calls) {
@@ -1291,19 +1339,19 @@
     __ popl(func_reg);  // Restore.
     __ LeaveFrame();
   }
-  __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
+  __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
 }
 
 // Loads function into 'temp_reg'.
-void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
-                                             Register temp_reg) {
+void StubCodeCompiler::GenerateUsageCounterIncrement(Assembler* assembler,
+                                                     Register temp_reg) {
   if (FLAG_optimization_counter_threshold >= 0) {
     Register ic_reg = ECX;
     Register func_reg = temp_reg;
     ASSERT(ic_reg != func_reg);
     __ Comment("Increment function counter");
-    __ movl(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
-    __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
+    __ movl(func_reg, FieldAddress(ic_reg, target::ICData::owner_offset()));
+    __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
   }
 }
 
@@ -1317,8 +1365,8 @@
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   ASSERT(num_args == 2);
-  __ movl(EDI, Address(ESP, +1 * kWordSize));  // Right
-  __ movl(EAX, Address(ESP, +2 * kWordSize));  // Left
+  __ movl(EDI, Address(ESP, +1 * target::kWordSize));  // Right
+  __ movl(EAX, Address(ESP, +2 * target::kWordSize));  // Left
   __ movl(EBX, EDI);
   __ orl(EBX, EAX);
   __ testl(EBX, Immediate(kSmiTagMask));
@@ -1344,10 +1392,10 @@
       Label done, is_true;
       __ cmpl(EAX, EDI);
       __ j(EQUAL, &is_true, Assembler::kNearJump);
-      __ LoadObject(EAX, Bool::False());
+      __ LoadObject(EAX, CastHandle<Object>(FalseObject()));
       __ jmp(&done, Assembler::kNearJump);
       __ Bind(&is_true);
-      __ LoadObject(EAX, Bool::True());
+      __ LoadObject(EAX, CastHandle<Object>(TrueObject()));
       __ Bind(&done);
       break;
     }
@@ -1356,26 +1404,26 @@
   }
 
   // ECX: IC data object.
-  __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
+  __ movl(EBX, FieldAddress(ECX, target::ICData::entries_offset()));
   // EBX: ic_data_array with check entries: classes and target functions.
-  __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
+  __ leal(EBX, FieldAddress(EBX, target::Array::data_offset()));
 #if defined(DEBUG)
   // Check that first entry is for Smi/Smi.
   Label error, ok;
-  const Immediate& imm_smi_cid =
-      Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
-  __ cmpl(Address(EBX, 0 * kWordSize), imm_smi_cid);
+  const Immediate& imm_smi_cid = Immediate(target::ToRawSmi(kSmiCid));
+  __ cmpl(Address(EBX, 0 * target::kWordSize), imm_smi_cid);
   __ j(NOT_EQUAL, &error, Assembler::kNearJump);
-  __ cmpl(Address(EBX, 1 * kWordSize), imm_smi_cid);
+  __ cmpl(Address(EBX, 1 * target::kWordSize), imm_smi_cid);
   __ j(EQUAL, &ok, Assembler::kNearJump);
   __ Bind(&error);
   __ Stop("Incorrect IC data");
   __ Bind(&ok);
 #endif
   if (FLAG_optimization_counter_threshold >= 0) {
-    const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+    const intptr_t count_offset =
+        target::ICData::CountIndexFor(num_args) * target::kWordSize;
     // Update counter, ignore overflow.
-    __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
+    __ addl(Address(EBX, count_offset), Immediate(target::ToRawSmi(1)));
   }
   __ ret();
 }
@@ -1390,7 +1438,7 @@
 // - Check if 'num_args' (including receiver) match any IC data group.
 // - Match found -> jump to target.
 // - Match not found -> jump to IC miss.
-void StubCode::GenerateNArgsCheckInlineCacheStub(
+void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
     Assembler* assembler,
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
@@ -1404,9 +1452,9 @@
     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, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
+    __ movl(EBX, 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));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect stub for IC data");
@@ -1419,7 +1467,7 @@
   if (!optimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(EAX);
-    __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0));
+    __ cmpb(Address(EAX, target::Isolate::single_step_offset()), Immediate(0));
     __ j(NOT_EQUAL, &stepping);
     __ Bind(&done_stepping);
   }
@@ -1433,20 +1481,21 @@
   __ Comment("Extract ICData initial values and receiver cid");
   // ECX: IC data object (preserved).
   // Load arguments descriptor into EDX.
-  __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
+  __ movl(EDX,
+          FieldAddress(ECX, target::ICData::arguments_descriptor_offset()));
   // Loop that checks if there is an IC data match.
   Label loop, found, miss;
   // ECX: IC data object (preserved).
-  __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
+  __ movl(EBX, FieldAddress(ECX, target::ICData::entries_offset()));
   // EBX: ic_data_array with check entries: classes and target functions.
-  __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
+  __ leal(EBX, FieldAddress(EBX, target::Array::data_offset()));
   // EBX: points directly to the first ic data array element.
 
   // Get argument descriptor into EAX.  In the 1-argument case this is the
   // last time we need the argument descriptor, and we reuse EAX for the
   // class IDs from the IC descriptor.  In the 2-argument case we preserve
   // the argument descriptor in EAX.
-  __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  __ movl(EAX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
   if (num_args == 1) {
     // Load receiver into EDI.
     __ movl(EDI,
@@ -1459,20 +1508,23 @@
 
   // We unroll the generic one that is generated once more than the others.
   bool optimize = kind == Token::kILLEGAL;
-  const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(num_args) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(num_args) * target::kWordSize;
   const intptr_t entry_size =
-      ICData::TestEntryLengthFor(num_args, exactness_check) * kWordSize;
+      target::ICData::TestEntryLengthFor(num_args, exactness_check) *
+      target::kWordSize;
 
   __ Bind(&loop);
   for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
     Label update;
     if (num_args == 1) {
       __ movl(EDI, Address(EBX, 0));
-      __ cmpl(EDI, EAX);                                    // Class id match?
-      __ j(EQUAL, &found);                                  // Break.
-      __ addl(EBX, Immediate(entry_size));                  // Next entry.
-      __ cmpl(EDI, Immediate(Smi::RawValue(kIllegalCid)));  // Done?
+      __ cmpl(EDI, EAX);                    // Class id match?
+      __ j(EQUAL, &found);                  // Break.
+      __ addl(EBX, Immediate(entry_size));  // Next entry.
+      __ cmpl(EDI, Immediate(target::ToRawSmi(kIllegalCid)));  // Done?
     } else {
       ASSERT(num_args == 2);
       // Load receiver into EDI.
@@ -1482,15 +1534,15 @@
       __ j(NOT_EQUAL, &update);       // Continue.
 
       // Load second argument into EDI.
-      __ movl(EDI, Address(ESP, EAX, TIMES_2, -kWordSize));
+      __ movl(EDI, Address(ESP, EAX, TIMES_2, -target::kWordSize));
       __ LoadTaggedClassIdMayBeSmi(EDI, EDI);
-      __ cmpl(EDI, Address(EBX, kWordSize));  // Class id match?
-      __ j(EQUAL, &found);                    // Break.
+      __ cmpl(EDI, Address(EBX, target::kWordSize));  // Class id match?
+      __ j(EQUAL, &found);                            // Break.
 
       __ Bind(&update);
       __ addl(EBX, Immediate(entry_size));  // Next entry.
       __ cmpl(Address(EBX, -entry_size),
-              Immediate(Smi::RawValue(kIllegalCid)));  // Done?
+              Immediate(target::ToRawSmi(kIllegalCid)));  // Done?
     }
 
     if (unroll == 0) {
@@ -1504,7 +1556,7 @@
   __ Comment("IC miss");
   // Compute address of arguments (first read number of arguments from
   // arguments descriptor array and then compute address on the stack).
-  __ movl(EAX, FieldAddress(EDX, ArgumentsDescriptor::count_offset()));
+  __ movl(EAX, FieldAddress(EDX, target::ArgumentsDescriptor::count_offset()));
   __ leal(EAX, Address(ESP, EAX, TIMES_2, 0));  // EAX is Smi.
   // Create a stub frame as we are pushing some objects on the stack before
   // calling into the runtime.
@@ -1514,7 +1566,7 @@
   __ pushl(Immediate(0));  // Result slot.
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ movl(EBX, Address(EAX, -kWordSize * i));
+    __ movl(EBX, Address(EAX, -target::kWordSize * i));
     __ pushl(EBX);
   }
   __ pushl(ECX);  // Pass IC data object.
@@ -1540,14 +1592,14 @@
   if (FLAG_optimization_counter_threshold >= 0) {
     __ Comment("Update caller's counter");
     // Ignore overflow.
-    __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
+    __ addl(Address(EBX, count_offset), Immediate(target::ToRawSmi(1)));
   }
 
   __ movl(EAX, Address(EBX, target_offset));
   __ Bind(&call_target_function);
   __ Comment("Call target");
   // EAX: Target function.
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EBX);
 
 #if !defined(PRODUCT)
@@ -1573,37 +1625,39 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
                                     kInlineCacheMissHandlerTwoArgsRuntimeEntry,
                                     Token::kILLEGAL);
 }
 
-void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
-void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
-void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
@@ -1620,7 +1674,7 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
@@ -1628,12 +1682,13 @@
                                     Token::kILLEGAL, true /* optimized */);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
-    Assembler* assembler) {
+void StubCodeCompiler::
+    GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
+        Assembler* assembler) {
   __ Stop("Unimplemented");
 }
 
-void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
@@ -1644,7 +1699,8 @@
 // Intermediary stub between a static call and its target. ICData contains
 // the target function and the call count.
 // ECX: ICData
-void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
 
 #if defined(DEBUG)
@@ -1652,9 +1708,9 @@
     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, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andl(EBX, Immediate(ICData::NumArgsTestedMask()));
+    __ movl(EBX, FieldAddress(ECX, target::ICData::state_bits_offset()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andl(EBX, Immediate(target::ICData::NumArgsTestedMask()));
     __ cmpl(EBX, Immediate(0));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect IC data for unoptimized static call");
@@ -1666,30 +1722,33 @@
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(EAX);
-  __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0));
+  __ cmpb(Address(EAX, target::Isolate::single_step_offset()), Immediate(0));
   __ j(NOT_EQUAL, &stepping, Assembler::kNearJump);
   __ Bind(&done_stepping);
 #endif
 
   // ECX: IC data object (preserved).
-  __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset()));
+  __ movl(EBX, FieldAddress(ECX, target::ICData::entries_offset()));
   // EBX: ic_data_array with entries: target functions and count.
-  __ leal(EBX, FieldAddress(EBX, Array::data_offset()));
+  __ leal(EBX, FieldAddress(EBX, target::Array::data_offset()));
   // EBX: points directly to the first ic data array element.
-  const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(0) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(0) * target::kWordSize;
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Increment count for this call, ignore overflow.
-    __ addl(Address(EBX, count_offset), Immediate(Smi::RawValue(1)));
+    __ addl(Address(EBX, count_offset), Immediate(target::ToRawSmi(1)));
   }
 
   // Load arguments descriptor into EDX.
-  __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset()));
+  __ movl(EDX,
+          FieldAddress(ECX, target::ICData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ movl(EAX, Address(EBX, target_offset));
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EBX);
 
 #if !defined(PRODUCT)
@@ -1703,13 +1762,15 @@
 #endif
 }
 
-void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, EBX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
@@ -1718,7 +1779,7 @@
 // Stub for compiling a function and jumping to the compiled code.
 // EDX: Arguments descriptor.
 // EAX: Function.
-void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushl(EDX);  // Preserve arguments descriptor array.
   __ pushl(EAX);  // Pass function.
@@ -1729,16 +1790,16 @@
 
   // When using the interpreter, the function's code may now point to the
   // InterpretCall stub. Make sure EAX, ECX, and EDX are preserved.
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EBX);
 }
 
-void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
   __ Unimplemented("Interpreter not yet supported");
 }
 
 // ECX: Contains an ICData.
-void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Save IC data.
   __ pushl(ECX);
@@ -1750,11 +1811,11 @@
   __ popl(ECX);  // Restore IC data.
   __ LeaveFrame();
   // Jump to original stub.
-  __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
+  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
   __ jmp(EAX);
 }
 
-void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Room for result. Debugger stub returns address of the
   // unpatched runtime stub.
@@ -1763,16 +1824,19 @@
   __ popl(EAX);  // Code of the original stub
   __ LeaveFrame();
   // Jump to original stub.
-  __ movl(EAX, FieldAddress(EAX, Code::entry_point_offset()));
+  __ movl(EAX, FieldAddress(EAX, target::Code::entry_point_offset()));
   __ jmp(EAX);
 }
 
 // Called only from unoptimized code.
-void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDebugStepCheckStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ ret();
+#else
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(EAX);
-  __ movzxb(EAX, Address(EAX, Isolate::single_step_offset()));
+  __ movzxb(EAX, Address(EAX, target::Isolate::single_step_offset()));
   __ cmpl(EAX, Immediate(0));
   __ j(NOT_EQUAL, &stepping, Assembler::kNearJump);
   __ Bind(&done_stepping);
@@ -1783,6 +1847,7 @@
   __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
   __ LeaveFrame();
   __ jmp(&done_stepping, Assembler::kNearJump);
+#endif  // defined(PRODUCT)
 }
 
 // Used to check class and type arguments. Arguments passed on stack:
@@ -1795,26 +1860,25 @@
 static void GenerateSubtypeNTestCacheStub(Assembler* assembler, int n) {
   ASSERT(n == 1 || n == 2 || n == 4 || n == 6);
 
-  static intptr_t kFunctionTypeArgumentsInBytes = 1 * kWordSize;
-  static intptr_t kInstantiatorTypeArgumentsInBytes = 2 * kWordSize;
-  static intptr_t kInstanceOffsetInBytes = 3 * kWordSize;
-  static intptr_t kCacheOffsetInBytes = 4 * kWordSize;
+  static intptr_t kFunctionTypeArgumentsInBytes = 1 * target::kWordSize;
+  static intptr_t kInstantiatorTypeArgumentsInBytes = 2 * target::kWordSize;
+  static intptr_t kInstanceOffsetInBytes = 3 * target::kWordSize;
+  static intptr_t kCacheOffsetInBytes = 4 * target::kWordSize;
 
   const Register kInstanceReg = EAX;
 
   const Register kInstanceCidOrFunction = ECX;
   const Register kInstanceInstantiatorTypeArgumentsReg = EBX;
 
-  const Immediate& raw_null =
-      Immediate(reinterpret_cast<intptr_t>(Object::null()));
+  const auto& raw_null = Immediate(target::ToRawPointer(NullObject()));
 
   __ movl(kInstanceReg, Address(ESP, kInstanceOffsetInBytes));
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other)
   __ movl(EDX, Address(ESP, kCacheOffsetInBytes));
-  __ movl(EDX, FieldAddress(EDX, SubtypeTestCache::cache_offset()));
-  __ addl(EDX, Immediate(Array::data_offset() - kHeapObjectTag));
+  __ movl(EDX, FieldAddress(EDX, target::SubtypeTestCache::cache_offset()));
+  __ addl(EDX, Immediate(target::Array::data_offset() - kHeapObjectTag));
 
   Label loop, not_closure;
   if (n >= 4) {
@@ -1828,16 +1892,17 @@
   // Closure handling.
   {
     __ movl(kInstanceCidOrFunction,
-            FieldAddress(kInstanceReg, Closure::function_offset()));
+            FieldAddress(kInstanceReg, target::Closure::function_offset()));
     if (n >= 2) {
-      __ movl(kInstanceInstantiatorTypeArgumentsReg,
-              FieldAddress(kInstanceReg,
-                           Closure::instantiator_type_arguments_offset()));
+      __ movl(
+          kInstanceInstantiatorTypeArgumentsReg,
+          FieldAddress(kInstanceReg,
+                       target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
-        __ pushl(FieldAddress(kInstanceReg,
-                              Closure::delayed_type_arguments_offset()));
-        __ pushl(FieldAddress(kInstanceReg,
-                              Closure::function_type_arguments_offset()));
+        __ pushl(FieldAddress(
+            kInstanceReg, target::Closure::delayed_type_arguments_offset()));
+        __ pushl(FieldAddress(
+            kInstanceReg, target::Closure::function_type_arguments_offset()));
       }
     }
     __ jmp(&loop, Assembler::kNearJump);
@@ -1850,10 +1915,12 @@
       Label has_no_type_arguments;
       __ LoadClassById(EDI, kInstanceCidOrFunction);
       __ movl(kInstanceInstantiatorTypeArgumentsReg, raw_null);
-      __ movl(EDI,
-              FieldAddress(
-                  EDI, Class::type_arguments_field_offset_in_words_offset()));
-      __ cmpl(EDI, Immediate(Class::kNoTypeArguments));
+      __ movl(
+          EDI,
+          FieldAddress(
+              EDI,
+              target::Class::type_arguments_field_offset_in_words_offset()));
+      __ cmpl(EDI, Immediate(target::Class::kNoTypeArguments));
       __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
       __ movl(kInstanceInstantiatorTypeArgumentsReg,
               FieldAddress(kInstanceReg, EDI, TIMES_4, 0));
@@ -1868,15 +1935,18 @@
   }
 
   const intptr_t kInstanceParentFunctionTypeArgumentsFromSp = 0;
-  const intptr_t kInstanceDelayedFunctionTypeArgumentsFromSp = kWordSize;
-  const intptr_t args_offset = n >= 6 ? 2 * kWordSize : 0;
+  const intptr_t kInstanceDelayedFunctionTypeArgumentsFromSp =
+      target::kWordSize;
+  const intptr_t args_offset = n >= 6 ? 2 * target::kWordSize : 0;
 
   Label found, not_found, next_iteration;
 
   // Loop header.
   __ Bind(&loop);
-  __ movl(EDI, Address(EDX, kWordSize *
-                                SubtypeTestCache::kInstanceClassIdOrFunction));
+  __ movl(
+      EDI,
+      Address(EDX, target::kWordSize *
+                       target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmpl(EDI, raw_null);
   __ j(EQUAL, &not_found, Assembler::kNearJump);
   __ cmpl(EDI, kInstanceCidOrFunction);
@@ -1885,19 +1955,24 @@
   } else {
     __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
     __ cmpl(kInstanceInstantiatorTypeArgumentsReg,
-            Address(EDX, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
+            Address(EDX, target::kWordSize *
+                             target::SubtypeTestCache::kInstanceTypeArguments));
     if (n == 2) {
       __ j(EQUAL, &found, Assembler::kNearJump);
     } else {
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-      __ movl(EDI,
-              Address(EDX, kWordSize *
-                               SubtypeTestCache::kInstantiatorTypeArguments));
+      __ movl(
+          EDI,
+          Address(EDX,
+                  target::kWordSize *
+                      target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ cmpl(EDI,
               Address(ESP, args_offset + kInstantiatorTypeArgumentsInBytes));
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-      __ movl(EDI, Address(EDX, kWordSize *
-                                    SubtypeTestCache::kFunctionTypeArguments));
+      __ movl(
+          EDI,
+          Address(EDX, target::kWordSize *
+                           target::SubtypeTestCache::kFunctionTypeArguments));
       __ cmpl(EDI, Address(ESP, args_offset + kFunctionTypeArgumentsInBytes));
       if (n == 4) {
         __ j(EQUAL, &found, Assembler::kNearJump);
@@ -1905,31 +1980,29 @@
         ASSERT(n == 6);
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
 
-        __ movl(
-            EDI,
-            Address(
-                EDX,
-                kWordSize *
-                    SubtypeTestCache::kInstanceParentFunctionTypeArguments));
+        __ movl(EDI,
+                Address(EDX, target::kWordSize *
+                                 target::SubtypeTestCache::
+                                     kInstanceParentFunctionTypeArguments));
         __ cmpl(EDI, Address(ESP, kInstanceParentFunctionTypeArgumentsFromSp));
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-        __ movl(
-            EDI,
-            Address(
-                EDX,
-                kWordSize *
-                    SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
+        __ movl(EDI,
+                Address(EDX, target::kWordSize *
+                                 target::SubtypeTestCache::
+                                     kInstanceDelayedFunctionTypeArguments));
         __ cmpl(EDI, Address(ESP, kInstanceDelayedFunctionTypeArgumentsFromSp));
         __ j(EQUAL, &found, Assembler::kNearJump);
       }
     }
   }
   __ Bind(&next_iteration);
-  __ addl(EDX, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
+  __ addl(EDX, Immediate(target::kWordSize *
+                         target::SubtypeTestCache::kTestEntryLength));
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&found);
-  __ movl(ECX, Address(EDX, kWordSize * SubtypeTestCache::kTestResult));
+  __ movl(ECX, Address(EDX, target::kWordSize *
+                                target::SubtypeTestCache::kTestResult));
   if (n == 6) {
     __ Drop(2);
   }
@@ -1944,51 +2017,52 @@
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype1TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 1);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype2TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 2);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype4TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 4);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype6TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype6TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 6);
 }
 
-void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
 
-void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
 
-void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
 
-void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
 
-void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
+    Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
 
-void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
   // Not implemented on ia32.
   __ Breakpoint();
 }
@@ -1996,8 +2070,8 @@
 // Return the current stack pointer address, used to do stack alignment checks.
 // TOS + 0: return address
 // Result in EAX.
-void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
-  __ leal(EAX, Address(ESP, kWordSize));
+void StubCodeCompiler::GenerateGetCStackPointerStub(Assembler* assembler) {
+  __ leal(EAX, Address(ESP, target::kWordSize));
   __ ret();
 }
 
@@ -2008,15 +2082,19 @@
 // TOS + 3: frame_pointer
 // TOS + 4: thread
 // No Result.
-void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
-  __ movl(THR, Address(ESP, 4 * kWordSize));  // Load target thread.
-  __ movl(EBP, Address(ESP, 3 * kWordSize));  // Load target frame_pointer.
-  __ movl(EBX, Address(ESP, 1 * kWordSize));  // Load target PC into EBX.
-  __ movl(ESP, Address(ESP, 2 * kWordSize));  // Load target stack_pointer.
+void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
+  __ movl(THR, Address(ESP, 4 * target::kWordSize));  // Load target thread.
+  __ movl(EBP,
+          Address(ESP, 3 * target::kWordSize));  // Load target frame_pointer.
+  __ movl(EBX,
+          Address(ESP, 1 * target::kWordSize));  // Load target PC into EBX.
+  __ movl(ESP,
+          Address(ESP, 2 * target::kWordSize));  // Load target stack_pointer.
   // Set tag.
   __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   // Clear top exit frame.
-  __ movl(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movl(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
   __ jmp(EBX);  // Jump to the exception handler code.
 }
 
@@ -2024,21 +2102,21 @@
 //
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
   ASSERT(kExceptionObjectReg == EAX);
   ASSERT(kStackTraceObjectReg == EDX);
-  __ movl(EBX, Address(THR, Thread::resume_pc_offset()));
+  __ movl(EBX, Address(THR, target::Thread::resume_pc_offset()));
 
-  ASSERT(Thread::CanLoadFromThread(Object::null_object()));
-  __ movl(ECX, Address(THR, Thread::OffsetFromThread(Object::null_object())));
+  ASSERT(target::CanLoadFromThread(NullObject()));
+  __ movl(ECX, Address(THR, target::Thread::OffsetFromThread(NullObject())));
 
   // Load the exception from the current thread.
-  Address exception_addr(THR, Thread::active_exception_offset());
+  Address exception_addr(THR, target::Thread::active_exception_offset());
   __ movl(kExceptionObjectReg, exception_addr);
   __ movl(exception_addr, ECX);
 
   // Load the stacktrace from the current thread.
-  Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
+  Address stacktrace_addr(THR, target::Thread::active_stacktrace_offset());
   __ movl(kStackTraceObjectReg, stacktrace_addr);
   __ movl(stacktrace_addr, ECX);
 
@@ -2048,9 +2126,9 @@
 // Deoptimize a frame on the call stack before rewinding.
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
   // Push the deopt pc.
-  __ pushl(Address(THR, Thread::resume_pc_offset()));
+  __ pushl(Address(THR, target::Thread::resume_pc_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -2063,7 +2141,7 @@
 // Calls to the runtime to optimize the given function.
 // EBX: function to be reoptimized.
 // EDX: argument descriptor (preserved).
-void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushl(EDX);
   __ pushl(Immediate(0));  // Setup space on stack for return value.
@@ -2073,8 +2151,8 @@
   __ popl(EAX);  // Get Function object
   __ popl(EDX);  // Restore argument descriptor.
   __ LeaveFrame();
-  __ movl(CODE_REG, FieldAddress(EAX, Function::code_offset()));
-  __ movl(EAX, FieldAddress(EAX, Function::entry_point_offset()));
+  __ movl(CODE_REG, FieldAddress(EAX, target::Function::code_offset()));
+  __ movl(EAX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ jmp(EAX);
   __ int3();
 }
@@ -2101,11 +2179,15 @@
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
 
   // Double values bitwise compare.
-  __ movl(temp, FieldAddress(left, Double::value_offset() + 0 * kWordSize));
-  __ cmpl(temp, FieldAddress(right, Double::value_offset() + 0 * kWordSize));
+  __ movl(temp, FieldAddress(left, target::Double::value_offset() +
+                                       0 * target::kWordSize));
+  __ cmpl(temp, FieldAddress(right, target::Double::value_offset() +
+                                        0 * target::kWordSize));
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-  __ movl(temp, FieldAddress(left, Double::value_offset() + 1 * kWordSize));
-  __ cmpl(temp, FieldAddress(right, Double::value_offset() + 1 * kWordSize));
+  __ movl(temp, FieldAddress(left, target::Double::value_offset() +
+                                       1 * target::kWordSize));
+  __ cmpl(temp, FieldAddress(right, target::Double::value_offset() +
+                                        1 * target::kWordSize));
   __ jmp(&done, Assembler::kNearJump);
 
   __ Bind(&check_mint);
@@ -2113,11 +2195,15 @@
   __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
   __ CompareClassId(right, kMintCid, temp);
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-  __ movl(temp, FieldAddress(left, Mint::value_offset() + 0 * kWordSize));
-  __ cmpl(temp, FieldAddress(right, Mint::value_offset() + 0 * kWordSize));
+  __ movl(temp, FieldAddress(left, target::Mint::value_offset() +
+                                       0 * target::kWordSize));
+  __ cmpl(temp, FieldAddress(right, target::Mint::value_offset() +
+                                        0 * target::kWordSize));
   __ j(NOT_EQUAL, &done, Assembler::kNearJump);
-  __ movl(temp, FieldAddress(left, Mint::value_offset() + 1 * kWordSize));
-  __ cmpl(temp, FieldAddress(right, Mint::value_offset() + 1 * kWordSize));
+  __ movl(temp, FieldAddress(left, target::Mint::value_offset() +
+                                       1 * target::kWordSize));
+  __ cmpl(temp, FieldAddress(right, target::Mint::value_offset() +
+                                        1 * target::kWordSize));
   __ jmp(&done, Assembler::kNearJump);
 
   __ Bind(&reference_compare);
@@ -2130,13 +2216,13 @@
 // TOS + 1: right argument.
 // TOS + 2: left argument.
 // Returns ZF set.
-void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
 #if !defined(PRODUCT)
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(EAX);
-  __ movzxb(EAX, Address(EAX, Isolate::single_step_offset()));
+  __ movzxb(EAX, Address(EAX, target::Isolate::single_step_offset()));
   __ cmpl(EAX, Immediate(0));
   __ j(NOT_EQUAL, &stepping);
   __ Bind(&done_stepping);
@@ -2145,8 +2231,8 @@
   const Register left = EAX;
   const Register right = EDX;
   const Register temp = ECX;
-  __ movl(left, Address(ESP, 2 * kWordSize));
-  __ movl(right, Address(ESP, 1 * kWordSize));
+  __ movl(left, Address(ESP, 2 * target::kWordSize));
+  __ movl(right, Address(ESP, 1 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ ret();
 
@@ -2164,24 +2250,24 @@
 // TOS + 1: right argument.
 // TOS + 2: left argument.
 // Returns ZF set.
-void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
   const Register left = EAX;
   const Register right = EDX;
   const Register temp = ECX;
-  __ movl(left, Address(ESP, 2 * kWordSize));
-  __ movl(right, Address(ESP, 1 * kWordSize));
+  __ movl(left, Address(ESP, 2 * target::kWordSize));
+  __ movl(right, Address(ESP, 1 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
   __ ret();
 }
 
 // Called from megamorphic calls.
 //  EBX: receiver
-//  ECX: MegamorphicCache (preserved)
+//  ECX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  EBX: target entry point
 //  EDX: argument descriptor
-void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   // Jump if receiver is a smi.
   Label smi_case;
   // Check if object (in tmp) is a Smi.
@@ -2194,8 +2280,8 @@
 
   Label cid_loaded;
   __ Bind(&cid_loaded);
-  __ movl(EBX, FieldAddress(ECX, MegamorphicCache::mask_offset()));
-  __ movl(EDI, FieldAddress(ECX, MegamorphicCache::buckets_offset()));
+  __ movl(EBX, FieldAddress(ECX, target::MegamorphicCache::mask_offset()));
+  __ movl(EDI, FieldAddress(ECX, target::MegamorphicCache::buckets_offset()));
   // EDI: cache buckets array.
   // EBX: mask as a smi.
 
@@ -2203,7 +2289,7 @@
   __ addl(EAX, EAX);
 
   // Compute the table index.
-  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
   // Use leal and subl multiply with 7 == 8 - 1.
   __ leal(EDX, Address(EAX, TIMES_8, 0));
   __ subl(EDX, EAX);
@@ -2212,7 +2298,7 @@
   __ Bind(&loop);
   __ andl(EDX, EBX);
 
-  const intptr_t base = Array::data_offset();
+  const intptr_t base = target::Array::data_offset();
   Label probe_failed;
   // EDX is smi tagged, but table entries are two words, so TIMES_4.
   __ cmpl(EAX, FieldAddress(EDI, EDX, TIMES_4, base));
@@ -2224,20 +2310,21 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, base + kWordSize));
+  __ movl(EAX, FieldAddress(EDI, EDX, TIMES_4, base + target::kWordSize));
   __ movl(EDX,
-          FieldAddress(ECX, MegamorphicCache::arguments_descriptor_offset()));
-  __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset()));
+          FieldAddress(
+              ECX, target::MegamorphicCache::arguments_descriptor_offset()));
+  __ movl(EBX, FieldAddress(EAX, target::Function::entry_point_offset()));
   __ ret();
 
   __ Bind(&probe_failed);
   // Probe failed, check if it is a miss.
   __ cmpl(FieldAddress(EDI, EDX, TIMES_4, base),
-          Immediate(Smi::RawValue(kIllegalCid)));
+          Immediate(target::ToRawSmi(kIllegalCid)));
   __ j(ZERO, &load_target, Assembler::kNearJump);
 
   // Try next entry in the table.
-  __ AddImmediate(EDX, Immediate(Smi::RawValue(1)));
+  __ AddImmediate(EDX, Immediate(target::ToRawSmi(1)));
   __ jmp(&loop);
 
   // Load cid for the Smi case.
@@ -2251,34 +2338,37 @@
 //  ECX: ICData (preserved)
 // Passed to target:
 //  EDX: arguments descriptor
-void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
+    Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
   __ int3();
 }
 
+}  // namespace compiler
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_IA32) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/stub_code_x64.cc b/runtime/vm/compiler/stub_code_compiler_x64.cc
similarity index 68%
rename from runtime/vm/stub_code_x64.cc
rename to runtime/vm/compiler/stub_code_compiler_x64.cc
index 346ee01..b357b77 100644
--- a/runtime/vm/stub_code_x64.cc
+++ b/runtime/vm/compiler/stub_code_compiler_x64.cc
@@ -1,27 +1,22 @@
-// Copyright (c) 2013, 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.
 
 #include "vm/globals.h"
 
-#include "vm/stub_code.h"
+#define SHOULD_NOT_INCLUDE_RUNTIME
+
+#include "vm/compiler/stub_code_compiler.h"
 
 #if defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
 
+#include "vm/class_id.h"
+#include "vm/code_entry_kind.h"
 #include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/assembler/disassembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
 #include "vm/constants_x64.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
-#include "vm/heap/scavenger.h"
 #include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/resolver.h"
-#include "vm/stack_frame.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/tags.h"
-#include "vm/type_testing_stubs.h"
 
 #define __ assembler->
 
@@ -35,6 +30,8 @@
 DECLARE_FLAG(bool, enable_interpreter);
 DECLARE_FLAG(bool, precompiled_mode);
 
+namespace compiler {
+
 // Input parameters:
 //   RSP : points to return address.
 //   RSP + 8 : address of last argument in argument array.
@@ -43,18 +40,19 @@
 //   RBX : address of the runtime function to call.
 //   R10 : number of arguments to the call.
 // Must preserve callee saved registers R12 and R13.
-void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) {
-  const intptr_t thread_offset = NativeArguments::thread_offset();
-  const intptr_t argc_tag_offset = NativeArguments::argc_tag_offset();
-  const intptr_t argv_offset = NativeArguments::argv_offset();
-  const intptr_t retval_offset = NativeArguments::retval_offset();
+void StubCodeCompiler::GenerateCallToRuntimeStub(Assembler* assembler) {
+  const intptr_t thread_offset = target::NativeArguments::thread_offset();
+  const intptr_t argc_tag_offset = target::NativeArguments::argc_tag_offset();
+  const intptr_t argv_offset = target::NativeArguments::argv_offset();
+  const intptr_t retval_offset = target::NativeArguments::retval_offset();
 
-  __ movq(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::call_to_runtime_stub_offset()));
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   {
@@ -72,23 +70,30 @@
   __ movq(Assembler::VMTagAddress(), RBX);
 
   // Reserve space for arguments and align frame before entering C++ world.
-  __ subq(RSP, Immediate(sizeof(NativeArguments)));
+  __ subq(RSP, Immediate(target::NativeArguments::StructSize()));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
-  // Pass NativeArguments structure by value and call runtime.
+  // Pass target::NativeArguments structure by value and call runtime.
   __ movq(Address(RSP, thread_offset), THR);  // Set thread in NativeArgs.
   // There are no runtime calls to closures, so we do not need to set the tag
   // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_.
-  __ movq(Address(RSP, argc_tag_offset), R10);  // Set argc in NativeArguments.
+  __ movq(Address(RSP, argc_tag_offset),
+          R10);  // Set argc in target::NativeArguments.
   // Compute argv.
-  __ leaq(RAX, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
-  __ movq(Address(RSP, argv_offset), RAX);    // Set argv in NativeArguments.
-  __ addq(RAX, Immediate(1 * kWordSize));     // Retval is next to 1st argument.
-  __ movq(Address(RSP, retval_offset), RAX);  // Set retval in NativeArguments.
+  __ leaq(RAX,
+          Address(RBP, R10, TIMES_8,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
+  __ movq(Address(RSP, argv_offset),
+          RAX);  // Set argv in target::NativeArguments.
+  __ addq(RAX,
+          Immediate(1 * target::kWordSize));  // Retval is next to 1st argument.
+  __ movq(Address(RSP, retval_offset),
+          RAX);  // Set retval in target::NativeArguments.
 #if defined(_WIN64)
-  ASSERT(sizeof(NativeArguments) > CallingConventions::kRegisterTransferLimit);
+  ASSERT(target::NativeArguments::StructSize() >
+         CallingConventions::kRegisterTransferLimit);
   __ movq(CallingConventions::kArg1Reg, RSP);
 #endif
   __ CallCFunction(RBX);
@@ -97,12 +102,13 @@
   __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   // Restore the global object pool after returning from runtime (old space is
   // moving, so the GOP could have been relocated).
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ movq(PP, Address(THR, target::Thread::global_object_pool_offset()));
   }
 
   __ LeaveStubFrame();
@@ -116,11 +122,12 @@
   __ ret();
 }
 
-void StubCode::GenerateSharedStub(Assembler* assembler,
-                                  bool save_fpu_registers,
-                                  const RuntimeEntry* target,
-                                  intptr_t self_code_stub_offset_from_thread,
-                                  bool allow_return) {
+void StubCodeCompiler::GenerateSharedStub(
+    Assembler* assembler,
+    bool save_fpu_registers,
+    const RuntimeEntry* target,
+    intptr_t self_code_stub_offset_from_thread,
+    bool allow_return) {
   // We want the saved registers to appear like part of the caller's frame, so
   // we push them before calling EnterStubFrame.
   __ PushRegisters(kDartAvailableCpuRegs,
@@ -130,14 +137,15 @@
       Utils::CountOneBitsWord(kDartAvailableCpuRegs);
 
   const intptr_t kSavedFpuRegisterSlots =
-      save_fpu_registers ? kNumberOfFpuRegisters * kFpuRegisterSize / kWordSize
-                         : 0;
+      save_fpu_registers
+          ? kNumberOfFpuRegisters * kFpuRegisterSize / target::kWordSize
+          : 0;
 
   const intptr_t kAllSavedRegistersSlots =
       kSavedCpuRegisterSlots + kSavedFpuRegisterSlots;
 
   // Copy down the return address so the stack layout is correct.
-  __ pushq(Address(RSP, kAllSavedRegistersSlots * kWordSize));
+  __ pushq(Address(RSP, kAllSavedRegistersSlots * target::kWordSize));
 
   __ movq(CODE_REG, Address(THR, self_code_stub_offset_from_thread));
 
@@ -161,26 +169,18 @@
 
 // RBX: The extracted method.
 // RDX: The type_arguments_field_offset (or 0)
-void StubCode::GenerateBuildMethodExtractorStub(Assembler* assembler) {
-  Thread* thread = Thread::Current();
-  Zone* Z = thread->zone();
-  ObjectStore* object_store = thread->isolate()->object_store();
-
-  const auto& closure_class =
-      Class::ZoneHandle(Z, object_store->closure_class());
-  const auto& closure_allocation_stub =
-      Code::ZoneHandle(Z, StubCode::GetAllocationStubForClass(closure_class));
-
+void StubCodeCompiler::GenerateBuildMethodExtractorStub(
+    Assembler* assembler,
+    const Object& closure_allocation_stub,
+    const Object& context_allocation_stub) {
   const intptr_t kReceiverOffsetInWords =
       compiler::target::frame_layout.param_end_from_fp + 1;
 
-  const auto& context_allocation_stub = StubCode::AllocateContext();
-
   __ EnterStubFrame();
 
   // Push type_arguments vector (or null)
   Label no_type_args;
-  __ movq(RCX, Address(THR, Thread::object_null_offset()));
+  __ movq(RCX, Address(THR, target::Thread::object_null_offset()));
   __ cmpq(RDX, Immediate(0));
   __ j(EQUAL, &no_type_args, Assembler::kNearJump);
   __ movq(RAX,
@@ -195,21 +195,22 @@
   // Allocate context.
   {
     Label done, slow_path;
-    __ TryAllocateArray(kContextCid, Context::InstanceSize(1), &slow_path,
-                        Assembler::kFarJump,
+    __ TryAllocateArray(kContextCid, target::Context::InstanceSize(1),
+                        &slow_path, Assembler::kFarJump,
                         RAX,  // instance
                         RSI,  // end address
                         RDI);
-    __ movq(RSI, Address(THR, Thread::object_null_offset()));
-    __ movq(FieldAddress(RAX, Context::parent_offset()), RSI);
-    __ movq(FieldAddress(RAX, Context::num_variables_offset()), Immediate(1));
+    __ movq(RSI, Address(THR, target::Thread::object_null_offset()));
+    __ movq(FieldAddress(RAX, target::Context::parent_offset()), RSI);
+    __ movq(FieldAddress(RAX, target::Context::num_variables_offset()),
+            Immediate(1));
     __ jmp(&done);
 
     __ Bind(&slow_path);
 
     __ LoadImmediate(/*num_vars=*/R10, Immediate(1));
     __ LoadObject(CODE_REG, context_allocation_stub);
-    __ call(FieldAddress(CODE_REG, Code::entry_point_offset()));
+    __ call(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 
     __ Bind(&done);
   }
@@ -217,69 +218,75 @@
   // Store receiver in context
   __ movq(RSI,
           Address(RBP, compiler::target::kWordSize * kReceiverOffsetInWords));
-  __ StoreIntoObject(RAX, FieldAddress(RAX, Context::variable_offset(0)), RSI);
+  __ StoreIntoObject(
+      RAX, FieldAddress(RAX, target::Context::variable_offset(0)), RSI);
 
   // Push context.
   __ pushq(RAX);
 
   // Allocate closure.
   __ LoadObject(CODE_REG, closure_allocation_stub);
-  __ call(FieldAddress(CODE_REG,
-                       Code::entry_point_offset(Code::EntryKind::kUnchecked)));
+  __ call(FieldAddress(
+      CODE_REG, target::Code::entry_point_offset(CodeEntryKind::kUnchecked)));
 
   // Populate closure object.
   __ popq(RCX);  // Pop context.
-  __ StoreIntoObject(RAX, FieldAddress(RAX, Closure::context_offset()), RCX);
+  __ StoreIntoObject(RAX, FieldAddress(RAX, target::Closure::context_offset()),
+                     RCX);
   __ popq(RCX);  // Pop extracted method.
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, Closure::function_offset()), RCX);
+      RAX, FieldAddress(RAX, target::Closure::function_offset()), RCX);
   __ popq(RCX);  // Pop type argument vector.
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, Closure::instantiator_type_arguments_offset()),
+      RAX,
+      FieldAddress(RAX, target::Closure::instantiator_type_arguments_offset()),
       RCX);
-  __ LoadObject(RCX, Object::empty_type_arguments());
+  __ LoadObject(RCX, EmptyTypeArguments());
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, Closure::delayed_type_arguments_offset()), RCX);
+      RAX, FieldAddress(RAX, target::Closure::delayed_type_arguments_offset()),
+      RCX);
 
   __ LeaveStubFrame();
   __ Ret();
 }
 
-void StubCode::GenerateNullErrorSharedWithoutFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/false,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_without_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithoutFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/false, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_without_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateNullErrorSharedWithFPURegsStub(Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kNullErrorRuntimeEntry,
-                     Thread::null_error_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/false);
+void StubCodeCompiler::GenerateNullErrorSharedWithFPURegsStub(
+    Assembler* assembler) {
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kNullErrorRuntimeEntry,
+      target::Thread::null_error_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/false);
 }
 
-void StubCode::GenerateStackOverflowSharedWithoutFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithoutFPURegsStub(
     Assembler* assembler) {
   GenerateSharedStub(
       assembler, /*save_fpu_registers=*/false, &kStackOverflowRuntimeEntry,
-      Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
+      target::Thread::stack_overflow_shared_without_fpu_regs_stub_offset(),
       /*allow_return=*/true);
 }
 
-void StubCode::GenerateStackOverflowSharedWithFPURegsStub(
+void StubCodeCompiler::GenerateStackOverflowSharedWithFPURegsStub(
     Assembler* assembler) {
-  GenerateSharedStub(assembler, /*save_fpu_registers=*/true,
-                     &kStackOverflowRuntimeEntry,
-                     Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
-                     /*allow_return=*/true);
+  GenerateSharedStub(
+      assembler, /*save_fpu_registers=*/true, &kStackOverflowRuntimeEntry,
+      target::Thread::stack_overflow_shared_with_fpu_regs_stub_offset(),
+      /*allow_return=*/true);
 }
 
 // Input parameters:
 //   RSP : points to return address.
 //   RDI : stop message (const char*).
 // Must preserve all registers.
-void StubCode::GeneratePrintStopMessageStub(Assembler* assembler) {
+void StubCodeCompiler::GeneratePrintStopMessageStub(Assembler* assembler) {
   __ EnterCallRuntimeFrame(0);
 // Call the runtime leaf function. RDI already contains the parameter.
 #if defined(_WIN64)
@@ -300,19 +307,19 @@
                                               Address wrapper_address) {
   const intptr_t native_args_struct_offset = 0;
   const intptr_t thread_offset =
-      NativeArguments::thread_offset() + native_args_struct_offset;
+      target::NativeArguments::thread_offset() + native_args_struct_offset;
   const intptr_t argc_tag_offset =
-      NativeArguments::argc_tag_offset() + native_args_struct_offset;
+      target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
   const intptr_t argv_offset =
-      NativeArguments::argv_offset() + native_args_struct_offset;
+      target::NativeArguments::argv_offset() + native_args_struct_offset;
   const intptr_t retval_offset =
-      NativeArguments::retval_offset() + native_args_struct_offset;
+      target::NativeArguments::retval_offset() + native_args_struct_offset;
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   {
@@ -332,19 +339,23 @@
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // RDI) and align frame before entering the C++ world.
-  __ subq(RSP, Immediate(sizeof(NativeArguments)));
+  __ subq(RSP, Immediate(target::NativeArguments::StructSize()));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
-  // Pass NativeArguments structure by value and call native function.
-  __ movq(Address(RSP, thread_offset), THR);    // Set thread in NativeArgs.
-  __ movq(Address(RSP, argc_tag_offset), R10);  // Set argc in NativeArguments.
-  __ movq(Address(RSP, argv_offset), RAX);      // Set argv in NativeArguments.
-  __ leaq(RAX, Address(RBP, 2 * kWordSize));    // Compute return value addr.
-  __ movq(Address(RSP, retval_offset), RAX);  // Set retval in NativeArguments.
+  // Pass target::NativeArguments structure by value and call native function.
+  __ movq(Address(RSP, thread_offset), THR);  // Set thread in NativeArgs.
+  __ movq(Address(RSP, argc_tag_offset),
+          R10);  // Set argc in target::NativeArguments.
+  __ movq(Address(RSP, argv_offset),
+          RAX);  // Set argv in target::NativeArguments.
+  __ leaq(RAX,
+          Address(RBP, 2 * target::kWordSize));  // Compute return value addr.
+  __ movq(Address(RSP, retval_offset),
+          RAX);  // Set retval in target::NativeArguments.
 
-  // Pass the pointer to the NativeArguments.
+  // Pass the pointer to the target::NativeArguments.
   __ movq(CallingConventions::kArg1Reg, RSP);
   // Pass pointer to function entrypoint.
   __ movq(CallingConventions::kArg2Reg, RBX);
@@ -356,22 +367,25 @@
   __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
 }
 
-void StubCode::GenerateCallNoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallNoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::no_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::no_scope_native_wrapper_entry_point_offset()));
 }
 
-void StubCode::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallAutoScopeNativeStub(Assembler* assembler) {
   GenerateCallNativeWithWrapperStub(
       assembler,
-      Address(THR, Thread::auto_scope_native_wrapper_entry_point_offset()));
+      Address(THR,
+              target::Thread::auto_scope_native_wrapper_entry_point_offset()));
 }
 
 // Input parameters:
@@ -380,22 +394,22 @@
 //   RAX : address of first argument in argument array.
 //   RBX : address of the native function to call.
 //   R10 : argc_tag including number of arguments and function kind.
-void StubCode::GenerateCallBootstrapNativeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallBootstrapNativeStub(Assembler* assembler) {
   const intptr_t native_args_struct_offset = 0;
   const intptr_t thread_offset =
-      NativeArguments::thread_offset() + native_args_struct_offset;
+      target::NativeArguments::thread_offset() + native_args_struct_offset;
   const intptr_t argc_tag_offset =
-      NativeArguments::argc_tag_offset() + native_args_struct_offset;
+      target::NativeArguments::argc_tag_offset() + native_args_struct_offset;
   const intptr_t argv_offset =
-      NativeArguments::argv_offset() + native_args_struct_offset;
+      target::NativeArguments::argv_offset() + native_args_struct_offset;
   const intptr_t retval_offset =
-      NativeArguments::retval_offset() + native_args_struct_offset;
+      target::NativeArguments::retval_offset() + native_args_struct_offset;
 
   __ EnterStubFrame();
 
   // Save exit frame information to enable stack walking as we are about
   // to transition to native code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
 
 #if defined(DEBUG)
   {
@@ -415,19 +429,23 @@
   // Reserve space for the native arguments structure passed on the stack (the
   // outgoing pointer parameter to the native arguments structure is passed in
   // RDI) and align frame before entering the C++ world.
-  __ subq(RSP, Immediate(sizeof(NativeArguments)));
+  __ subq(RSP, Immediate(target::NativeArguments::StructSize()));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
-  // Pass NativeArguments structure by value and call native function.
-  __ movq(Address(RSP, thread_offset), THR);    // Set thread in NativeArgs.
-  __ movq(Address(RSP, argc_tag_offset), R10);  // Set argc in NativeArguments.
-  __ movq(Address(RSP, argv_offset), RAX);      // Set argv in NativeArguments.
-  __ leaq(RAX, Address(RBP, 2 * kWordSize));    // Compute return value addr.
-  __ movq(Address(RSP, retval_offset), RAX);  // Set retval in NativeArguments.
+  // Pass target::NativeArguments structure by value and call native function.
+  __ movq(Address(RSP, thread_offset), THR);  // Set thread in NativeArgs.
+  __ movq(Address(RSP, argc_tag_offset),
+          R10);  // Set argc in target::NativeArguments.
+  __ movq(Address(RSP, argv_offset),
+          RAX);  // Set argv in target::NativeArguments.
+  __ leaq(RAX,
+          Address(RBP, 2 * target::kWordSize));  // Compute return value addr.
+  __ movq(Address(RSP, retval_offset),
+          RAX);  // Set retval in target::NativeArguments.
 
-  // Pass the pointer to the NativeArguments.
+  // Pass the pointer to the target::NativeArguments.
   __ movq(CallingConventions::kArg1Reg, RSP);
   __ CallCFunction(RBX);
 
@@ -435,7 +453,8 @@
   __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
@@ -443,7 +462,7 @@
 
 // Input parameters:
 //   R10: arguments descriptor array.
-void StubCode::GenerateCallStaticFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallStaticFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
@@ -454,18 +473,19 @@
   // Remove the stub frame as we are about to jump to the dart function.
   __ LeaveStubFrame();
 
-  __ movq(RBX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(RBX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ jmp(RBX);
 }
 
 // Called from a static call only when an invalid code has been entered
 // (invalid because its function was optimized or deoptimized).
 // R10: arguments descriptor array.
-void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixCallersTargetStub(Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ movq(CODE_REG, Address(THR, Thread::fix_callers_target_code_offset()));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::fix_callers_target_code_offset()));
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   // Setup space on stack for return value.
@@ -473,7 +493,7 @@
   __ CallRuntime(kFixCallersTargetRuntimeEntry, 0);
   __ popq(CODE_REG);  // Get Code object.
   __ popq(R10);       // Restore arguments descriptor array.
-  __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ LeaveStubFrame();
   __ jmp(RAX);
   __ int3();
@@ -481,17 +501,19 @@
 
 // Called from object allocate instruction when the allocation stub has been
 // disabled.
-void StubCode::GenerateFixAllocationStubTargetStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFixAllocationStubTargetStub(
+    Assembler* assembler) {
   // Load code pointer to this stub from the thread:
   // The one that is passed in, is not correct - it points to the code object
   // that needs to be replaced.
-  __ movq(CODE_REG, Address(THR, Thread::fix_allocation_stub_code_offset()));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::fix_allocation_stub_code_offset()));
   __ EnterStubFrame();
   // Setup space on stack for return value.
   __ pushq(Immediate(0));
   __ CallRuntime(kFixAllocationStubTargetRuntimeEntry, 0);
   __ popq(CODE_REG);  // Get Code object.
-  __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ LeaveStubFrame();
   __ jmp(RAX);
   __ int3();
@@ -499,18 +521,20 @@
 
 // Input parameters:
 //   R10: smi-tagged argument count, may be zero.
-//   RBP[kParamEndSlotFromFp + 1]: last argument.
+//   RBP[target::frame_layout.param_end_from_fp + 1]: last argument.
 static void PushArrayOfArguments(Assembler* assembler) {
-  __ LoadObject(R12, Object::null_object());
+  __ LoadObject(R12, NullObject());
   // Allocate array to store arguments of caller.
   __ movq(RBX, R12);  // Null element type for raw Array.
-  __ Call(StubCode::AllocateArray());
+  __ Call(StubCodeAllocateArray());
   __ SmiUntag(R10);
   // RAX: newly allocated array.
   // R10: length of the array (was preserved by the stub).
   __ pushq(RAX);  // Array is in RAX and on top of stack.
-  __ leaq(R12, Address(RBP, R10, TIMES_8, kParamEndSlotFromFp * kWordSize));
-  __ leaq(RBX, FieldAddress(RAX, Array::data_offset()));
+  __ leaq(R12,
+          Address(RBP, R10, TIMES_8,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
+  __ leaq(RBX, FieldAddress(RAX, target::Array::data_offset()));
   // R12: address of first argument on stack.
   // RBX: address of first argument in array.
   Label loop, loop_condition;
@@ -524,8 +548,8 @@
   __ movq(RDI, Address(R12, 0));
   // Generational barrier is needed, array is not necessarily in new space.
   __ StoreIntoObject(RAX, Address(RBX, 0), RDI);
-  __ addq(RBX, Immediate(kWordSize));
-  __ subq(R12, Immediate(kWordSize));
+  __ addq(RBX, Immediate(target::kWordSize));
+  __ subq(R12, Immediate(target::kWordSize));
   __ Bind(&loop_condition);
   __ decq(R10);
   __ j(POSITIVE, &loop, Assembler::kNearJump);
@@ -582,7 +606,7 @@
     if (i == CODE_REG) {
       // Save the original value of CODE_REG pushed before invoking this stub
       // instead of the value used to call this stub.
-      __ pushq(Address(RBP, 2 * kWordSize));
+      __ pushq(Address(RBP, 2 * target::kWordSize));
     } else {
       __ pushq(static_cast<Register>(i));
     }
@@ -606,11 +630,13 @@
 
   if (kind == kLazyDeoptFromReturn) {
     // Restore result into RBX temporarily.
-    __ movq(RBX, Address(RBP, saved_result_slot_from_fp * kWordSize));
+    __ movq(RBX, Address(RBP, saved_result_slot_from_fp * target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore result into RBX temporarily.
-    __ movq(RBX, Address(RBP, saved_exception_slot_from_fp * kWordSize));
-    __ movq(RDX, Address(RBP, saved_stacktrace_slot_from_fp * kWordSize));
+    __ movq(RBX,
+            Address(RBP, saved_exception_slot_from_fp * target::kWordSize));
+    __ movq(RDX,
+            Address(RBP, saved_stacktrace_slot_from_fp * target::kWordSize));
   }
 
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -640,17 +666,17 @@
     // Restore result into RBX.
     __ movq(RBX,
             Address(RBP, compiler::target::frame_layout.first_local_from_fp *
-                             kWordSize));
+                             target::kWordSize));
   } else if (kind == kLazyDeoptFromThrow) {
     // Restore exception into RBX.
     __ movq(RBX,
             Address(RBP, compiler::target::frame_layout.first_local_from_fp *
-                             kWordSize));
+                             target::kWordSize));
     // Restore stacktrace into RDX.
     __ movq(
         RDX,
         Address(RBP, (compiler::target::frame_layout.first_local_from_fp - 1) *
-                         kWordSize));
+                         target::kWordSize));
   }
   // Code above cannot cause GC.
   // There is a Dart Frame on the stack. We must restore PP and leave frame.
@@ -668,7 +694,7 @@
     __ pushq(RBX);  // Preserve exception.
     __ pushq(RDX);  // Preserve stacktrace.
   }
-  __ pushq(Immediate(Smi::RawValue(0)));  // Space for the result.
+  __ pushq(Immediate(target::ToRawSmi(0)));  // Space for the result.
   __ CallRuntime(kDeoptimizeMaterializeRuntimeEntry, 0);
   // Result tells stub how many bytes to remove from the expression stack
   // of the bottom-most frame. They were used as materialization arguments.
@@ -689,33 +715,37 @@
 }
 
 // RAX: result, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromReturnStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ pushq(Immediate(kZapCodeReg));
   // Return address for "call" to deopt stub.
   __ pushq(Immediate(kZapReturnAddress));
-  __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_return_stub_offset()));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::lazy_deopt_from_return_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromReturn);
   __ ret();
 }
 
 // RAX: exception, must be preserved
 // RDX: stacktrace, must be preserved
-void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeLazyFromThrowStub(
+    Assembler* assembler) {
   // Push zap value instead of CODE_REG for lazy deopt.
   __ pushq(Immediate(kZapCodeReg));
   // Return address for "call" to deopt stub.
   __ pushq(Immediate(kZapReturnAddress));
-  __ movq(CODE_REG, Address(THR, Thread::lazy_deopt_from_throw_stub_offset()));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::lazy_deopt_from_throw_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kLazyDeoptFromThrow);
   __ ret();
 }
 
-void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptimizeStub(Assembler* assembler) {
   __ popq(TMP);
   __ pushq(CODE_REG);
   __ pushq(TMP);
-  __ movq(CODE_REG, Address(THR, Thread::deoptimize_stub_offset()));
+  __ movq(CODE_REG, Address(THR, target::Thread::deoptimize_stub_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
   __ ret();
 }
@@ -725,25 +755,27 @@
   __ Comment("NoSuchMethodDispatch");
   // When lazily generated invocation dispatchers are disabled, the
   // miss-handler may return null.
-  __ CompareObject(RAX, Object::null_object());
+  __ CompareObject(RAX, NullObject());
   __ j(NOT_EQUAL, call_target_function);
   __ EnterStubFrame();
   // Load the receiver.
-  __ movq(RDI, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ movq(RAX, Address(RBP, RDI, TIMES_HALF_WORD_SIZE,
-                       kParamEndSlotFromFp * kWordSize));
+  __ movq(RDI, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+  __ movq(RAX,
+          Address(RBP, RDI, TIMES_HALF_WORD_SIZE,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
   __ pushq(Immediate(0));  // Setup space on stack for result.
   __ pushq(RAX);           // Receiver.
   __ pushq(RBX);           // ICData/MegamorphicCache.
   __ pushq(R10);           // Arguments descriptor array.
 
   // Adjust arguments count.
-  __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ cmpq(
+      FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   __ movq(R10, RDI);
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addq(R10, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addq(R10, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
 
   // R10: Smi-tagged arguments array length.
@@ -756,16 +788,16 @@
   __ ret();
 }
 
-void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicMissStub(Assembler* assembler) {
   __ EnterStubFrame();
   // Load the receiver into RAX.  The argument count in the arguments
   // descriptor in R10 is a smi.
-  __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  __ movq(RAX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
   // Three words (saved pp, saved fp, stub's pc marker)
   // in the stack above the return address.
-  __ movq(RAX,
-          Address(RSP, RAX, TIMES_4,
-                  compiler::target::frame_layout.saved_below_pc() * kWordSize));
+  __ movq(RAX, Address(RSP, RAX, TIMES_4,
+                       compiler::target::frame_layout.saved_below_pc() *
+                           target::kWordSize));
   // Preserve IC data and arguments descriptor.
   __ pushq(RBX);
   __ pushq(R10);
@@ -790,8 +822,8 @@
     GenerateDispatcherCode(assembler, &call_target_function);
     __ Bind(&call_target_function);
   }
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RCX);
 }
 
@@ -801,11 +833,12 @@
 //   RBX : array element type (either NULL or an instantiated type).
 // NOTE: R10 cannot be clobbered here as the caller relies on it being saved.
 // The newly allocated object is returned in RAX.
-void StubCode::GenerateAllocateArrayStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAllocateArrayStub(Assembler* assembler) {
   Label slow_case;
   // Compute the size to be allocated, it is based on the array length
   // and is computed as:
-  // RoundedAllocationSize((array_length * kwordSize) + sizeof(RawArray)).
+  // RoundedAllocationSize(
+  //     (array_length * target::kwordSize) + target::Array::header_size()).
   __ movq(RDI, R10);  // Array Length.
   // Check that length is a positive Smi.
   __ testq(RDI, Immediate(kSmiTagMask));
@@ -817,8 +850,8 @@
   __ cmpq(RDI, Immediate(0));
   __ j(LESS, &slow_case);
   // Check for maximum allowed length.
-  const Immediate& max_len = Immediate(
-      reinterpret_cast<int64_t>(Smi::New(Array::kMaxNewSpaceElements)));
+  const Immediate& max_len =
+      Immediate(target::ToRawSmi(target::Array::kMaxNewSpaceElements));
   __ cmpq(RDI, max_len);
   __ j(GREATER, &slow_case);
 
@@ -827,14 +860,15 @@
       __ MaybeTraceAllocation(kArrayCid, &slow_case, Assembler::kFarJump));
 
   const intptr_t fixed_size_plus_alignment_padding =
-      sizeof(RawArray) + kObjectAlignment - 1;
+      target::Array::header_size() + target::ObjectAlignment::kObjectAlignment -
+      1;
   // RDI is a Smi.
   __ leaq(RDI, Address(RDI, TIMES_4, fixed_size_plus_alignment_padding));
   ASSERT(kSmiTagShift == 1);
-  __ andq(RDI, Immediate(-kObjectAlignment));
+  __ andq(RDI, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
   const intptr_t cid = kArrayCid;
-  __ movq(RAX, Address(THR, Thread::top_offset()));
+  __ movq(RAX, Address(THR, target::Thread::top_offset()));
 
   // RDI: allocation size.
   __ movq(RCX, RAX);
@@ -845,12 +879,12 @@
   // RAX: potential new object start.
   // RCX: potential next object start.
   // RDI: allocation size.
-  __ cmpq(RCX, Address(THR, Thread::end_offset()));
+  __ cmpq(RCX, Address(THR, target::Thread::end_offset()));
   __ j(ABOVE_EQUAL, &slow_case);
 
   // Successfully allocated the object(s), now update top to point to
   // next object start and initialize the object.
-  __ movq(Address(THR, Thread::top_offset()), RCX);
+  __ movq(Address(THR, target::Thread::top_offset()), RCX);
   __ addq(RAX, Immediate(kHeapObjectTag));
   NOT_IN_PRODUCT(__ UpdateAllocationStatsWithSize(cid, RDI));
   // Initialize the tags.
@@ -858,9 +892,10 @@
   // RDI: allocation size.
   {
     Label size_tag_overflow, done;
-    __ cmpq(RDI, Immediate(RawObject::SizeTag::kMaxSizeTag));
+    __ cmpq(RDI, Immediate(target::RawObject::kSizeTagMaxSizeTag));
     __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-    __ shlq(RDI, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+    __ shlq(RDI, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                           target::ObjectAlignment::kObjectAlignmentLog2));
     __ jmp(&done, Assembler::kNearJump);
 
     __ Bind(&size_tag_overflow);
@@ -868,30 +903,28 @@
     __ Bind(&done);
 
     // Get the class index and insert it into the tags.
-    uint32_t tags = 0;
-    tags = RawObject::ClassIdTag::update(cid, tags);
-    tags = RawObject::NewBit::update(true, tags);
+    uint32_t tags = target::MakeTagWordForNewSpaceObject(cid, 0);
     __ orq(RDI, Immediate(tags));
-    __ movq(FieldAddress(RAX, Array::tags_offset()), RDI);  // Tags.
+    __ movq(FieldAddress(RAX, target::Array::tags_offset()), RDI);  // Tags.
   }
 
   // RAX: new object start as a tagged pointer.
   // Store the type argument field.
   // No generational barrier needed, since we store into a new object.
   __ StoreIntoObjectNoBarrier(
-      RAX, FieldAddress(RAX, Array::type_arguments_offset()), RBX);
+      RAX, FieldAddress(RAX, target::Array::type_arguments_offset()), RBX);
 
   // Set the length field.
-  __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, Array::length_offset()),
-                              R10);
+  __ StoreIntoObjectNoBarrier(
+      RAX, FieldAddress(RAX, target::Array::length_offset()), R10);
 
   // Initialize all array elements to raw_null.
   // RAX: new object start as a tagged pointer.
   // RCX: new object end address.
   // RDI: iterator which initially points to the start of the variable
   // data area to be initialized.
-  __ LoadObject(R12, Object::null_object());
-  __ leaq(RDI, FieldAddress(RAX, sizeof(RawArray)));
+  __ LoadObject(R12, NullObject());
+  __ leaq(RDI, FieldAddress(RAX, target::Array::header_size()));
   Label done;
   Label init_loop;
   __ Bind(&init_loop);
@@ -904,7 +937,7 @@
   __ j(ABOVE_EQUAL, &done, kJumpLength);
   // No generational barrier needed, since we are storing null.
   __ StoreIntoObjectNoBarrier(RAX, Address(RDI, 0), R12);
-  __ addq(RDI, Immediate(kWordSize));
+  __ addq(RDI, Immediate(target::kWordSize));
   __ jmp(&init_loop, kJumpLength);
   __ Bind(&done);
   __ ret();  // returns the newly allocated object in RAX.
@@ -934,7 +967,7 @@
 //   RSI : arguments descriptor array.
 //   RDX : arguments array.
 //   RCX : current thread.
-void StubCode::GenerateInvokeDartCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeStub(Assembler* assembler) {
   __ pushq(Address(RSP, 0));  // Marker for the profiler.
   __ EnterFrame(0);
 
@@ -944,7 +977,7 @@
   const Register kThreadReg = CallingConventions::kArg4Reg;
 
   // Push code object to PC marker slot.
-  __ pushq(Address(kThreadReg, Thread::invoke_dart_code_stub_offset()));
+  __ pushq(Address(kThreadReg, target::Thread::invoke_dart_code_stub_offset()));
 
   // At this point, the stack looks like:
   // | stub code object
@@ -953,7 +986,7 @@
 
   const intptr_t kInitialOffset = 2;
   // Save arguments descriptor array, later replaced by Smi argument count.
-  const intptr_t kArgumentsDescOffset = -(kInitialOffset)*kWordSize;
+  const intptr_t kArgumentsDescOffset = -(kInitialOffset)*target::kWordSize;
   __ pushq(kArgDescReg);
 
   // Save C++ ABI callee-saved registers.
@@ -961,7 +994,7 @@
                    CallingConventions::kCalleeSaveXmmRegisters);
 
   // If any additional (or fewer) values are pushed, the offsets in
-  // kExitLinkSlotFromEntryFp will need to be changed.
+  // target::frame_layout.exit_link_slot_from_entry_fp will need to be changed.
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != kThreadReg) {
@@ -974,26 +1007,29 @@
 
   // Save top resource and top exit frame info. Use RAX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ movq(RAX, Address(THR, Thread::top_resource_offset()));
+  __ movq(RAX, Address(THR, target::Thread::top_resource_offset()));
   __ pushq(RAX);
-  __ movq(Address(THR, Thread::top_resource_offset()), Immediate(0));
-  __ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset()));
+  __ movq(Address(THR, target::Thread::top_resource_offset()), Immediate(0));
+  __ movq(RAX, Address(THR, target::Thread::top_exit_frame_info_offset()));
   __ pushq(RAX);
 
-// The constant kExitLinkSlotFromEntryFp must be kept in sync with the
-// code below.
+  // The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
+  // in sync with the code below.
 #if defined(DEBUG)
   {
     Label ok;
-    __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize));
+    __ leaq(RAX,
+            Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
     __ cmpq(RAX, RSP);
     __ j(EQUAL, &ok);
-    __ Stop("kExitLinkSlotFromEntryFp mismatch");
+    __ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
     __ Bind(&ok);
   }
 #endif
 
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   // Mark that the thread is executing Dart code. Do this after initializing the
   // exit link for the profiler.
@@ -1006,12 +1042,13 @@
   ASSERT(kTargetCodeReg != RDX);
 
   // Load number of arguments into RBX and adjust count for type arguments.
-  __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ movq(RBX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+  __ cmpq(
+      FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addq(RBX, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addq(RBX, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
   // Save number of arguments as Smi on stack, replacing saved ArgumentsDesc.
   __ movq(Address(RBP, kArgumentsDescOffset), RBX);
@@ -1019,7 +1056,7 @@
 
   // Compute address of 'arguments array' data area into RDX.
   __ movq(RDX, Address(kArgsReg, VMHandles::kOffsetOfRawPtrInHandle));
-  __ leaq(RDX, FieldAddress(RDX, Array::data_offset()));
+  __ leaq(RDX, FieldAddress(RDX, target::Array::data_offset()));
 
   // Set up arguments for the Dart call.
   Label push_arguments;
@@ -1035,13 +1072,14 @@
 
   // Call the Dart code entrypoint.
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ movq(PP, Address(THR, target::Thread::global_object_pool_offset()));
   } else {
     __ xorq(PP, PP);  // GC-safe value into PP.
   }
   __ movq(CODE_REG,
           Address(kTargetCodeReg, VMHandles::kOffsetOfRawPtrInHandle));
-  __ movq(kTargetCodeReg, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(kTargetCodeReg,
+          FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ call(kTargetCodeReg);  // R10 is the arguments descriptor array.
 
   // Read the saved number of passed arguments as Smi.
@@ -1052,8 +1090,8 @@
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure.
-  __ popq(Address(THR, Thread::top_exit_frame_info_offset()));
-  __ popq(Address(THR, Thread::top_resource_offset()));
+  __ popq(Address(THR, target::Thread::top_exit_frame_info_offset()));
+  __ popq(Address(THR, target::Thread::top_resource_offset()));
 
   // Restore the current VMTag from the stack.
   __ popq(Assembler::VMTagAddress());
@@ -1077,7 +1115,8 @@
 //   RSI : arguments raw descriptor array.
 //   RDX : address of first argument.
 //   RCX : current thread.
-void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInvokeDartCodeFromBytecodeStub(
+    Assembler* assembler) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   __ Stop("Not using interpreter");
 #else
@@ -1090,8 +1129,9 @@
   const Register kThreadReg = CallingConventions::kArg4Reg;
 
   // Push code object to PC marker slot.
-  __ pushq(Address(kThreadReg,
-                   Thread::invoke_dart_code_from_bytecode_stub_offset()));
+  __ pushq(
+      Address(kThreadReg,
+              target::Thread::invoke_dart_code_from_bytecode_stub_offset()));
 
   // At this point, the stack looks like:
   // | stub code object
@@ -1100,7 +1140,7 @@
 
   const intptr_t kInitialOffset = 2;
   // Save arguments descriptor array, later replaced by Smi argument count.
-  const intptr_t kArgumentsDescOffset = -(kInitialOffset)*kWordSize;
+  const intptr_t kArgumentsDescOffset = -(kInitialOffset)*target::kWordSize;
   __ pushq(kArgDescReg);
 
   // Save C++ ABI callee-saved registers.
@@ -1108,7 +1148,7 @@
                    CallingConventions::kCalleeSaveXmmRegisters);
 
   // If any additional (or fewer) values are pushed, the offsets in
-  // kExitLinkSlotFromEntryFp will need to be changed.
+  // target::frame_layout.exit_link_slot_from_entry_fp will need to be changed.
 
   // Set up THR, which caches the current thread in Dart code.
   if (THR != kThreadReg) {
@@ -1121,22 +1161,25 @@
 
   // Save top resource and top exit frame info. Use RAX as a temporary register.
   // StackFrameIterator reads the top exit frame info saved in this frame.
-  __ movq(RAX, Address(THR, Thread::top_resource_offset()));
+  __ movq(RAX, Address(THR, target::Thread::top_resource_offset()));
   __ pushq(RAX);
-  __ movq(Address(THR, Thread::top_resource_offset()), Immediate(0));
-  __ movq(RAX, Address(THR, Thread::top_exit_frame_info_offset()));
+  __ movq(Address(THR, target::Thread::top_resource_offset()), Immediate(0));
+  __ movq(RAX, Address(THR, target::Thread::top_exit_frame_info_offset()));
   __ pushq(RAX);
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
-// The constant kExitLinkSlotFromEntryFp must be kept in sync with the
-// code below.
+  // The constant target::frame_layout.exit_link_slot_from_entry_fp must be kept
+  // in sync with the code below.
 #if defined(DEBUG)
   {
     Label ok;
-    __ leaq(RAX, Address(RBP, kExitLinkSlotFromEntryFp * kWordSize));
+    __ leaq(RAX,
+            Address(RBP, target::frame_layout.exit_link_slot_from_entry_fp *
+                             target::kWordSize));
     __ cmpq(RAX, RSP);
     __ j(EQUAL, &ok);
-    __ Stop("kExitLinkSlotFromEntryFp mismatch");
+    __ Stop("target::frame_layout.exit_link_slot_from_entry_fp mismatch");
     __ Bind(&ok);
   }
 #endif
@@ -1152,12 +1195,13 @@
   ASSERT(kTargetCodeReg != RDX);
 
   // Load number of arguments into RBX and adjust count for type arguments.
-  __ movq(RBX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ movq(RBX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+  __ cmpq(
+      FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addq(RBX, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addq(RBX, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
   // Save number of arguments as Smi on stack, replacing saved ArgumentsDesc.
   __ movq(Address(RBP, kArgumentsDescOffset), RBX);
@@ -1183,7 +1227,8 @@
   // Call the Dart code entrypoint.
   __ xorq(PP, PP);  // GC-safe value into PP.
   __ movq(CODE_REG, kTargetCodeReg);
-  __ movq(kTargetCodeReg, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(kTargetCodeReg,
+          FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ call(kTargetCodeReg);  // R10 is the arguments descriptor array.
 
   // Read the saved number of passed arguments as Smi.
@@ -1194,8 +1239,8 @@
 
   // Restore the saved top exit frame info and top resource back into the
   // Isolate structure.
-  __ popq(Address(THR, Thread::top_exit_frame_info_offset()));
-  __ popq(Address(THR, Thread::top_resource_offset()));
+  __ popq(Address(THR, target::Thread::top_exit_frame_info_offset()));
+  __ popq(Address(THR, target::Thread::top_resource_offset()));
 
   // Restore the current VMTag from the stack.
   __ popq(Assembler::VMTagAddress());
@@ -1218,16 +1263,17 @@
 // R10: number of context variables.
 // Output:
 // RAX: new allocated RawContext object.
-void StubCode::GenerateAllocateContextStub(Assembler* assembler) {
-  __ LoadObject(R9, Object::null_object());
+void StubCodeCompiler::GenerateAllocateContextStub(Assembler* assembler) {
+  __ LoadObject(R9, NullObject());
   if (FLAG_inline_alloc) {
     Label slow_case;
     // First compute the rounded instance size.
     // R10: number of context variables.
     intptr_t fixed_size_plus_alignment_padding =
-        (sizeof(RawContext) + kObjectAlignment - 1);
+        (target::Context::header_size() +
+         target::ObjectAlignment::kObjectAlignment - 1);
     __ leaq(R13, Address(R10, TIMES_8, fixed_size_plus_alignment_padding));
-    __ andq(R13, Immediate(-kObjectAlignment));
+    __ andq(R13, Immediate(-target::ObjectAlignment::kObjectAlignment));
 
     // Check for allocation tracing.
     NOT_IN_PRODUCT(
@@ -1236,13 +1282,13 @@
     // Now allocate the object.
     // R10: number of context variables.
     const intptr_t cid = kContextCid;
-    __ movq(RAX, Address(THR, Thread::top_offset()));
+    __ movq(RAX, Address(THR, target::Thread::top_offset()));
     __ addq(R13, RAX);
     // Check if the allocation fits into the remaining space.
     // RAX: potential new object.
     // R13: potential next object start.
     // R10: number of context variables.
-    __ cmpq(R13, Address(THR, Thread::end_offset()));
+    __ cmpq(R13, Address(THR, target::Thread::end_offset()));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
@@ -1254,7 +1300,7 @@
     // RAX: new object.
     // R13: next object start.
     // R10: number of context variables.
-    __ movq(Address(THR, Thread::top_offset()), R13);
+    __ movq(Address(THR, target::Thread::top_offset()), R13);
     // R13: Size of allocation in bytes.
     __ subq(R13, RAX);
     __ addq(RAX, Immediate(kHeapObjectTag));
@@ -1267,10 +1313,11 @@
     {
       Label size_tag_overflow, done;
       __ leaq(R13, Address(R10, TIMES_8, fixed_size_plus_alignment_padding));
-      __ andq(R13, Immediate(-kObjectAlignment));
-      __ cmpq(R13, Immediate(RawObject::SizeTag::kMaxSizeTag));
+      __ andq(R13, Immediate(-target::ObjectAlignment::kObjectAlignment));
+      __ cmpq(R13, Immediate(target::RawObject::kSizeTagMaxSizeTag));
       __ j(ABOVE, &size_tag_overflow, Assembler::kNearJump);
-      __ shlq(R13, Immediate(RawObject::kSizeTagPos - kObjectAlignmentLog2));
+      __ shlq(R13, Immediate(target::RawObject::kTagBitsSizeTagPos -
+                             target::ObjectAlignment::kObjectAlignmentLog2));
       __ jmp(&done);
 
       __ Bind(&size_tag_overflow);
@@ -1281,31 +1328,29 @@
       // RAX: new object.
       // R10: number of context variables.
       // R13: size and bit tags.
-      uint32_t tags = 0;
-      tags = RawObject::ClassIdTag::update(cid, tags);
-      tags = RawObject::NewBit::update(true, tags);
+      uint32_t tags = target::MakeTagWordForNewSpaceObject(cid, 0);
       __ orq(R13, Immediate(tags));
-      __ movq(FieldAddress(RAX, Context::tags_offset()), R13);  // Tags.
+      __ movq(FieldAddress(RAX, target::Object::tags_offset()), R13);  // Tags.
     }
 
     // Setup up number of context variables field.
     // RAX: new object.
     // R10: number of context variables as integer value (not object).
-    __ movq(FieldAddress(RAX, Context::num_variables_offset()), R10);
+    __ movq(FieldAddress(RAX, target::Context::num_variables_offset()), R10);
 
     // Setup the parent field.
     // RAX: new object.
     // R10: number of context variables.
     // No generational barrier needed, since we are storing null.
     __ StoreIntoObjectNoBarrier(
-        RAX, FieldAddress(RAX, Context::parent_offset()), R9);
+        RAX, FieldAddress(RAX, target::Context::parent_offset()), R9);
 
     // Initialize the context variables.
     // RAX: new object.
     // R10: number of context variables.
     {
       Label loop, entry;
-      __ leaq(R13, FieldAddress(RAX, Context::variable_offset(0)));
+      __ leaq(R13, FieldAddress(RAX, target::Context::variable_offset(0)));
 #if defined(DEBUG)
       static const bool kJumpLength = Assembler::kFarJump;
 #else
@@ -1341,7 +1386,7 @@
   __ ret();
 }
 
-void StubCode::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierWrappersStub(Assembler* assembler) {
   for (intptr_t i = 0; i < kNumberOfCpuRegisters; ++i) {
     if ((kDartAvailableCpuRegs & (1 << i)) == 0) continue;
 
@@ -1349,7 +1394,7 @@
     intptr_t start = __ CodeSize();
     __ pushq(kWriteBarrierObjectReg);
     __ movq(kWriteBarrierObjectReg, reg);
-    __ call(Address(THR, Thread::write_barrier_entry_point_offset()));
+    __ call(Address(THR, target::Thread::write_barrier_entry_point_offset()));
     __ popq(kWriteBarrierObjectReg);
     __ ret();
     intptr_t end = __ CodeSize();
@@ -1372,18 +1417,18 @@
                                            Address stub_code,
                                            bool cards) {
   Label add_to_mark_stack, remember_card;
-  __ testq(RAX, Immediate(1 << kNewObjectBitPosition));
+  __ testq(RAX, Immediate(1 << target::ObjectAlignment::kNewObjectBitPosition));
   __ j(ZERO, &add_to_mark_stack);
 
   if (cards) {
-    __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
-    __ testl(TMP, Immediate(1 << RawObject::kCardRememberedBit));
+    __ movl(TMP, FieldAddress(RDX, target::Object::tags_offset()));
+    __ testl(TMP, Immediate(1 << target::RawObject::kCardRememberedBit));
     __ j(NOT_ZERO, &remember_card, Assembler::kFarJump);
   } else {
 #if defined(DEBUG)
     Label ok;
-    __ movl(TMP, FieldAddress(RDX, Object::tags_offset()));
-    __ testl(TMP, Immediate(1 << RawObject::kCardRememberedBit));
+    __ movl(TMP, FieldAddress(RDX, target::Object::tags_offset()));
+    __ testl(TMP, Immediate(1 << target::RawObject::kCardRememberedBit));
     __ j(ZERO, &ok, Assembler::kFarJump);
     __ Stop("Wrong barrier");
     __ Bind(&ok);
@@ -1397,8 +1442,8 @@
   // RAX: Current tag value
   // lock+andl is an atomic read-modify-write.
   __ lock();
-  __ andl(FieldAddress(RDX, Object::tags_offset()),
-          Immediate(~(1 << RawObject::kOldAndNotRememberedBit)));
+  __ andl(FieldAddress(RDX, target::Object::tags_offset()),
+          Immediate(~(1 << target::RawObject::kOldAndNotRememberedBit)));
 
   // Save registers being destroyed.
   __ pushq(RAX);
@@ -1407,17 +1452,19 @@
   // Load the StoreBuffer block out of the thread. Then load top_ out of the
   // StoreBufferBlock and add the address to the pointers_.
   // RDX: Address being stored
-  __ movq(RAX, Address(THR, Thread::store_buffer_block_offset()));
-  __ movl(RCX, Address(RAX, StoreBufferBlock::top_offset()));
-  __ movq(Address(RAX, RCX, TIMES_8, StoreBufferBlock::pointers_offset()), RDX);
+  __ movq(RAX, Address(THR, target::Thread::store_buffer_block_offset()));
+  __ movl(RCX, Address(RAX, target::StoreBufferBlock::top_offset()));
+  __ movq(
+      Address(RAX, RCX, TIMES_8, target::StoreBufferBlock::pointers_offset()),
+      RDX);
 
   // Increment top_ and check for overflow.
   // RCX: top_
   // RAX: StoreBufferBlock
   Label overflow;
   __ incq(RCX);
-  __ movl(Address(RAX, StoreBufferBlock::top_offset()), RCX);
-  __ cmpl(RCX, Immediate(StoreBufferBlock::kSize));
+  __ movl(Address(RAX, target::StoreBufferBlock::top_offset()), RCX);
+  __ cmpl(RCX, Immediate(target::StoreBufferBlock::kSize));
   // Restore values.
   __ popq(RCX);
   __ popq(RAX);
@@ -1437,30 +1484,31 @@
   __ ret();
 
   __ Bind(&add_to_mark_stack);
-  __ pushq(RAX);  // Spill.
-  __ pushq(RCX);  // Spill.
+  __ pushq(RAX);      // Spill.
+  __ pushq(RCX);      // Spill.
   __ movq(TMP, RAX);  // RAX is fixed implicit operand of CAS.
 
   // Atomically clear kOldAndNotMarkedBit.
   // Note that we use 32 bit operations here to match the size of the
   // background marker which is also manipulating this 32 bit word.
   Label retry, lost_race, marking_overflow;
-  __ movl(RAX, FieldAddress(TMP, Object::tags_offset()));
+  __ movl(RAX, FieldAddress(TMP, target::Object::tags_offset()));
   __ Bind(&retry);
   __ movl(RCX, RAX);
-  __ testl(RCX, Immediate(1 << RawObject::kOldAndNotMarkedBit));
+  __ testl(RCX, Immediate(1 << target::RawObject::kOldAndNotMarkedBit));
   __ j(ZERO, &lost_race);  // Marked by another thread.
-  __ andl(RCX, Immediate(~(1 << RawObject::kOldAndNotMarkedBit)));
-  __ LockCmpxchgl(FieldAddress(TMP, Object::tags_offset()), RCX);
+  __ andl(RCX, Immediate(~(1 << target::RawObject::kOldAndNotMarkedBit)));
+  __ LockCmpxchgl(FieldAddress(TMP, target::Object::tags_offset()), RCX);
   __ j(NOT_EQUAL, &retry, Assembler::kNearJump);
 
-  __ movq(RAX, Address(THR, Thread::marking_stack_block_offset()));
-  __ movl(RCX, Address(RAX, MarkingStackBlock::top_offset()));
-  __ movq(Address(RAX, RCX, TIMES_8, MarkingStackBlock::pointers_offset()),
-          TMP);
+  __ movq(RAX, Address(THR, target::Thread::marking_stack_block_offset()));
+  __ movl(RCX, Address(RAX, target::MarkingStackBlock::top_offset()));
+  __ movq(
+      Address(RAX, RCX, TIMES_8, target::MarkingStackBlock::pointers_offset()),
+      TMP);
   __ incq(RCX);
-  __ movl(Address(RAX, MarkingStackBlock::top_offset()), RCX);
-  __ cmpl(RCX, Immediate(MarkingStackBlock::kSize));
+  __ movl(Address(RAX, target::MarkingStackBlock::top_offset()), RCX);
+  __ cmpl(RCX, Immediate(target::MarkingStackBlock::kSize));
   __ popq(RCX);  // Unspill.
   __ popq(RAX);  // Unspill.
   __ j(EQUAL, &marking_overflow, Assembler::kNearJump);
@@ -1486,16 +1534,19 @@
 
     // Get card table.
     __ Bind(&remember_card);
-    __ movq(TMP, RDX);                   // Object.
-    __ andq(TMP, Immediate(kPageMask));  // HeapPage.
-    __ cmpq(Address(TMP, HeapPage::card_table_offset()), Immediate(0));
+    __ movq(TMP, RDX);                           // Object.
+    __ andq(TMP, Immediate(target::kPageMask));  // HeapPage.
+    __ cmpq(Address(TMP, target::HeapPage::card_table_offset()), Immediate(0));
     __ j(EQUAL, &remember_card_slow, Assembler::kNearJump);
 
     // Dirty the card.
     __ subq(R13, TMP);  // Offset in page.
-    __ movq(TMP, Address(TMP, HeapPage::card_table_offset()));  // Card table.
+    __ movq(
+        TMP,
+        Address(TMP, target::HeapPage::card_table_offset()));  // Card table.
     __ shrq(R13,
-            Immediate(HeapPage::kBytesPerCardLog2));  // Index in card table.
+            Immediate(
+                target::HeapPage::kBytesPerCardLog2));  // Index in card table.
     __ movb(Address(TMP, R13, TIMES_1, 0), Immediate(1));
     __ ret();
 
@@ -1513,70 +1564,70 @@
   }
 }
 
-void StubCode::GenerateWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::write_barrier_code_offset()), false);
+      assembler, Address(THR, target::Thread::write_barrier_code_offset()),
+      false);
 }
 
-void StubCode::GenerateArrayWriteBarrierStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateArrayWriteBarrierStub(Assembler* assembler) {
   GenerateWriteBarrierStubHelper(
-      assembler, Address(THR, Thread::array_write_barrier_code_offset()), true);
+      assembler,
+      Address(THR, target::Thread::array_write_barrier_code_offset()), true);
 }
 
 // Called for inline allocation of objects.
 // Input parameters:
 //   RSP + 8 : type arguments object (only if class is parameterized).
 //   RSP : points to return address.
-void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
-                                              const Class& cls) {
-  const intptr_t kObjectTypeArgumentsOffset = 1 * kWordSize;
+void StubCodeCompiler::GenerateAllocationStubForClass(Assembler* assembler,
+                                                      const Class& cls) {
+  const intptr_t kObjectTypeArgumentsOffset = 1 * target::kWordSize;
   // The generated code is different if the class is parameterized.
-  const bool is_cls_parameterized = cls.NumTypeArguments() > 0;
-  ASSERT(!is_cls_parameterized ||
-         (cls.type_arguments_field_offset() != Class::kNoTypeArguments));
+  const bool is_cls_parameterized = target::Class::NumTypeArguments(cls) > 0;
+  ASSERT(!is_cls_parameterized || target::Class::TypeArgumentsFieldOffset(
+                                      cls) != target::Class::kNoTypeArguments);
   // kInlineInstanceSize is a constant used as a threshold for determining
   // when the object initialization should be done as a loop or as
   // straight line code.
   const int kInlineInstanceSize = 12;  // In words.
-  const intptr_t instance_size = cls.instance_size();
+  const intptr_t instance_size = target::Class::InstanceSize(cls);
   ASSERT(instance_size > 0);
-  __ LoadObject(R9, Object::null_object());
+  __ LoadObject(R9, NullObject());
   if (is_cls_parameterized) {
     __ movq(RDX, Address(RSP, kObjectTypeArgumentsOffset));
     // RDX: instantiated type arguments.
   }
-  Isolate* isolate = Isolate::Current();
-  if (FLAG_inline_alloc && Heap::IsAllocatableInNewSpace(instance_size) &&
-      !cls.TraceAllocation(isolate)) {
+  if (FLAG_inline_alloc &&
+      target::Heap::IsAllocatableInNewSpace(instance_size) &&
+      !target::Class::TraceAllocation(cls)) {
     Label slow_case;
     // Allocate the object and update top to point to
     // next object start and initialize the allocated object.
     // RDX: instantiated type arguments (if is_cls_parameterized).
-    __ movq(RAX, Address(THR, Thread::top_offset()));
+    __ movq(RAX, Address(THR, target::Thread::top_offset()));
     __ leaq(RBX, Address(RAX, instance_size));
     // Check if the allocation fits into the remaining space.
     // RAX: potential new object start.
     // RBX: potential next object start.
-    __ cmpq(RBX, Address(THR, Thread::end_offset()));
+    __ cmpq(RBX, Address(THR, target::Thread::end_offset()));
     if (FLAG_use_slow_path) {
       __ jmp(&slow_case);
     } else {
       __ j(ABOVE_EQUAL, &slow_case);
     }
-    __ movq(Address(THR, Thread::top_offset()), RBX);
-    NOT_IN_PRODUCT(__ UpdateAllocationStats(cls.id()));
+    __ movq(Address(THR, target::Thread::top_offset()), RBX);
+    NOT_IN_PRODUCT(__ UpdateAllocationStats(target::Class::GetId(cls)));
 
     // RAX: new object start (untagged).
     // RBX: next object start.
     // RDX: new object type arguments (if is_cls_parameterized).
     // Set the tags.
-    uint32_t tags = 0;
-    tags = RawObject::SizeTag::update(instance_size, tags);
-    ASSERT(cls.id() != kIllegalCid);
-    tags = RawObject::ClassIdTag::update(cls.id(), tags);
-    tags = RawObject::NewBit::update(true, tags);
+    ASSERT(target::Class::GetId(cls) != kIllegalCid);
+    const uint32_t tags = target::MakeTagWordForNewSpaceObject(
+        target::Class::GetId(cls), instance_size);
     // 64 bit store also zeros the identity hash field.
-    __ movq(Address(RAX, Instance::tags_offset()), Immediate(tags));
+    __ movq(Address(RAX, target::Object::tags_offset()), Immediate(tags));
     __ addq(RAX, Immediate(kHeapObjectTag));
 
     // Initialize the remaining words of the object.
@@ -1585,15 +1636,16 @@
     // RDX: new object type arguments (if is_cls_parameterized).
     // R9: raw null.
     // First try inlining the initialization without a loop.
-    if (instance_size < (kInlineInstanceSize * kWordSize)) {
+    if (instance_size < (kInlineInstanceSize * target::kWordSize)) {
       // Check if the object contains any non-header fields.
       // Small objects are initialized using a consecutive set of writes.
-      for (intptr_t current_offset = Instance::NextFieldOffset();
-           current_offset < instance_size; current_offset += kWordSize) {
+      for (intptr_t current_offset = target::Instance::first_field_offset();
+           current_offset < instance_size;
+           current_offset += target::kWordSize) {
         __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, current_offset), R9);
       }
     } else {
-      __ leaq(RCX, FieldAddress(RAX, Instance::NextFieldOffset()));
+      __ leaq(RCX, FieldAddress(RAX, target::Instance::first_field_offset()));
       // Loop until the whole object is initialized.
       // RAX: new object (tagged).
       // RBX: next object start.
@@ -1610,7 +1662,7 @@
 #endif  // DEBUG
       __ j(ABOVE_EQUAL, &done, kJumpLength);
       __ StoreIntoObjectNoBarrier(RAX, Address(RCX, 0), R9);
-      __ addq(RCX, Immediate(kWordSize));
+      __ addq(RCX, Immediate(target::kWordSize));
       __ jmp(&init_loop, Assembler::kNearJump);
       __ Bind(&done);
     }
@@ -1618,7 +1670,7 @@
       // RAX: new object (tagged).
       // RDX: new object type arguments.
       // Set the type arguments in the new object.
-      intptr_t offset = cls.type_arguments_field_offset();
+      const intptr_t offset = target::Class::TypeArgumentsFieldOffset(cls);
       __ StoreIntoObjectNoBarrier(RAX, FieldAddress(RAX, offset), RDX);
     }
     // Done allocating and initializing the instance.
@@ -1632,7 +1684,8 @@
   // Create a stub frame.
   __ EnterStubFrame();  // Uses PP to access class object.
   __ pushq(R9);         // Setup space on stack for return value.
-  __ PushObject(cls);   // Push class of object to be allocated.
+  __ PushObject(
+      CastHandle<Object>(cls));  // Push class of object to be allocated.
   if (is_cls_parameterized) {
     __ pushq(RDX);  // Push type arguments of object to be allocated.
   } else {
@@ -1655,24 +1708,28 @@
 //   RSP : points to return address.
 //   RSP + 8 : address of last argument.
 //   R10 : arguments descriptor array.
-void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateCallClosureNoSuchMethodStub(
+    Assembler* assembler) {
   __ EnterStubFrame();
 
   // Load the receiver.
-  __ movq(R13, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
-  __ movq(RAX, Address(RBP, R13, TIMES_4, kParamEndSlotFromFp * kWordSize));
+  __ movq(R13, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
+  __ movq(RAX,
+          Address(RBP, R13, TIMES_4,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
 
   __ pushq(Immediate(0));  // Result slot.
   __ pushq(RAX);           // Receiver.
   __ pushq(R10);           // Arguments descriptor array.
 
   // Adjust arguments count.
-  __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ cmpq(
+      FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   __ movq(R10, R13);
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
-  __ addq(R10, Immediate(Smi::RawValue(1)));  // Include the type arguments.
+  __ addq(R10, Immediate(target::ToRawSmi(1)));  // Include the type arguments.
   __ Bind(&args_count_ok);
 
   // R10: Smi-tagged arguments array length.
@@ -1686,7 +1743,8 @@
 
 // Cannot use function object from ICData as it may be the inlined
 // function and not the top-scope function.
-void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizedUsageCounterIncrement(
+    Assembler* assembler) {
   Register ic_reg = RBX;
   Register func_reg = RDI;
   if (FLAG_trace_optimized_ic_calls) {
@@ -1702,19 +1760,19 @@
     __ popq(func_reg);  // Restore.
     __ LeaveStubFrame();
   }
-  __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
+  __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
 }
 
 // Loads function into 'temp_reg', preserves 'ic_reg'.
-void StubCode::GenerateUsageCounterIncrement(Assembler* assembler,
-                                             Register temp_reg) {
+void StubCodeCompiler::GenerateUsageCounterIncrement(Assembler* assembler,
+                                                     Register temp_reg) {
   if (FLAG_optimization_counter_threshold >= 0) {
     Register ic_reg = RBX;
     Register func_reg = temp_reg;
     ASSERT(ic_reg != func_reg);
     __ Comment("Increment function counter");
-    __ movq(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
-    __ incl(FieldAddress(func_reg, Function::usage_counter_offset()));
+    __ movq(func_reg, FieldAddress(ic_reg, target::ICData::owner_offset()));
+    __ incl(FieldAddress(func_reg, target::Function::usage_counter_offset()));
   }
 }
 
@@ -1728,8 +1786,8 @@
                           Label* not_smi_or_overflow) {
   __ Comment("Fast Smi op");
   ASSERT(num_args == 2);
-  __ movq(RCX, Address(RSP, +1 * kWordSize));  // Right
-  __ movq(RAX, Address(RSP, +2 * kWordSize));  // Left.
+  __ movq(RCX, Address(RSP, +1 * target::kWordSize));  // Right
+  __ movq(RAX, Address(RSP, +2 * target::kWordSize));  // Left.
   __ movq(R13, RCX);
   __ orq(R13, RAX);
   __ testq(R13, Immediate(kSmiTagMask));
@@ -1749,10 +1807,10 @@
       Label done, is_true;
       __ cmpq(RAX, RCX);
       __ j(EQUAL, &is_true, Assembler::kNearJump);
-      __ LoadObject(RAX, Bool::False());
+      __ LoadObject(RAX, CastHandle<Object>(FalseObject()));
       __ jmp(&done, Assembler::kNearJump);
       __ Bind(&is_true);
-      __ LoadObject(RAX, Bool::True());
+      __ LoadObject(RAX, CastHandle<Object>(TrueObject()));
       __ Bind(&done);
       break;
     }
@@ -1761,18 +1819,17 @@
   }
 
   // RBX: IC data object (preserved).
-  __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
+  __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
   // R13: ic_data_array with check entries: classes and target functions.
-  __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+  __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
 // R13: points directly to the first ic data array element.
 #if defined(DEBUG)
   // Check that first entry is for Smi/Smi.
   Label error, ok;
-  const Immediate& imm_smi_cid =
-      Immediate(reinterpret_cast<intptr_t>(Smi::New(kSmiCid)));
-  __ cmpq(Address(R13, 0 * kWordSize), imm_smi_cid);
+  const Immediate& imm_smi_cid = Immediate(target::ToRawSmi(kSmiCid));
+  __ cmpq(Address(R13, 0 * target::kWordSize), imm_smi_cid);
   __ j(NOT_EQUAL, &error, Assembler::kNearJump);
-  __ cmpq(Address(R13, 1 * kWordSize), imm_smi_cid);
+  __ cmpq(Address(R13, 1 * target::kWordSize), imm_smi_cid);
   __ j(EQUAL, &ok, Assembler::kNearJump);
   __ Bind(&error);
   __ Stop("Incorrect IC data");
@@ -1780,9 +1837,10 @@
 #endif
 
   if (FLAG_optimization_counter_threshold >= 0) {
-    const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+    const intptr_t count_offset =
+        target::ICData::CountIndexFor(num_args) * target::kWordSize;
     // Update counter, ignore overflow.
-    __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1)));
+    __ addq(Address(R13, count_offset), Immediate(target::ToRawSmi(1)));
   }
 
   __ ret();
@@ -1798,7 +1856,7 @@
 // - Check if 'num_args' (including receiver) match any IC data group.
 // - Match found -> jump to target.
 // - Match not found -> jump to IC miss.
-void StubCode::GenerateNArgsCheckInlineCacheStub(
+void StubCodeCompiler::GenerateNArgsCheckInlineCacheStub(
     Assembler* assembler,
     intptr_t num_args,
     const RuntimeEntry& handle_ic_miss,
@@ -1811,9 +1869,9 @@
     Label ok;
     // Check that the IC data array has NumArgsTested() == num_args.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
+    __ movl(RCX, FieldAddress(RBX, target::ICData::state_bits_offset()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andq(RCX, Immediate(target::ICData::NumArgsTestedMask()));
     __ cmpq(RCX, Immediate(num_args));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect stub for IC data");
@@ -1826,7 +1884,7 @@
   if (!optimized) {
     __ Comment("Check single stepping");
     __ LoadIsolate(RAX);
-    __ cmpb(Address(RAX, Isolate::single_step_offset()), Immediate(0));
+    __ cmpb(Address(RAX, target::Isolate::single_step_offset()), Immediate(0));
     __ j(NOT_EQUAL, &stepping);
     __ Bind(&done_stepping);
   }
@@ -1840,24 +1898,25 @@
 
   __ Comment("Extract ICData initial values and receiver cid");
   // Load arguments descriptor into R10.
-  __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
+  __ 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, ICData::ic_data_offset()));
+  __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
   // R13: ic_data_array with check entries: classes and target functions.
-  __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+  __ 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, ArgumentsDescriptor::count_offset()));
+  __ 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, -kWordSize));
+    __ movq(R9, Address(RSP, RCX, TIMES_4, -target::kWordSize));
     __ LoadTaggedClassIdMayBeSmi(RCX, R9);
     // RCX: second argument class ID (smi).
   }
@@ -1866,10 +1925,12 @@
 
   // We unroll the generic one that is generated once more than the others.
   const bool optimize = kind == Token::kILLEGAL;
-  const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(num_args) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(num_args) * target::kWordSize;
   const intptr_t exactness_offset =
-      ICData::ExactnessOffsetFor(num_args) * kWordSize;
+      target::ICData::ExactnessOffsetFor(num_args) * target::kWordSize;
 
   __ Bind(&loop);
   for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
@@ -1878,7 +1939,7 @@
     __ cmpq(RAX, R9);  // Class id match?
     if (num_args == 2) {
       __ j(NOT_EQUAL, &update);  // Continue.
-      __ movq(R9, Address(R13, kWordSize));
+      __ movq(R9, Address(R13, target::kWordSize));
       // R9: next class ID to check (smi).
       __ cmpq(RCX, R9);  // Class id match?
     }
@@ -1887,10 +1948,11 @@
     __ Bind(&update);
 
     const intptr_t entry_size =
-        ICData::TestEntryLengthFor(num_args, exactness_check) * kWordSize;
+        target::ICData::TestEntryLengthFor(num_args, exactness_check) *
+        target::kWordSize;
     __ addq(R13, Immediate(entry_size));  // Next entry.
 
-    __ cmpq(R9, Immediate(Smi::RawValue(kIllegalCid)));  // Done?
+    __ cmpq(R9, Immediate(target::ToRawSmi(kIllegalCid)));  // Done?
     if (unroll == 0) {
       __ j(NOT_EQUAL, &loop);
     } else {
@@ -1902,7 +1964,7 @@
   __ Comment("IC miss");
   // Compute address of arguments (first read number of arguments from
   // arguments descriptor array and then compute address on the stack).
-  __ movq(RAX, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  __ movq(RAX, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
   __ leaq(RAX, Address(RSP, RAX, TIMES_4, 0));  // RAX is Smi.
   __ EnterStubFrame();
   __ pushq(R10);           // Preserve arguments descriptor array.
@@ -1910,7 +1972,7 @@
   __ pushq(Immediate(0));  // Result slot.
   // Push call arguments.
   for (intptr_t i = 0; i < num_args; i++) {
-    __ movq(RCX, Address(RAX, -kWordSize * i));
+    __ movq(RCX, Address(RAX, -target::kWordSize * i));
     __ pushq(RCX);
   }
   __ pushq(RBX);  // Pass IC data object.
@@ -1938,7 +2000,7 @@
     Label exactness_ok;
     ASSERT(num_args == 1);
     __ movq(RAX, Address(R13, exactness_offset));
-    __ cmpq(RAX, Immediate(Smi::RawValue(
+    __ cmpq(RAX, Immediate(target::ToRawSmi(
                      StaticTypeExactnessState::HasExactSuperType().Encode())));
     __ j(LESS, &exactness_ok);
     __ j(EQUAL, &call_target_function_through_unchecked_entry);
@@ -1946,8 +2008,9 @@
     // Check trivial exactness.
     // Note: RawICData::static_receiver_type_ is guaranteed to be not null
     // because we only emit calls to this stub when it is not null.
-    __ movq(RCX, FieldAddress(RBX, ICData::static_receiver_type_offset()));
-    __ movq(RCX, FieldAddress(RCX, Type::arguments_offset()));
+    __ movq(RCX,
+            FieldAddress(RBX, target::ICData::static_receiver_type_offset()));
+    __ movq(RCX, FieldAddress(RCX, target::Type::arguments_offset()));
     // RAX contains an offset to type arguments in words as a smi,
     // hence TIMES_4. RDX is guaranteed to be non-smi because it is expected to
     // have type arguments.
@@ -1956,8 +2019,8 @@
 
     // Update exactness state (not-exact anymore).
     __ movq(Address(R13, exactness_offset),
-            Immediate(
-                Smi::RawValue(StaticTypeExactnessState::NotExact().Encode())));
+            Immediate(target::ToRawSmi(
+                StaticTypeExactnessState::NotExact().Encode())));
     __ Bind(&exactness_ok);
   }
   __ movq(RAX, Address(R13, target_offset));
@@ -1965,14 +2028,14 @@
   if (FLAG_optimization_counter_threshold >= 0) {
     __ Comment("Update ICData counter");
     // Ignore overflow.
-    __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1)));
+    __ addq(Address(R13, count_offset), Immediate(target::ToRawSmi(1)));
   }
 
   __ Comment("Call target (via checked entry point)");
   __ Bind(&call_target_function);
   // RAX: Target function.
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RCX);
 
   if (exactness_check) {
@@ -1980,12 +2043,13 @@
     if (FLAG_optimization_counter_threshold >= 0) {
       __ Comment("Update ICData counter");
       // Ignore overflow.
-      __ addq(Address(R13, count_offset), Immediate(Smi::RawValue(1)));
+      __ addq(Address(R13, count_offset), Immediate(target::ToRawSmi(1)));
     }
     __ Comment("Call target (via unchecked entry point)");
     __ movq(RAX, Address(R13, target_offset));
-    __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-    __ movq(RCX, FieldAddress(RAX, Function::unchecked_entry_point_offset()));
+    __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+    __ movq(RCX, FieldAddress(
+                     RAX, target::Function::unchecked_entry_point_offset()));
     __ jmp(RCX);
   }
 
@@ -2013,13 +2077,14 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
+void StubCodeCompiler::GenerateOneArgCheckInlineCacheWithExactnessCheckStub(
     Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
@@ -2027,26 +2092,27 @@
       /*optimized=*/false, /*exactness_check=*/true);
 }
 
-void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsCheckInlineCacheStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
                                     kInlineCacheMissHandlerTwoArgsRuntimeEntry,
                                     Token::kILLEGAL);
 }
 
-void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
 }
 
-void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
 }
 
-void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
@@ -2063,7 +2129,7 @@
 // 2 .. (length - 1): group of checks, each check containing:
 //   - N classes.
 //   - 1 target function.
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateOneArgOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
@@ -2071,8 +2137,9 @@
                                     Token::kILLEGAL, /*optimized=*/true);
 }
 
-void StubCode::GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
-    Assembler* assembler) {
+void StubCodeCompiler::
+    GenerateOneArgOptimizedCheckInlineCacheWithExactnessCheckStub(
+        Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 1,
                                     kInlineCacheMissHandlerOneArgRuntimeEntry,
@@ -2080,7 +2147,7 @@
                                     /*exactness_check=*/true);
 }
 
-void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
+void StubCodeCompiler::GenerateTwoArgsOptimizedCheckInlineCacheStub(
     Assembler* assembler) {
   GenerateOptimizedUsageCounterIncrement(assembler);
   GenerateNArgsCheckInlineCacheStub(assembler, 2,
@@ -2091,16 +2158,17 @@
 // Intermediary stub between a static call and its target. ICData contains
 // the target function and the call count.
 // RBX: ICData
-void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateZeroArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
 #if defined(DEBUG)
   {
     Label ok;
     // Check that the IC data array has NumArgsTested() == 0.
     // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
-    __ movl(RCX, FieldAddress(RBX, ICData::state_bits_offset()));
-    ASSERT(ICData::NumArgsTestedShift() == 0);  // No shift needed.
-    __ andq(RCX, Immediate(ICData::NumArgsTestedMask()));
+    __ movl(RCX, FieldAddress(RBX, target::ICData::state_bits_offset()));
+    ASSERT(target::ICData::NumArgsTestedShift() == 0);  // No shift needed.
+    __ andq(RCX, Immediate(target::ICData::NumArgsTestedMask()));
     __ cmpq(RCX, Immediate(0));
     __ j(EQUAL, &ok, Assembler::kNearJump);
     __ Stop("Incorrect IC data for unoptimized static call");
@@ -2112,7 +2180,7 @@
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(RAX);
-  __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
+  __ movzxb(RAX, Address(RAX, target::Isolate::single_step_offset()));
   __ cmpq(RAX, Immediate(0));
 #if defined(DEBUG)
   static const bool kJumpLength = Assembler::kFarJump;
@@ -2124,25 +2192,28 @@
 #endif
 
   // RBX: IC data object (preserved).
-  __ movq(R12, FieldAddress(RBX, ICData::ic_data_offset()));
+  __ movq(R12, FieldAddress(RBX, target::ICData::entries_offset()));
   // R12: ic_data_array with entries: target functions and count.
-  __ leaq(R12, FieldAddress(R12, Array::data_offset()));
+  __ leaq(R12, FieldAddress(R12, target::Array::data_offset()));
   // R12: points directly to the first ic data array element.
-  const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
-  const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(0) * target::kWordSize;
+  const intptr_t count_offset =
+      target::ICData::CountIndexFor(0) * target::kWordSize;
 
   if (FLAG_optimization_counter_threshold >= 0) {
     // Increment count for this call, ignore overflow.
-    __ addq(Address(R12, count_offset), Immediate(Smi::RawValue(1)));
+    __ addq(Address(R12, count_offset), Immediate(target::ToRawSmi(1)));
   }
 
   // Load arguments descriptor into R10.
-  __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
+  __ movq(R10,
+          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
 
   // Get function and call it, if possible.
   __ movq(RAX, Address(R12, target_offset));
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RCX);
 
 #if !defined(PRODUCT)
@@ -2157,13 +2228,15 @@
 #endif
 }
 
-void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOneArgUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
 }
 
-void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTwoArgsUnoptimizedStaticCallStub(
+    Assembler* assembler) {
   GenerateUsageCounterIncrement(assembler, RCX);
   GenerateNArgsCheckInlineCacheStub(
       assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
@@ -2172,7 +2245,7 @@
 // Stub for compiling a function and jumping to the compiled code.
 // R10: Arguments descriptor.
 // RAX: Function.
-void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazyCompileStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(R10);  // Preserve arguments descriptor array.
   __ pushq(RAX);  // Pass function.
@@ -2183,15 +2256,15 @@
 
   // When using the interpreter, the function's code may now point to the
   // InterpretCall stub. Make sure RAX, R10, and RBX are preserved.
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RCX);
 }
 
 // Stub for interpreting a function call.
 // R10: Arguments descriptor.
 // RAX: Function.
-void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateInterpretCallStub(Assembler* assembler) {
 #if defined(DART_PRECOMPILED_RUNTIME)
   __ Stop("Not using interpreter");
 #else
@@ -2210,43 +2283,47 @@
 #endif
 
   // Adjust arguments count for type arguments vector.
-  __ movq(R11, FieldAddress(R10, ArgumentsDescriptor::count_offset()));
+  __ movq(R11, FieldAddress(R10, target::ArgumentsDescriptor::count_offset()));
   __ SmiUntag(R11);
-  __ cmpq(FieldAddress(R10, ArgumentsDescriptor::type_args_len_offset()),
-          Immediate(0));
+  __ cmpq(
+      FieldAddress(R10, target::ArgumentsDescriptor::type_args_len_offset()),
+      Immediate(0));
   Label args_count_ok;
   __ j(EQUAL, &args_count_ok, Assembler::kNearJump);
   __ incq(R11);
   __ Bind(&args_count_ok);
 
   // Compute argv.
-  __ leaq(R12, Address(RBP, R11, TIMES_8, kParamEndSlotFromFp * kWordSize));
+  __ leaq(R12,
+          Address(RBP, R11, TIMES_8,
+                  target::frame_layout.param_end_from_fp * target::kWordSize));
 
   // Indicate decreasing memory addresses of arguments with negative argc.
   __ negq(R11);
 
   // Reserve shadow space for args and align frame before entering C++ world.
-  __ subq(RSP, Immediate(5 * kWordSize));
+  __ subq(RSP, Immediate(5 * target::kWordSize));
   if (OS::ActivationFrameAlignment() > 1) {
     __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
   }
 
-  __ movq(CallingConventions::kArg1Reg, RAX);  // Function.
-  __ movq(CallingConventions::kArg2Reg, R10);  // Arguments descriptor.
-  __ movq(CallingConventions::kArg3Reg, R11);  // Negative argc.
-  __ movq(CallingConventions::kArg4Reg, R12);  // Argv.
+  __ movq(CallingConventions::kArg1Reg, RAX);         // Function.
+  __ movq(CallingConventions::kArg2Reg, R10);         // Arguments descriptor.
+  __ movq(CallingConventions::kArg3Reg, R11);         // Negative argc.
+  __ movq(CallingConventions::kArg4Reg, R12);         // Argv.
 
 #if defined(_WIN64)
-  __ movq(Address(RSP, 0 * kWordSize), THR);  // Thread.
+  __ movq(Address(RSP, 0 * target::kWordSize), THR);  // Thread.
 #else
   __ movq(CallingConventions::kArg5Reg, THR);  // Thread.
 #endif
   // Save exit frame information to enable stack walking as we are about
   // to transition to Dart VM C++ code.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()), RBP);
 
   // Mark that the thread is executing VM code.
-  __ movq(RAX, Address(THR, Thread::interpret_call_entry_point_offset()));
+  __ movq(RAX,
+          Address(THR, target::Thread::interpret_call_entry_point_offset()));
   __ movq(Assembler::VMTagAddress(), RAX);
 
   __ call(RAX);
@@ -2255,7 +2332,8 @@
   __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
 
   // Reset exit frame information in Isolate structure.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
 
   __ LeaveStubFrame();
   __ ret();
@@ -2264,7 +2342,7 @@
 
 // RBX: Contains an ICData.
 // TOS(0): return address (Dart code).
-void StubCode::GenerateICCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(RBX);           // Preserve IC data.
   __ pushq(Immediate(0));  // Result slot.
@@ -2273,28 +2351,31 @@
   __ popq(RBX);       // Restore IC data.
   __ LeaveStubFrame();
 
-  __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ jmp(RAX);  // Jump to original stub.
 }
 
 //  TOS(0): return address (Dart code).
-void StubCode::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRuntimeCallBreakpointStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(Immediate(0));  // Result slot.
   __ CallRuntime(kBreakpointRuntimeHandlerRuntimeEntry, 0);
   __ popq(CODE_REG);  // Original stub.
   __ LeaveStubFrame();
 
-  __ movq(RAX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(RAX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ jmp(RAX);  // Jump to original stub.
 }
 
 // Called only from unoptimized code.
-void StubCode::GenerateDebugStepCheckStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDebugStepCheckStub(Assembler* assembler) {
+#if defined(PRODUCT)
+  __ Ret();
+#else
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(RAX);
-  __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
+  __ movzxb(RAX, Address(RAX, target::Isolate::single_step_offset()));
   __ cmpq(RAX, Immediate(0));
   __ j(NOT_EQUAL, &stepping, Assembler::kNearJump);
   __ Bind(&done_stepping);
@@ -2305,6 +2386,7 @@
   __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0);
   __ LeaveStubFrame();
   __ jmp(&done_stepping, Assembler::kNearJump);
+#endif  // defined(PRODUCT)
 }
 
 // Used to check class and type arguments. Arguments passed in registers:
@@ -2335,7 +2417,7 @@
 
   const Register kNullReg = R8;
 
-  __ LoadObject(kNullReg, Object::null_object());
+  __ LoadObject(kNullReg, NullObject());
 
   // Free up these 2 registers to be used for 6-value test.
   if (n >= 6) {
@@ -2345,8 +2427,9 @@
 
   // Loop initialization (moved up here to avoid having all dependent loads
   // after each other).
-  __ movq(RSI, FieldAddress(kCacheReg, SubtypeTestCache::cache_offset()));
-  __ addq(RSI, Immediate(Array::data_offset() - kHeapObjectTag));
+  __ movq(RSI,
+          FieldAddress(kCacheReg, target::SubtypeTestCache::cache_offset()));
+  __ addq(RSI, Immediate(target::Array::data_offset() - kHeapObjectTag));
 
   Label loop, not_closure;
   if (n >= 4) {
@@ -2360,19 +2443,21 @@
   // Closure handling.
   {
     __ movq(kInstanceCidOrFunction,
-            FieldAddress(kInstanceReg, Closure::function_offset()));
+            FieldAddress(kInstanceReg, target::Closure::function_offset()));
     if (n >= 2) {
-      __ movq(kInstanceInstantiatorTypeArgumentsReg,
-              FieldAddress(kInstanceReg,
-                           Closure::instantiator_type_arguments_offset()));
+      __ movq(
+          kInstanceInstantiatorTypeArgumentsReg,
+          FieldAddress(kInstanceReg,
+                       target::Closure::instantiator_type_arguments_offset()));
       if (n >= 6) {
         ASSERT(n == 6);
-        __ movq(kInstanceParentFunctionTypeArgumentsReg,
-                FieldAddress(kInstanceReg,
-                             Closure::function_type_arguments_offset()));
+        __ movq(
+            kInstanceParentFunctionTypeArgumentsReg,
+            FieldAddress(kInstanceReg,
+                         target::Closure::function_type_arguments_offset()));
         __ movq(kInstanceDelayedFunctionTypeArgumentsReg,
                 FieldAddress(kInstanceReg,
-                             Closure::delayed_type_arguments_offset()));
+                             target::Closure::delayed_type_arguments_offset()));
       }
     }
     __ jmp(&loop, Assembler::kNearJump);
@@ -2389,10 +2474,12 @@
       // [LoadClassById] also tags [kInstanceCidOrFunction] as a side-effect.
       __ LoadClassById(RDI, kInstanceCidOrFunction);
       __ movq(kInstanceInstantiatorTypeArgumentsReg, kNullReg);
-      __ movl(RDI,
-              FieldAddress(
-                  RDI, Class::type_arguments_field_offset_in_words_offset()));
-      __ cmpl(RDI, Immediate(Class::kNoTypeArguments));
+      __ movl(
+          RDI,
+          FieldAddress(
+              RDI,
+              target::Class::type_arguments_field_offset_in_words_offset()));
+      __ cmpl(RDI, Immediate(target::Class::kNoTypeArguments));
       __ j(EQUAL, &has_no_type_arguments, Assembler::kNearJump);
       __ movq(kInstanceInstantiatorTypeArgumentsReg,
               FieldAddress(kInstanceReg, RDI, TIMES_8, 0));
@@ -2409,8 +2496,10 @@
 
   // Loop header.
   __ Bind(&loop);
-  __ movq(RDI, Address(RSI, kWordSize *
-                                SubtypeTestCache::kInstanceClassIdOrFunction));
+  __ movq(
+      RDI,
+      Address(RSI, target::kWordSize *
+                       target::SubtypeTestCache::kInstanceClassIdOrFunction));
   __ cmpq(RDI, kNullReg);
   __ j(EQUAL, &not_found, Assembler::kNearJump);
   __ cmpq(RDI, kInstanceCidOrFunction);
@@ -2419,18 +2508,22 @@
   } else {
     __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
     __ cmpq(kInstanceInstantiatorTypeArgumentsReg,
-            Address(RSI, kWordSize * SubtypeTestCache::kInstanceTypeArguments));
+            Address(RSI, target::kWordSize *
+                             target::SubtypeTestCache::kInstanceTypeArguments));
     if (n == 2) {
       __ j(EQUAL, &found, Assembler::kNearJump);
     } else {
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-      __ cmpq(kInstantiatorTypeArgumentsReg,
-              Address(RSI, kWordSize *
-                               SubtypeTestCache::kInstantiatorTypeArguments));
+      __ cmpq(
+          kInstantiatorTypeArgumentsReg,
+          Address(RSI,
+                  target::kWordSize *
+                      target::SubtypeTestCache::kInstantiatorTypeArguments));
       __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
       __ cmpq(
           kFunctionTypeArgumentsReg,
-          Address(RSI, kWordSize * SubtypeTestCache::kFunctionTypeArguments));
+          Address(RSI, target::kWordSize *
+                           target::SubtypeTestCache::kFunctionTypeArguments));
 
       if (n == 4) {
         __ j(EQUAL, &found, Assembler::kNearJump);
@@ -2438,30 +2531,28 @@
         ASSERT(n == 6);
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
 
-        __ cmpq(
-            kInstanceParentFunctionTypeArgumentsReg,
-            Address(
-                RSI,
-                kWordSize *
-                    SubtypeTestCache::kInstanceParentFunctionTypeArguments));
+        __ cmpq(kInstanceParentFunctionTypeArgumentsReg,
+                Address(RSI, target::kWordSize *
+                                 target::SubtypeTestCache::
+                                     kInstanceParentFunctionTypeArguments));
         __ j(NOT_EQUAL, &next_iteration, Assembler::kNearJump);
-        __ cmpq(
-            kInstanceDelayedFunctionTypeArgumentsReg,
-            Address(
-                RSI,
-                kWordSize *
-                    SubtypeTestCache::kInstanceDelayedFunctionTypeArguments));
+        __ cmpq(kInstanceDelayedFunctionTypeArgumentsReg,
+                Address(RSI, target::kWordSize *
+                                 target::SubtypeTestCache::
+                                     kInstanceDelayedFunctionTypeArguments));
         __ j(EQUAL, &found, Assembler::kNearJump);
       }
     }
   }
 
   __ Bind(&next_iteration);
-  __ addq(RSI, Immediate(kWordSize * SubtypeTestCache::kTestEntryLength));
+  __ addq(RSI, Immediate(target::kWordSize *
+                         target::SubtypeTestCache::kTestEntryLength));
   __ jmp(&loop, Assembler::kNearJump);
 
   __ Bind(&found);
-  __ movq(R8, Address(RSI, kWordSize * SubtypeTestCache::kTestResult));
+  __ movq(R8, Address(RSI, target::kWordSize *
+                               target::SubtypeTestCache::kTestResult));
   if (n >= 6) {
     __ popq(kInstanceDelayedFunctionTypeArgumentsReg);
     __ popq(kInstanceParentFunctionTypeArgumentsReg);
@@ -2477,22 +2568,22 @@
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype1TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype1TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 1);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype2TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype2TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 2);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype4TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype4TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 4);
 }
 
 // See comment on [GenerateSubtypeNTestCacheStub].
-void StubCode::GenerateSubtype6TestCacheStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSubtype6TestCacheStub(Assembler* assembler) {
   GenerateSubtypeNTestCacheStub(assembler, 6);
 }
 
@@ -2512,88 +2603,40 @@
 //
 // Note of warning: The caller will not populate CODE_REG and we have therefore
 // no access to the pool.
-void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDefaultTypeTestStub(Assembler* assembler) {
   Label done;
 
   const Register kInstanceReg = RAX;
 
   // Fast case for 'null'.
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
-  __ movq(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ jmp(FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(CODE_REG, Address(THR, target::Thread::slow_type_test_stub_offset()));
+  __ jmp(FieldAddress(CODE_REG, target::Code::entry_point_offset()));
 
   __ Bind(&done);
   __ Ret();
 }
 
-void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTopTypeTypeTestStub(Assembler* assembler) {
   __ Ret();
 }
 
-void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateTypeRefTypeTestStub(Assembler* assembler) {
   const Register kTypeRefReg = RBX;
 
   // We dereference the TypeRef and tail-call to it's type testing stub.
-  __ movq(kTypeRefReg, FieldAddress(kTypeRefReg, TypeRef::type_offset()));
-  __ jmp(FieldAddress(kTypeRefReg,
-                      AbstractType::type_test_stub_entry_point_offset()));
+  __ movq(kTypeRefReg,
+          FieldAddress(kTypeRefReg, target::TypeRef::type_offset()));
+  __ jmp(FieldAddress(
+      kTypeRefReg, target::AbstractType::type_test_stub_entry_point_offset()));
 }
 
-void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnreachableTypeTestStub(Assembler* assembler) {
   __ Breakpoint();
 }
 
-void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const Type& type,
-    const Class& type_class) {
-  const Register kInstanceReg = RAX;
-  const Register kClassIdReg = TMP;
-
-  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
-                                      kInstanceReg, kClassIdReg);
-
-  __ movq(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
-  __ jmp(FieldAddress(CODE_REG, Code::entry_point_offset()));
-}
-
-void TypeTestingStubGenerator::
-    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
-                                                      HierarchyInfo* hi,
-                                                      const Class& type_class,
-                                                      const TypeArguments& tp,
-                                                      const TypeArguments& ta) {
-  const Register kInstanceReg = RAX;
-  const Register kInstanceTypeArguments = RSI;
-  const Register kClassIdReg = TMP;
-
-  BuildOptimizedSubclassRangeCheckWithTypeArguments(
-      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
-      kInstanceTypeArguments);
-}
-
-void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
-    Assembler* assembler,
-    HierarchyInfo* hi,
-    const AbstractType& type_arg,
-    intptr_t type_param_value_offset_i,
-    Label* check_failed) {
-  const Register kInstanceTypeArguments = RSI;
-  const Register kInstantiatorTypeArgumentsReg = RDX;
-  const Register kFunctionTypeArgumentsReg = RCX;
-
-  const Register kClassIdReg = TMP;
-  const Register kOwnTypeArgumentValue = RDI;
-
-  BuildOptimizedTypeArgumentValueCheck(
-      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
-      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
-      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
-}
-
 static void InvokeTypeCheckFromTypeTestStub(Assembler* assembler,
                                             TypeCheckMode mode) {
   const Register kInstanceReg = RAX;
@@ -2602,14 +2645,14 @@
   const Register kDstTypeReg = RBX;
   const Register kSubtypeTestCacheReg = R9;
 
-  __ PushObject(Object::null_object());  // Make room for result.
+  __ PushObject(NullObject());  // Make room for result.
   __ pushq(kInstanceReg);
   __ pushq(kDstTypeReg);
   __ pushq(kInstantiatorTypeArgumentsReg);
   __ pushq(kFunctionTypeArgumentsReg);
-  __ PushObject(Object::null_object());
+  __ PushObject(NullObject());
   __ pushq(kSubtypeTestCacheReg);
-  __ PushObject(Smi::ZoneHandle(Smi::New(mode)));
+  __ PushImmediate(Immediate(target::ToRawSmi(mode)));
   __ CallRuntime(kTypeCheckRuntimeEntry, 7);
   __ Drop(1);
   __ popq(kSubtypeTestCacheReg);
@@ -2621,17 +2664,19 @@
   __ Drop(1);  // Discard return value.
 }
 
-void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateLazySpecializeTypeTestStub(
+    Assembler* assembler) {
   const Register kInstanceReg = RAX;
 
   Label done;
 
   // Fast case for 'null'.
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(EQUAL, &done);
 
-  __ movq(CODE_REG,
-          Address(THR, Thread::lazy_specialize_type_test_stub_offset()));
+  __ movq(
+      CODE_REG,
+      Address(THR, target::Thread::lazy_specialize_type_test_stub_offset()));
   __ EnterStubFrame();
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromLazySpecializeStub);
   __ LeaveStubFrame();
@@ -2640,7 +2685,7 @@
   __ Ret();
 }
 
-void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSlowTypeTestStub(Assembler* assembler) {
   Label done, call_runtime;
 
   const Register kInstanceReg = RAX;
@@ -2652,14 +2697,14 @@
 #ifdef DEBUG
   // Guaranteed by caller.
   Label no_error;
-  __ CompareObject(kInstanceReg, Object::null_object());
+  __ CompareObject(kInstanceReg, NullObject());
   __ BranchIf(NOT_EQUAL, &no_error);
   __ Breakpoint();
   __ Bind(&no_error);
 #endif
 
   // If the subtype-cache is null, it needs to be lazily-created by the runtime.
-  __ CompareObject(kSubtypeTestCacheReg, Object::null_object());
+  __ CompareObject(kSubtypeTestCacheReg, NullObject());
   __ BranchIf(EQUAL, &call_runtime);
 
   const Register kTmp = RDI;
@@ -2671,13 +2716,13 @@
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is instantiated/uninstantiated.
-  __ cmpb(FieldAddress(kDstTypeReg, Type::type_state_offset()),
-          Immediate(RawType::kFinalizedInstantiated));
+  __ cmpb(FieldAddress(kDstTypeReg, target::Type::type_state_offset()),
+          Immediate(target::RawAbstractType::kTypeStateFinalizedInstantiated));
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // Check whether this [Type] is a function type.
-  __ movq(kTmp, FieldAddress(kDstTypeReg, Type::signature_offset()));
-  __ CompareObject(kTmp, Object::null_object());
+  __ movq(kTmp, FieldAddress(kDstTypeReg, target::Type::signature_offset()));
+  __ CompareObject(kTmp, NullObject());
   __ BranchIf(NOT_EQUAL, &is_complex_case);
 
   // This [Type] could be a FutureOr. Subtype2TestCache does not support Smi.
@@ -2687,16 +2732,16 @@
 
   __ Bind(&is_simple_case);
   {
-    __ Call(StubCode::Subtype2TestCache());
-    __ CompareObject(R8, Bool::True());
+    __ Call(StubCodeSubtype2TestCache());
+    __ CompareObject(R8, CastHandle<Object>(TrueObject()));
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     __ Jump(&call_runtime);
   }
 
   __ Bind(&is_complex_case);
   {
-    __ Call(StubCode::Subtype6TestCache());
-    __ CompareObject(R8, Bool::True());
+    __ Call(StubCodeSubtype6TestCache());
+    __ CompareObject(R8, CastHandle<Object>(TrueObject()));
     __ BranchIf(EQUAL, &done);  // Cache said: yes.
     // Fall through to runtime_call
   }
@@ -2708,11 +2753,11 @@
   // because we do constant evaluation with default stubs and only install
   // optimized versions before writing out the AOT snapshot.
   // So dynamic/Object/void will run with default stub in constant evaluation.
-  __ CompareObject(kDstTypeReg, Type::dynamic_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(DynamicType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::Handle(Type::ObjectType()));
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(ObjectType()));
   __ BranchIf(EQUAL, &done);
-  __ CompareObject(kDstTypeReg, Type::void_type());
+  __ CompareObject(kDstTypeReg, CastHandle<Object>(VoidType()));
   __ BranchIf(EQUAL, &done);
 
   InvokeTypeCheckFromTypeTestStub(assembler, kTypeCheckFromSlowStub);
@@ -2726,8 +2771,8 @@
 // checks.
 // TOS + 0: return address
 // Result in RAX.
-void StubCode::GenerateGetCStackPointerStub(Assembler* assembler) {
-  __ leaq(RAX, Address(RSP, kWordSize));
+void StubCodeCompiler::GenerateGetCStackPointerStub(Assembler* assembler) {
+  __ leaq(RAX, Address(RSP, target::kWordSize));
   __ ret();
 }
 
@@ -2738,18 +2783,19 @@
 // Arg3: frame_pointer
 // Arg4: thread
 // No Result.
-void StubCode::GenerateJumpToFrameStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateJumpToFrameStub(Assembler* assembler) {
   __ movq(THR, CallingConventions::kArg4Reg);
   __ movq(RBP, CallingConventions::kArg3Reg);
   __ movq(RSP, CallingConventions::kArg2Reg);
   // Set the tag.
   __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   // Clear top exit frame.
-  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+  __ movq(Address(THR, target::Thread::top_exit_frame_info_offset()),
+          Immediate(0));
   // Restore the pool pointer.
   __ RestoreCodePointer();
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
-    __ movq(PP, Address(THR, Thread::global_object_pool_offset()));
+    __ movq(PP, Address(THR, target::Thread::global_object_pool_offset()));
   } else {
     __ LoadPoolPointer(PP);
   }
@@ -2760,22 +2806,24 @@
 //
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateRunExceptionHandlerStub(Assembler* assembler) {
   ASSERT(kExceptionObjectReg == RAX);
   ASSERT(kStackTraceObjectReg == RDX);
   __ movq(CallingConventions::kArg1Reg,
-          Address(THR, Thread::resume_pc_offset()));
+          Address(THR, target::Thread::resume_pc_offset()));
 
-  ASSERT(Thread::CanLoadFromThread(Object::null_object()));
-  __ movq(TMP, Address(THR, Thread::OffsetFromThread(Object::null_object())));
+  word offset_from_thread = 0;
+  bool ok = target::CanLoadFromThread(NullObject(), &offset_from_thread);
+  ASSERT(ok);
+  __ movq(TMP, Address(THR, offset_from_thread));
 
   // Load the exception from the current thread.
-  Address exception_addr(THR, Thread::active_exception_offset());
+  Address exception_addr(THR, target::Thread::active_exception_offset());
   __ movq(kExceptionObjectReg, exception_addr);
   __ movq(exception_addr, TMP);
 
   // Load the stacktrace from the current thread.
-  Address stacktrace_addr(THR, Thread::active_stacktrace_offset());
+  Address stacktrace_addr(THR, target::Thread::active_stacktrace_offset());
   __ movq(kStackTraceObjectReg, stacktrace_addr);
   __ movq(stacktrace_addr, TMP);
 
@@ -2785,12 +2833,12 @@
 // Deoptimize a frame on the call stack before rewinding.
 // The arguments are stored in the Thread object.
 // No result.
-void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateDeoptForRewindStub(Assembler* assembler) {
   // Push zap value instead of CODE_REG.
   __ pushq(Immediate(kZapCodeReg));
 
   // Push the deopt pc.
-  __ pushq(Address(THR, Thread::resume_pc_offset()));
+  __ pushq(Address(THR, target::Thread::resume_pc_offset()));
   GenerateDeoptimizationSequence(assembler, kEagerDeopt);
 
   // After we have deoptimized, jump to the correct frame.
@@ -2803,7 +2851,7 @@
 // Calls to the runtime to optimize the given function.
 // RDI: function to be reoptimized.
 // R10: argument descriptor (preserved).
-void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateOptimizeFunctionStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(R10);           // Preserve args descriptor.
   __ pushq(Immediate(0));  // Result slot.
@@ -2813,8 +2861,8 @@
   __ popq(RAX);  // Get Code object.
   __ popq(R10);  // Restore argument descriptor.
   __ LeaveStubFrame();
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
   __ jmp(RCX);
   __ int3();
 }
@@ -2841,8 +2889,8 @@
   __ j(NOT_EQUAL, &done, Assembler::kFarJump);
 
   // Double values bitwise compare.
-  __ movq(left, FieldAddress(left, Double::value_offset()));
-  __ cmpq(left, FieldAddress(right, Double::value_offset()));
+  __ movq(left, FieldAddress(left, target::Double::value_offset()));
+  __ cmpq(left, FieldAddress(right, target::Double::value_offset()));
   __ jmp(&done, Assembler::kFarJump);
 
   __ Bind(&check_mint);
@@ -2850,8 +2898,8 @@
   __ j(NOT_EQUAL, &reference_compare, Assembler::kNearJump);
   __ CompareClassId(right, kMintCid);
   __ j(NOT_EQUAL, &done, Assembler::kFarJump);
-  __ movq(left, FieldAddress(left, Mint::value_offset()));
-  __ cmpq(left, FieldAddress(right, Mint::value_offset()));
+  __ movq(left, FieldAddress(left, target::Mint::value_offset()));
+  __ cmpq(left, FieldAddress(right, target::Mint::value_offset()));
   __ jmp(&done, Assembler::kFarJump);
 
   __ Bind(&reference_compare);
@@ -2864,13 +2912,13 @@
 // TOS + 1: right argument.
 // TOS + 2: left argument.
 // Returns ZF set.
-void StubCode::GenerateUnoptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateUnoptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
 #if !defined(PRODUCT)
   // Check single stepping.
   Label stepping, done_stepping;
   __ LoadIsolate(RAX);
-  __ movzxb(RAX, Address(RAX, Isolate::single_step_offset()));
+  __ movzxb(RAX, Address(RAX, target::Isolate::single_step_offset()));
   __ cmpq(RAX, Immediate(0));
   __ j(NOT_EQUAL, &stepping);
   __ Bind(&done_stepping);
@@ -2879,8 +2927,8 @@
   const Register left = RAX;
   const Register right = RDX;
 
-  __ movq(left, Address(RSP, 2 * kWordSize));
-  __ movq(right, Address(RSP, 1 * kWordSize));
+  __ movq(left, Address(RSP, 2 * target::kWordSize));
+  __ movq(right, Address(RSP, 1 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 
@@ -2899,24 +2947,24 @@
 // TOS + 1: right argument.
 // TOS + 2: left argument.
 // Returns ZF set.
-void StubCode::GenerateOptimizedIdenticalWithNumberCheckStub(
+void StubCodeCompiler::GenerateOptimizedIdenticalWithNumberCheckStub(
     Assembler* assembler) {
   const Register left = RAX;
   const Register right = RDX;
 
-  __ movq(left, Address(RSP, 2 * kWordSize));
-  __ movq(right, Address(RSP, 1 * kWordSize));
+  __ movq(left, Address(RSP, 2 * target::kWordSize));
+  __ movq(right, Address(RSP, 1 * target::kWordSize));
   GenerateIdenticalWithNumberCheckStub(assembler, left, right);
   __ ret();
 }
 
 // Called from megamorphic calls.
 //  RDI: receiver
-//  RBX: MegamorphicCache (preserved)
+//  RBX: target::MegamorphicCache (preserved)
 // Passed to target:
 //  CODE_REG: target Code
 //  R10: arguments descriptor
-void StubCode::GenerateMegamorphicCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateMegamorphicCallStub(Assembler* assembler) {
   // Jump if receiver is a smi.
   Label smi_case;
   __ testq(RDI, Immediate(kSmiTagMask));
@@ -2928,8 +2976,8 @@
 
   Label cid_loaded;
   __ Bind(&cid_loaded);
-  __ movq(R9, FieldAddress(RBX, MegamorphicCache::mask_offset()));
-  __ movq(RDI, FieldAddress(RBX, MegamorphicCache::buckets_offset()));
+  __ movq(R9, FieldAddress(RBX, target::MegamorphicCache::mask_offset()));
+  __ movq(RDI, FieldAddress(RBX, target::MegamorphicCache::buckets_offset()));
   // R9: mask as a smi.
   // RDI: cache buckets array.
 
@@ -2937,7 +2985,7 @@
   __ addq(RAX, RAX);
 
   // Compute the table index.
-  ASSERT(MegamorphicCache::kSpreadFactor == 7);
+  ASSERT(target::MegamorphicCache::kSpreadFactor == 7);
   // Use leaq and subq multiply with 7 == 8 - 1.
   __ leaq(RCX, Address(RAX, TIMES_8, 0));
   __ subq(RCX, RAX);
@@ -2946,7 +2994,7 @@
   __ Bind(&loop);
   __ andq(RCX, R9);
 
-  const intptr_t base = Array::data_offset();
+  const intptr_t base = target::Array::data_offset();
   // RCX is smi tagged, but table entries are two words, so TIMES_8.
   Label probe_failed;
   __ cmpq(RAX, FieldAddress(RDI, RCX, TIMES_8, base));
@@ -2958,28 +3006,31 @@
   // proper target for the given name and arguments descriptor.  If the
   // illegal class id was found, the target is a cache miss handler that can
   // be invoked as a normal Dart function.
-  const auto target_address = FieldAddress(RDI, RCX, TIMES_8, base + kWordSize);
+  const auto target_address =
+      FieldAddress(RDI, RCX, TIMES_8, base + target::kWordSize);
   if (FLAG_precompiled_mode && FLAG_use_bare_instructions) {
     __ movq(R10,
-            FieldAddress(RBX, MegamorphicCache::arguments_descriptor_offset()));
+            FieldAddress(
+                RBX, target::MegamorphicCache::arguments_descriptor_offset()));
     __ jmp(target_address);
   } else {
     __ movq(RAX, target_address);
     __ movq(R10,
-            FieldAddress(RBX, MegamorphicCache::arguments_descriptor_offset()));
-    __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
-    __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
+            FieldAddress(
+                RBX, target::MegamorphicCache::arguments_descriptor_offset()));
+    __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+    __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
     __ jmp(RCX);
   }
 
   // Probe failed, check if it is a miss.
   __ Bind(&probe_failed);
   __ cmpq(FieldAddress(RDI, RCX, TIMES_8, base),
-          Immediate(Smi::RawValue(kIllegalCid)));
+          Immediate(target::ToRawSmi(kIllegalCid)));
   __ j(ZERO, &load_target, Assembler::kNearJump);
 
   // Try next entry in the table.
-  __ AddImmediate(RCX, Immediate(Smi::RawValue(1)));
+  __ AddImmediate(RCX, Immediate(target::ToRawSmi(1)));
   __ jmp(&loop);
 
   // Load cid for the Smi case.
@@ -2994,11 +3045,12 @@
 // Passed to target:
 //  CODE_REG: target Code object
 //  R10: arguments descriptor
-void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughFunctionStub(Assembler* assembler) {
   Label loop, found, miss;
-  __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
-  __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
-  __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+  __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
+  __ movq(R10,
+          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+  __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: first IC entry
   __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
   // RAX: receiver cid as Smi
@@ -3008,34 +3060,37 @@
   __ cmpq(RAX, R9);
   __ j(EQUAL, &found, Assembler::kNearJump);
 
-  ASSERT(Smi::RawValue(kIllegalCid) == 0);
+  ASSERT(target::ToRawSmi(kIllegalCid) == 0);
   __ testq(R9, R9);
   __ j(ZERO, &miss, Assembler::kNearJump);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ addq(R13, Immediate(entry_length));  // Next entry.
   __ jmp(&loop);
 
   __ Bind(&found);
-  const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize;
+  const intptr_t target_offset =
+      target::ICData::TargetIndexFor(1) * target::kWordSize;
   __ movq(RAX, Address(R13, target_offset));
-  __ movq(RCX, FieldAddress(RAX, Function::entry_point_offset()));
-  __ movq(CODE_REG, FieldAddress(RAX, Function::code_offset()));
+  __ movq(RCX, FieldAddress(RAX, target::Function::entry_point_offset()));
+  __ movq(CODE_REG, FieldAddress(RAX, target::Function::code_offset()));
   __ jmp(RCX);
 
   __ Bind(&miss);
   __ LoadIsolate(RAX);
-  __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset()));
-  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(CODE_REG, Address(RAX, target::Isolate::ic_miss_code_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ jmp(RCX);
 }
 
-void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateICCallThroughCodeStub(Assembler* assembler) {
   Label loop, found, miss;
-  __ movq(R13, FieldAddress(RBX, ICData::ic_data_offset()));
-  __ movq(R10, FieldAddress(RBX, ICData::arguments_descriptor_offset()));
-  __ leaq(R13, FieldAddress(R13, Array::data_offset()));
+  __ movq(R13, FieldAddress(RBX, target::ICData::entries_offset()));
+  __ movq(R10,
+          FieldAddress(RBX, target::ICData::arguments_descriptor_offset()));
+  __ leaq(R13, FieldAddress(R13, target::Array::data_offset()));
   // R13: first IC entry
   __ LoadTaggedClassIdMayBeSmi(RAX, RDI);
   // RAX: receiver cid as Smi
@@ -3045,18 +3100,21 @@
   __ cmpq(RAX, R9);
   __ j(EQUAL, &found, Assembler::kNearJump);
 
-  ASSERT(Smi::RawValue(kIllegalCid) == 0);
+  ASSERT(target::ToRawSmi(kIllegalCid) == 0);
   __ testq(R9, R9);
   __ j(ZERO, &miss, Assembler::kNearJump);
 
   const intptr_t entry_length =
-      ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) * kWordSize;
+      target::ICData::TestEntryLengthFor(1, /*tracking_exactness=*/false) *
+      target::kWordSize;
   __ addq(R13, Immediate(entry_length));  // Next entry.
   __ jmp(&loop);
 
   __ Bind(&found);
-  const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize;
-  const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize;
+  const intptr_t code_offset =
+      target::ICData::CodeIndexFor(1) * target::kWordSize;
+  const intptr_t entry_offset =
+      target::ICData::EntryPointIndexFor(1) * target::kWordSize;
   if (!(FLAG_precompiled_mode && FLAG_use_bare_instructions)) {
     __ movq(CODE_REG, Address(R13, code_offset));
   }
@@ -3064,14 +3122,14 @@
 
   __ Bind(&miss);
   __ LoadIsolate(RAX);
-  __ movq(CODE_REG, Address(RAX, Isolate::ic_miss_code_offset()));
-  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ movq(CODE_REG, Address(RAX, target::Isolate::ic_miss_code_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset()));
   __ jmp(RCX);
 }
 
 //  RDI: receiver
 //  RBX: UnlinkedCall
-void StubCode::GenerateUnlinkedCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateUnlinkedCallStub(Assembler* assembler) {
   __ EnterStubFrame();
   __ pushq(RDI);  // Preserve receiver.
 
@@ -3086,9 +3144,10 @@
   __ popq(RDI);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                          Code::EntryKind::kMonomorphic)));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                          CodeEntryKind::kMonomorphic)));
   __ jmp(RCX);
 }
 
@@ -3097,17 +3156,21 @@
 //  RBX: SingleTargetCache
 // Passed to target::
 //  CODE_REG: target Code object
-void StubCode::GenerateSingleTargetCallStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateSingleTargetCallStub(Assembler* assembler) {
   Label miss;
   __ LoadClassIdMayBeSmi(RAX, RDI);
-  __ movzxw(R9, FieldAddress(RBX, SingleTargetCache::lower_limit_offset()));
-  __ movzxw(R10, FieldAddress(RBX, SingleTargetCache::upper_limit_offset()));
+  __ movzxw(R9,
+            FieldAddress(RBX, target::SingleTargetCache::lower_limit_offset()));
+  __ movzxw(R10,
+            FieldAddress(RBX, target::SingleTargetCache::upper_limit_offset()));
   __ cmpq(RAX, R9);
   __ j(LESS, &miss, Assembler::kNearJump);
   __ cmpq(RAX, R10);
   __ j(GREATER, &miss, Assembler::kNearJump);
-  __ movq(RCX, FieldAddress(RBX, SingleTargetCache::entry_point_offset()));
-  __ movq(CODE_REG, FieldAddress(RBX, SingleTargetCache::target_offset()));
+  __ movq(RCX,
+          FieldAddress(RBX, target::SingleTargetCache::entry_point_offset()));
+  __ movq(CODE_REG,
+          FieldAddress(RBX, target::SingleTargetCache::target_offset()));
   __ jmp(RCX);
 
   __ Bind(&miss);
@@ -3123,16 +3186,18 @@
   __ popq(RDI);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                          Code::EntryKind::kMonomorphic)));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                          CodeEntryKind::kMonomorphic)));
   __ jmp(RCX);
 }
 
 // Called from the monomorphic checked entry.
 //  RDI: receiver
-void StubCode::GenerateMonomorphicMissStub(Assembler* assembler) {
-  __ movq(CODE_REG, Address(THR, Thread::monomorphic_miss_stub_offset()));
+void StubCodeCompiler::GenerateMonomorphicMissStub(Assembler* assembler) {
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::monomorphic_miss_stub_offset()));
   __ EnterStubFrame();
   __ pushq(RDI);  // Preserve receiver.
 
@@ -3145,20 +3210,24 @@
   __ popq(RDI);  // Restore receiver.
   __ LeaveStubFrame();
 
-  __ movq(CODE_REG, Address(THR, Thread::ic_lookup_through_code_stub_offset()));
-  __ movq(RCX, FieldAddress(CODE_REG, Code::entry_point_offset(
-                                          Code::EntryKind::kMonomorphic)));
+  __ movq(CODE_REG,
+          Address(THR, target::Thread::ic_lookup_through_code_stub_offset()));
+  __ movq(RCX, FieldAddress(CODE_REG, target::Code::entry_point_offset(
+                                          CodeEntryKind::kMonomorphic)));
   __ jmp(RCX);
 }
 
-void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateFrameAwaitingMaterializationStub(
+    Assembler* assembler) {
   __ int3();
 }
 
-void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
+void StubCodeCompiler::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
   __ int3();
 }
 
+}  // namespace compiler
+
 }  // namespace dart
 
 #endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/constants_kbc.h b/runtime/vm/constants_kbc.h
index 15506e5..aeb775e 100644
--- a/runtime/vm/constants_kbc.h
+++ b/runtime/vm/constants_kbc.h
@@ -271,6 +271,11 @@
 //    SP[-(1+ArgC)], ..., SP[-1] and argument descriptor PP[D], which
 //    indicates whether the first argument is a type argument vector.
 //
+//  - DirectCall ArgC, D
+//
+//    Invoke the function PP[D] with arguments
+//    SP[-(ArgC-1)], ..., SP[0] and argument descriptor PP[D+1].
+//
 //  - InterfaceCall ArgC, D
 //
 //    Lookup and invoke method using ICData in PP[D]
@@ -478,7 +483,8 @@
   V(CompareIntGt,                          0, ___, ___, ___)                   \
   V(CompareIntLt,                          0, ___, ___, ___)                   \
   V(CompareIntGe,                          0, ___, ___, ___)                   \
-  V(CompareIntLe,                          0, ___, ___, ___)
+  V(CompareIntLe,                          0, ___, ___, ___)                   \
+  V(DirectCall,                          A_D, num, num, ___)
 
 // clang-format on
 
@@ -607,6 +613,7 @@
       case KernelBytecode::kIndirectStaticCall:
       case KernelBytecode::kInterfaceCall:
       case KernelBytecode::kDynamicCall:
+      case KernelBytecode::kDirectCall:
         return true;
 
       default:
diff --git a/runtime/vm/constants_x64.cc b/runtime/vm/constants_x64.cc
new file mode 100644
index 0000000..df6fb75
--- /dev/null
+++ b/runtime/vm/constants_x64.cc
@@ -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.
+
+#include "vm/constants_x64.h"
+
+namespace dart {
+
+#if defined(_WIN64)
+const Register CallingConventions::ArgumentRegisters[] = {
+    CallingConventions::kArg1Reg, CallingConventions::kArg2Reg,
+    CallingConventions::kArg3Reg, CallingConventions::kArg4Reg};
+
+const XmmRegister CallingConventions::XmmArgumentRegisters[] = {
+    XmmRegister::XMM0, XmmRegister::XMM1, XmmRegister::XMM2, XmmRegister::XMM3};
+#else
+const Register CallingConventions::ArgumentRegisters[] = {
+    CallingConventions::kArg1Reg, CallingConventions::kArg2Reg,
+    CallingConventions::kArg3Reg, CallingConventions::kArg4Reg,
+    CallingConventions::kArg5Reg, CallingConventions::kArg6Reg};
+
+const XmmRegister CallingConventions::XmmArgumentRegisters[] = {
+    XmmRegister::XMM0, XmmRegister::XMM1, XmmRegister::XMM2, XmmRegister::XMM3,
+    XmmRegister::XMM4, XmmRegister::XMM5, XmmRegister::XMM6, XmmRegister::XMM7};
+#endif
+
+}  // namespace dart
diff --git a/runtime/vm/constants_x64.h b/runtime/vm/constants_x64.h
index 512ff98..5de7ddc 100644
--- a/runtime/vm/constants_x64.h
+++ b/runtime/vm/constants_x64.h
@@ -5,6 +5,9 @@
 #ifndef RUNTIME_VM_CONSTANTS_X64_H_
 #define RUNTIME_VM_CONSTANTS_X64_H_
 
+#include "platform/assert.h"
+#include "platform/globals.h"
+
 namespace dart {
 
 enum Register {
@@ -149,6 +152,20 @@
   static const Register kArg2Reg = RDX;
   static const Register kArg3Reg = R8;
   static const Register kArg4Reg = R9;
+  static const Register ArgumentRegisters[];
+  static const intptr_t kArgumentRegisters =
+      R(kArg1Reg) | R(kArg2Reg) | R(kArg3Reg) | R(kArg4Reg);
+  static const intptr_t kNumArgRegs = 4;
+
+  static const XmmRegister XmmArgumentRegisters[];
+  static const intptr_t kXmmArgumentRegisters =
+      R(XMM0) | R(XMM1) | R(XMM2) | R(XMM3);
+  static const intptr_t kNumXmmArgRegs = 4;
+
+  // can ArgumentRegisters[i] and XmmArgumentRegisters[i] both be used at the
+  // same time? (Windows no, rest yes)
+  static const bool kArgumentIntRegXorXmmReg = true;
+
   static const intptr_t kShadowSpaceBytes = 4 * kWordSize;
 
   static const intptr_t kVolatileCpuRegisters =
@@ -164,6 +181,8 @@
       R(XMM6) | R(XMM7) | R(XMM8) | R(XMM9) | R(XMM10) | R(XMM11) | R(XMM12) |
       R(XMM13) | R(XMM14) | R(XMM15);
 
+  static const XmmRegister xmmFirstNonParameterReg = XMM4;
+
   // Windows x64 ABI specifies that small objects are passed in registers.
   // Otherwise they are passed by reference.
   static const size_t kRegisterTransferLimit = 16;
@@ -177,6 +196,22 @@
   static const Register kArg4Reg = RCX;
   static const Register kArg5Reg = R8;
   static const Register kArg6Reg = R9;
+  static const Register ArgumentRegisters[];
+  static const intptr_t kArgumentRegisters = R(kArg1Reg) | R(kArg2Reg) |
+                                             R(kArg3Reg) | R(kArg4Reg) |
+                                             R(kArg5Reg) | R(kArg6Reg);
+  static const intptr_t kNumArgRegs = 6;
+
+  static const XmmRegister XmmArgumentRegisters[];
+  static const intptr_t kXmmArgumentRegisters = R(XMM0) | R(XMM1) | R(XMM2) |
+                                                R(XMM3) | R(XMM4) | R(XMM5) |
+                                                R(XMM6) | R(XMM7);
+  static const intptr_t kNumXmmArgRegs = 8;
+
+  // can ArgumentRegisters[i] and XmmArgumentRegisters[i] both be used at the
+  // same time? (Windows no, rest yes)
+  static const bool kArgumentIntRegXorXmmReg = false;
+
   static const intptr_t kShadowSpaceBytes = 0;
 
   static const intptr_t kVolatileCpuRegisters = R(RAX) | R(RCX) | R(RDX) |
@@ -192,6 +227,8 @@
       R(RBX) | R(R12) | R(R13) | R(R14) | R(R15);
 
   static const intptr_t kCalleeSaveXmmRegisters = 0;
+
+  static const XmmRegister xmmFirstNonParameterReg = XMM8;
 };
 #endif
 
diff --git a/runtime/vm/dart_api_impl.cc b/runtime/vm/dart_api_impl.cc
index 520d39a..8e45f57 100644
--- a/runtime/vm/dart_api_impl.cc
+++ b/runtime/vm/dart_api_impl.cc
@@ -1503,7 +1503,7 @@
   }
 #endif  // #if defined(DEBUG)
 
-  Symbols::Compact(I);
+  Symbols::Compact();
 
   FullSnapshotWriter writer(Snapshot::kFull, vm_snapshot_data_buffer,
                             isolate_snapshot_data_buffer, ApiReallocate,
@@ -4774,6 +4774,10 @@
       return Symbols::False().raw();
     }
 
+    if (!Api::ffiEnabled() && name.Equals(Symbols::DartLibraryFfi())) {
+      return Symbols::False().raw();
+    }
+
     if (name.Equals(Symbols::DartVMProduct())) {
 #ifdef PRODUCT
       return Symbols::True().raw();
@@ -5248,6 +5252,11 @@
   Isolate* I = T->isolate();
   CHECK_CALLBACK_STATE(T);
 
+  // The kernel loader is about to allocate a bunch of new libraries, classes,
+  // and functions into old space. Force growth, and use of the bump allocator
+  // instead of freelists.
+  BumpAllocateScope bump_allocate_scope(T);
+
   I->DoneLoading();
 
   // TODO(hausner): move the remaining code below (finalization and
@@ -5270,6 +5279,8 @@
   I->debugger()->NotifyDoneLoading();
 #endif
 
+  I->heap()->old_space()->EvaluateAfterLoading();
+
 #if !defined(DART_PRECOMPILED_RUNTIME)
   if (FLAG_enable_mirrors) {
     // Notify mirrors that MirrorSystem.libraries needs to be recomputed.
@@ -5502,107 +5513,43 @@
   return OS::GetCurrentMonotonicMicros();
 }
 
-#if defined(PRODUCT)
 DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
     const char* name,
     Dart_ServiceRequestCallback callback,
     void* user_data) {
-  return;
-}
-
-DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
-    const char* name,
-    Dart_ServiceRequestCallback callback,
-    void* user_data) {
-  return;
-}
-
-DART_EXPORT void Dart_SetEmbedderInformationCallback(
-    Dart_EmbedderInformationCallback callback) {
-  return;
-}
-
-DART_EXPORT char* Dart_SetServiceStreamCallbacks(
-    Dart_ServiceStreamListenCallback listen_callback,
-    Dart_ServiceStreamCancelCallback cancel_callback) {
-  return NULL;
-}
-
-DART_EXPORT void Dart_SetNativeServiceStreamCallback(
-    Dart_NativeStreamConsumer consumer,
-    const char* stream_id) {
-  return;
-}
-
-DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
-                                                  const char* event_kind,
-                                                  const uint8_t* bytes,
-                                                  intptr_t bytes_length) {
-  return Api::Success();
-}
-
-DART_EXPORT char* Dart_SetFileModifiedCallback(
-    Dart_FileModifiedCallback file_mod_callback) {
-  return NULL;
-}
-
-DART_EXPORT bool Dart_IsReloading() {
-  return false;
-}
-
-DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
-  return;
-}
-
-DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
-    Dart_EmbedderTimelineStartRecording start_recording,
-    Dart_EmbedderTimelineStopRecording stop_recording) {
-  return;
-}
-
-DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
-                                             void* user_data) {
-  return false;
-}
-
-DART_EXPORT void Dart_TimelineEvent(const char* label,
-                                    int64_t timestamp0,
-                                    int64_t timestamp1_or_async_id,
-                                    Dart_Timeline_Event_Type type,
-                                    intptr_t argument_count,
-                                    const char** argument_names,
-                                    const char** argument_values) {
-  return;
-}
-#else  // defined(PRODUCT)
-DART_EXPORT void Dart_RegisterIsolateServiceRequestCallback(
-    const char* name,
-    Dart_ServiceRequestCallback callback,
-    void* user_data) {
+#if !defined(PRODUCT)
   if (FLAG_support_service) {
     Service::RegisterIsolateEmbedderCallback(name, callback, user_data);
   }
+#endif
 }
 
 DART_EXPORT void Dart_RegisterRootServiceRequestCallback(
     const char* name,
     Dart_ServiceRequestCallback callback,
     void* user_data) {
+#if !defined(PRODUCT)
   if (FLAG_support_service) {
     Service::RegisterRootEmbedderCallback(name, callback, user_data);
   }
+#endif
 }
 
 DART_EXPORT void Dart_SetEmbedderInformationCallback(
     Dart_EmbedderInformationCallback callback) {
+#if !defined(PRODUCT)
   if (FLAG_support_service) {
     Service::SetEmbedderInformationCallback(callback);
   }
+#endif
 }
 
 DART_EXPORT char* Dart_SetServiceStreamCallbacks(
     Dart_ServiceStreamListenCallback listen_callback,
     Dart_ServiceStreamCancelCallback cancel_callback) {
+#if defined(PRODUCT)
+  return NULL;
+#else
   if (!FLAG_support_service) {
     return NULL;
   }
@@ -5636,18 +5583,22 @@
   }
   Service::SetEmbedderStreamCallbacks(listen_callback, cancel_callback);
   return NULL;
+#endif
 }
 
 DART_EXPORT void Dart_SetNativeServiceStreamCallback(
     Dart_NativeStreamConsumer consumer,
     const char* stream_id) {
+#if !defined(PRODUCT)
   Service::SetNativeServiceStreamCallback(consumer, stream_id);
+#endif
 }
 
 DART_EXPORT Dart_Handle Dart_ServiceSendDataEvent(const char* stream_id,
                                                   const char* event_kind,
                                                   const uint8_t* bytes,
                                                   intptr_t bytes_length) {
+#if !defined(PRODUCT)
   DARTSCOPE(Thread::Current());
   Isolate* I = T->isolate();
   if (stream_id == NULL) {
@@ -5664,11 +5615,13 @@
                          CURRENT_FUNC);
   }
   Service::SendEmbedderEvent(I, stream_id, event_kind, bytes, bytes_length);
+#endif
   return Api::Success();
 }
 
 DART_EXPORT char* Dart_SetFileModifiedCallback(
     Dart_FileModifiedCallback file_modified_callback) {
+#if !defined(PRODUCT)
   if (!FLAG_support_service) {
     return NULL;
   }
@@ -5689,14 +5642,19 @@
   }
   IsolateReloadContext::SetFileModifiedCallback(file_modified_callback);
 #endif  // !defined(DART_PRECOMPILED_RUNTIME)
+#endif  // !defined(PRODUCT)
   return NULL;
 }
 
 DART_EXPORT bool Dart_IsReloading() {
+#if defined(PRODUCT)
+  return false;
+#else
   Thread* thread = Thread::Current();
   Isolate* isolate = thread->isolate();
   CHECK_ISOLATE(isolate);
   return isolate->IsReloading();
+#endif
 }
 
 DART_EXPORT void Dart_GlobalTimelineSetRecordedStreams(int64_t stream_mask) {
@@ -5724,121 +5682,6 @@
 #endif
 }
 
-static void StartStreamToConsumer(Dart_StreamConsumer consumer,
-                                  void* user_data,
-                                  const char* stream_name) {
-  // Start stream.
-  consumer(Dart_StreamConsumer_kStart, stream_name, NULL, 0, user_data);
-}
-
-static void FinishStreamToConsumer(Dart_StreamConsumer consumer,
-                                   void* user_data,
-                                   const char* stream_name) {
-  // Finish stream.
-  consumer(Dart_StreamConsumer_kFinish, stream_name, NULL, 0, user_data);
-}
-
-static void DataStreamToConsumer(Dart_StreamConsumer consumer,
-                                 void* user_data,
-                                 const char* output,
-                                 intptr_t output_length,
-                                 const char* stream_name) {
-  if (output == NULL) {
-    return;
-  }
-  const intptr_t kDataSize = 64 * KB;
-  intptr_t cursor = 0;
-  intptr_t remaining = output_length;
-  while (remaining >= kDataSize) {
-    consumer(Dart_StreamConsumer_kData, stream_name,
-             reinterpret_cast<const uint8_t*>(&output[cursor]), kDataSize,
-             user_data);
-    cursor += kDataSize;
-    remaining -= kDataSize;
-  }
-  if (remaining > 0) {
-    ASSERT(remaining < kDataSize);
-    consumer(Dart_StreamConsumer_kData, stream_name,
-             reinterpret_cast<const uint8_t*>(&output[cursor]), remaining,
-             user_data);
-    cursor += remaining;
-    remaining -= remaining;
-  }
-  ASSERT(cursor == output_length);
-  ASSERT(remaining == 0);
-}
-
-static bool StreamTraceEvents(Dart_StreamConsumer consumer,
-                              void* user_data,
-                              JSONStream* js) {
-  ASSERT(js != NULL);
-  // Steal output from JSONStream.
-  char* output = NULL;
-  intptr_t output_length = 0;
-  js->Steal(&output, &output_length);
-  if (output_length < 3) {
-    // Empty JSON array.
-    free(output);
-    return false;
-  }
-  // We want to send the JSON array without the leading '[' or trailing ']'
-  // characters.
-  ASSERT(output[0] == '[');
-  ASSERT(output[output_length - 1] == ']');
-  // Replace the ']' with the null character.
-  output[output_length - 1] = '\0';
-  char* start = &output[1];
-  // We are skipping the '['.
-  output_length -= 1;
-
-  DataStreamToConsumer(consumer, user_data, start, output_length, "timeline");
-
-  // We stole the JSONStream's output buffer, free it.
-  free(output);
-
-  return true;
-}
-
-DART_EXPORT void Dart_SetEmbedderTimelineCallbacks(
-    Dart_EmbedderTimelineStartRecording start_recording,
-    Dart_EmbedderTimelineStopRecording stop_recording) {
-#if defined(SUPPORT_TIMELINE)
-  Timeline::set_start_recording_cb(start_recording);
-  Timeline::set_stop_recording_cb(stop_recording);
-#endif
-}
-
-DART_EXPORT bool Dart_GlobalTimelineGetTrace(Dart_StreamConsumer consumer,
-                                             void* user_data) {
-#if defined(PRODUCT)
-  return false;
-#else
-  // To support various embedders, it must be possible to call this function
-  // from a thread for which we have not entered an Isolate and set up a Thread
-  // TLS object. Therefore, a Zone may not be available, a StackZone cannot be
-  // created, and no ZoneAllocated objects can be allocated.
-  if (consumer == NULL) {
-    return false;
-  }
-  TimelineEventRecorder* timeline_recorder = Timeline::recorder();
-  if (timeline_recorder == NULL) {
-    // Nothing has been recorded.
-    return false;
-  }
-  Timeline::ReclaimCachedBlocksFromThreads();
-  bool success = false;
-  JSONStream js;
-  TimelineEventFilter filter;
-  timeline_recorder->PrintTraceEvent(&js, &filter);
-  StartStreamToConsumer(consumer, user_data, "timeline");
-  if (StreamTraceEvents(consumer, user_data, &js)) {
-    success = true;
-  }
-  FinishStreamToConsumer(consumer, user_data, "timeline");
-  return success;
-#endif
-}
-
 DART_EXPORT void Dart_TimelineEvent(const char* label,
                                     int64_t timestamp0,
                                     int64_t timestamp1_or_async_id,
@@ -5905,7 +5748,6 @@
   event->Complete();
 #endif
 }
-#endif  // defined(PRODUCT)
 
 DART_EXPORT void Dart_SetThreadName(const char* name) {
   OSThread* thread = OSThread::Current();
@@ -6255,7 +6097,7 @@
   DropRegExpMatchCode(Z);
 
   ProgramVisitor::Dedup();
-  Symbols::Compact(I);
+  Symbols::Compact();
 
   TIMELINE_DURATION(T, Isolate, "WriteCoreJITSnapshot");
   BlobImageWriter vm_image_writer(T, vm_snapshot_instructions_buffer,
@@ -6317,7 +6159,7 @@
     DropCodeWithoutReusableInstructions(reused_instructions);
   }
   ProgramVisitor::Dedup();
-  Symbols::Compact(I);
+  Symbols::Compact();
 
   if (FLAG_dump_tables) {
     Symbols::DumpTable(I);
diff --git a/runtime/vm/dart_api_impl.h b/runtime/vm/dart_api_impl.h
index 9c3518a..570a855 100644
--- a/runtime/vm/dart_api_impl.h
+++ b/runtime/vm/dart_api_impl.h
@@ -294,6 +294,25 @@
 
   static RawString* GetEnvironmentValue(Thread* thread, const String& name);
 
+  static bool ffiEnabled() {
+    // dart:ffi is not implemented for the following configurations
+#if !defined(TARGET_ARCH_X64)
+    // https://github.com/dart-lang/sdk/issues/35774
+    return false;
+#elif !defined(TARGET_OS_LINUX) && !defined(TARGET_OS_MACOS)
+    // https://github.com/dart-lang/sdk/issues/35760 Arm32 && Android
+    // https://github.com/dart-lang/sdk/issues/35771 Windows
+    // https://github.com/dart-lang/sdk/issues/35772 Arm64
+    // https://github.com/dart-lang/sdk/issues/35773 DBC
+    return false;
+#else
+    // dart:ffi is also not implemented for precompiled in which case
+    // FLAG_enable_ffi is set to false by --precompilation.
+    // Once dart:ffi is supported on all targets, only users will set this flag
+    return FLAG_enable_ffi;
+#endif
+  }
+
  private:
   static Dart_Handle InitNewHandle(Thread* thread, RawObject* raw);
 
diff --git a/runtime/vm/dart_api_impl_test.cc b/runtime/vm/dart_api_impl_test.cc
index 3a3c425..b4ad32a 100644
--- a/runtime/vm/dart_api_impl_test.cc
+++ b/runtime/vm/dart_api_impl_test.cc
@@ -7657,515 +7657,6 @@
   EXPECT_SUBSTRING("testAsyncEvent", js.ToCString());
 }
 
-struct AppendData {
-  uint8_t* buffer;
-  intptr_t buffer_length;
-};
-
-static void AppendStreamConsumer(Dart_StreamConsumer_State state,
-                                 const char* stream_name,
-                                 const uint8_t* buffer,
-                                 intptr_t buffer_length,
-                                 void* user_data) {
-  if (state == Dart_StreamConsumer_kFinish) {
-    return;
-  }
-  AppendData* data = reinterpret_cast<AppendData*>(user_data);
-  if (state == Dart_StreamConsumer_kStart) {
-    // Initialize append data.
-    data->buffer = NULL;
-    data->buffer_length = 0;
-    return;
-  }
-  ASSERT(state == Dart_StreamConsumer_kData);
-
-  // Grow buffer.
-  data->buffer = reinterpret_cast<uint8_t*>(
-      realloc(data->buffer, data->buffer_length + buffer_length));
-  // Copy new data.
-  memmove(&data->buffer[data->buffer_length], buffer, buffer_length);
-  // Update length.
-  data->buffer_length += buffer_length;
-}
-
-TEST_CASE(DartAPI_TimelineGetTrace) {
-  const char* kScriptChars =
-      "foo() => 'a';\n"
-      "main() => foo();\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-  bool success = false;
-
-  // Enable recording of all streams.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
-
-  // Invoke main, which will be compiled resulting in a compiler event in
-  // the timeline.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Grab the trace.
-  AppendData data;
-  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-  EXPECT(success);
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
-TEST_CASE(DartAPI_TimelineGetTraceOnlyDartEvents) {
-  const char* kScriptChars =
-      "import 'dart:developer';\n"
-      ""
-      "main() {\n"
-      "  Timeline.startSync('DART_NAME');\n"
-      "  Timeline.finishSync();\n"
-      "}\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-  bool success = false;
-
-  // Enable recording of the Dart stream.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_DART);
-
-  // Invoke main, which will add a new timeline event from Dart.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Grab the trace.
-  AppendData data;
-  data.buffer = NULL;
-  data.buffer_length = 0;
-  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-  EXPECT(success);
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"cat\":\"Dart\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"DART_NAME\"", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
-TEST_CASE(DartAPI_TimelineGetTraceWithDartEvents) {
-  const char* kScriptChars =
-      "import 'dart:developer';\n"
-      "\n"
-      "main() {\n"
-      "  Timeline.startSync('DART_NAME');\n"
-      "  Timeline.finishSync();\n"
-      "}\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-  bool success = false;
-
-  // Enable recording of all streams.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
-
-  // Invoke main, which will be compiled resulting in a compiler event in
-  // the timeline.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Grab the trace.
-  AppendData data;
-  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-  EXPECT(success);
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-  EXPECT_SUBSTRING("\"cat\":\"Dart\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"DART_NAME\"", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
-TEST_CASE(DartAPI_TimelineGetTraceGlobalOverride) {
-  const char* kScriptChars =
-      "foo() => 'a';\n"
-      "main() => foo();\n";
-
-  Dart_Handle lib = TestCase::LoadTestScript(kScriptChars, NULL);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-  bool success = false;
-
-  // Enable recording of all streams across the entire vm.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL);
-
-  // Invoke main, which will be compiled resulting in a compiler event in
-  // the timeline.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  // Grab the trace.
-  AppendData data;
-  success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-  EXPECT(success);
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
-static const char* arg_names[] = {"arg0"};
-
-static const char* arg_values[] = {"value0"};
-
-TEST_CASE(DartAPI_GlobalTimelineGetTrace) {
-  const char* kScriptChars =
-      "bar() => 'z';\n"
-      "foo() => 'a';\n"
-      "main() => foo();\n";
-
-  // Enable all streams.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL |
-                                        DART_TIMELINE_STREAM_VM);
-  Dart_Handle lib;
-  {
-    // Add something to the VM stream.
-    TimelineDurationScope tds(Timeline::GetVMStream(), "TestVMDuration");
-    lib = TestCase::LoadTestScript(kScriptChars, NULL);
-  }
-
-  {
-    // Add something to the embedder stream.
-    Dart_TimelineEvent("TRACE_EVENT", Dart_TimelineGetMicros(), 0,
-                       Dart_Timeline_Event_Begin, 1, &arg_names[0],
-                       &arg_values[0]);
-    // Add counter to the embedder stream.
-    Dart_TimelineEvent("COUNTER_EVENT", Dart_TimelineGetMicros(), 0,
-                       Dart_Timeline_Event_Counter, 0, NULL, NULL);
-    Dart_SetThreadName("CUSTOM THREAD NAME");
-  }
-
-  // Invoke main, which will be compiled resulting in a compiler event in
-  // the timeline.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-  bool success = false;
-
-  // Grab the global trace.
-  AppendData data;
-  {
-    Thread* T = Thread::Current();
-    StackZone zone(T);
-    success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-    EXPECT(success);
-    // The call should do no zone allocation.
-    EXPECT(zone.SizeInBytes() == 0);
-  }
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer);
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-  EXPECT_NOTSUBSTRING("\"function\":\"::_bar\"", buffer);
-  EXPECT_SUBSTRING("TRACE_EVENT", buffer);
-  EXPECT_SUBSTRING("arg0", buffer);
-  EXPECT_SUBSTRING("value0", buffer);
-  EXPECT_SUBSTRING("COUNTER_EVENT", buffer);
-  EXPECT_SUBSTRING("CUSTOM THREAD NAME", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-  data.buffer = NULL;
-  data.buffer_length = 0;
-
-  // Retrieving the global trace resulted in all open blocks being reclaimed.
-  // Add some new events and verify that both sets of events are present
-  // in the resulting trace.
-  {
-    // Add something to the VM stream.
-    TimelineDurationScope tds(Timeline::GetVMStream(), "TestVMDuration2");
-    // Invoke bar, which will be compiled resulting in a compiler event in
-    // the timeline.
-    result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
-  }
-
-  // Grab the global trace.
-  {
-    Thread* T = Thread::Current();
-    StackZone zone(T);
-    success = Dart_GlobalTimelineGetTrace(AppendStreamConsumer, &data);
-    EXPECT(success);
-    EXPECT(zone.SizeInBytes() == 0);
-  }
-  buffer = reinterpret_cast<char*>(data.buffer);
-  buffer_length = data.buffer_length;
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test for old events.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer);
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-
-  // Heartbeat test for new events.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration2\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_bar\"", buffer);
-
-  // Free buffer allocated by AppendStreamConsumer
-  free(data.buffer);
-}
-
-class GlobalTimelineThreadData {
- public:
-  GlobalTimelineThreadData()
-      : monitor_(new Monitor()), data_(new AppendData()), running_(true) {}
-
-  ~GlobalTimelineThreadData() {
-    delete monitor_;
-    monitor_ = NULL;
-    free(data_->buffer);
-    data_->buffer = NULL;
-    data_->buffer_length = 0;
-    delete data_;
-    data_ = NULL;
-  }
-
-  Monitor* monitor() const { return monitor_; }
-  bool running() const { return running_; }
-  AppendData* data() const { return data_; }
-  uint8_t* buffer() const { return data_->buffer; }
-  intptr_t buffer_length() const { return data_->buffer_length; }
-
-  void set_running(bool running) { running_ = running; }
-
- private:
-  Monitor* monitor_;
-  AppendData* data_;
-  bool running_;
-};
-
-static void GlobalTimelineThread(uword parameter) {
-  GlobalTimelineThreadData* data =
-      reinterpret_cast<GlobalTimelineThreadData*>(parameter);
-  Thread* T = Thread::Current();
-  // When there is no current Thread, then Zone allocation will fail.
-  EXPECT(T == NULL);
-  {
-    MonitorLocker ml(data->monitor());
-    bool success =
-        Dart_GlobalTimelineGetTrace(AppendStreamConsumer, data->data());
-    EXPECT(success);
-    data->set_running(false);
-    ml.Notify();
-  }
-}
-
-// This test is the same as the one above except that the calls to
-// Dart_GlobalTimelineGetTrace are made from a fresh thread. This ensures that
-// we can call the function from a thread for which we have not set up a
-// Thread object.
-TEST_CASE(DartAPI_GlobalTimelineGetTrace_Threaded) {
-  const char* kScriptChars =
-      "bar() => 'z';\n"
-      "foo() => 'a';\n"
-      "main() => foo();\n";
-
-  // Enable all streams.
-  Dart_GlobalTimelineSetRecordedStreams(DART_TIMELINE_STREAM_ALL |
-                                        DART_TIMELINE_STREAM_VM);
-  Dart_Handle lib;
-  {
-    // Add something to the VM stream.
-    TimelineDurationScope tds(Timeline::GetVMStream(), "TestVMDuration");
-    lib = TestCase::LoadTestScript(kScriptChars, NULL);
-  }
-
-  // Invoke main, which will be compiled resulting in a compiler event in
-  // the timeline.
-  Dart_Handle result = Dart_Invoke(lib, NewString("main"), 0, NULL);
-  EXPECT_VALID(result);
-
-  const char* buffer = NULL;
-  intptr_t buffer_length = 0;
-
-  // Run Dart_GlobalTimelineGetTrace on a fresh thread.
-  GlobalTimelineThreadData data;
-  int err = OSThread::Start("Timeline test thread", GlobalTimelineThread,
-                            reinterpret_cast<uword>(&data));
-  EXPECT(err == 0);
-  {
-    MonitorLocker ml(data.monitor());
-    while (data.running()) {
-      ml.Wait();
-    }
-    buffer = reinterpret_cast<char*>(data.buffer());
-    buffer_length = data.buffer_length();
-  }
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer);
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-  EXPECT_NOTSUBSTRING("\"function\":\"::_bar\"", buffer);
-
-  // Retrieving the global trace resulted in all open blocks being reclaimed.
-  // Add some new events and verify that both sets of events are present
-  // in the resulting trace.
-  {
-    // Add something to the VM stream.
-    TimelineDurationScope tds(Timeline::GetVMStream(), "TestVMDuration2");
-    // Invoke bar, which will be compiled resulting in a compiler event in
-    // the timeline.
-    result = Dart_Invoke(lib, NewString("bar"), 0, NULL);
-  }
-
-  // Grab the global trace.
-  GlobalTimelineThreadData data2;
-  err = OSThread::Start("Timeline test thread", GlobalTimelineThread,
-                        reinterpret_cast<uword>(&data2));
-  EXPECT(err == 0);
-  {
-    MonitorLocker ml(data2.monitor());
-    while (data2.running()) {
-      ml.Wait();
-    }
-    buffer = reinterpret_cast<char*>(data2.buffer());
-    buffer_length = data2.buffer_length();
-  }
-
-  EXPECT(buffer_length > 0);
-  EXPECT(buffer != NULL);
-  // Response starts with a '{' character and not a '['.
-  EXPECT(buffer[0] == '{');
-  // Response ends with a '}' character and not a ']'.
-  EXPECT(buffer[buffer_length - 1] == '\0');
-  EXPECT(buffer[buffer_length - 2] == '}');
-
-  // Heartbeat test for old events.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration\"", buffer);
-  EXPECT_SUBSTRING("\"cat\":\"Compiler\"", buffer);
-  EXPECT_SUBSTRING("\"name\":\"CompileFunction\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_main\"", buffer);
-
-  // Heartbeat test for new events.
-  EXPECT_SUBSTRING("\"name\":\"TestVMDuration2\"", buffer);
-  EXPECT_SUBSTRING("\"function\":\"::_bar\"", buffer);
-}
-
-static bool start_called = false;
-static bool stop_called = false;
-
-static void StartRecording() {
-  start_called = true;
-}
-
-static void StopRecording() {
-  stop_called = true;
-}
-
-TEST_CASE(DartAPI_EmbedderTimelineStartStopRecording) {
-  Dart_SetEmbedderTimelineCallbacks(StartRecording, StopRecording);
-
-  EXPECT(!start_called);
-  EXPECT(!stop_called);
-  Timeline::SetStreamEmbedderEnabled(true);
-  EXPECT(start_called);
-  EXPECT(!stop_called);
-
-  start_called = false;
-  stop_called = false;
-  EXPECT(!start_called);
-  EXPECT(!stop_called);
-  Timeline::SetStreamEmbedderEnabled(false);
-  EXPECT(!start_called);
-  EXPECT(stop_called);
-}
-
 void NotifyIdleShortNative(Dart_NativeArguments args) {
   Dart_NotifyIdle(Dart_TimelineGetMicros() + 10 * kMicrosecondsPerMillisecond);
 }
diff --git a/runtime/vm/ffi_trampoline_stubs_x64.cc b/runtime/vm/ffi_trampoline_stubs_x64.cc
new file mode 100644
index 0000000..9374f61
--- /dev/null
+++ b/runtime/vm/ffi_trampoline_stubs_x64.cc
@@ -0,0 +1,564 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// TODO(dacoharkes): Move this into compiler namespace.
+
+#include "vm/globals.h"
+
+#include "vm/stub_code.h"
+
+#if defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/assembler/disassembler.h"
+#include "vm/compiler/backend/flow_graph_compiler.h"
+#include "vm/compiler/jit/compiler.h"
+#include "vm/constants_x64.h"
+#include "vm/dart_entry.h"
+#include "vm/heap/heap.h"
+#include "vm/heap/scavenger.h"
+#include "vm/instructions.h"
+#include "vm/object_store.h"
+#include "vm/resolver.h"
+#include "vm/stack_frame.h"
+#include "vm/tags.h"
+#include "vm/type_testing_stubs.h"
+
+#define __ assembler->
+
+namespace dart {
+
+static Representation TypeRepresentation(const AbstractType& result_type) {
+  switch (result_type.type_class_id()) {
+    case kFfiFloatCid:
+    case kFfiDoubleCid:
+      return kUnboxedDouble;
+    case kFfiInt8Cid:
+    case kFfiInt16Cid:
+    case kFfiInt32Cid:
+    case kFfiInt64Cid:
+    case kFfiUint8Cid:
+    case kFfiUint16Cid:
+    case kFfiUint32Cid:
+    case kFfiUint64Cid:
+    case kFfiIntPtrCid:
+    case kFfiPointerCid:
+    default:  // Subtypes of Pointer.
+      return kUnboxedInt64;
+  }
+}
+
+// Converts a Ffi [signature] to a list of Representations.
+// Note that this ignores first argument (receiver) which is dynamic.
+static ZoneGrowableArray<Representation>* ArgumentRepresentations(
+    const Function& signature) {
+  intptr_t num_arguments = signature.num_fixed_parameters() - 1;
+  auto result = new ZoneGrowableArray<Representation>(num_arguments);
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    AbstractType& arg_type =
+        AbstractType::Handle(signature.ParameterTypeAt(i + 1));
+    result->Add(TypeRepresentation(arg_type));
+  }
+  return result;
+}
+
+// Takes a list of argument representations, and converts it to a list of
+// argument locations based on calling convention.
+static ZoneGrowableArray<Location>* ArgumentLocations(
+    const ZoneGrowableArray<Representation>& arg_representations) {
+  intptr_t num_arguments = arg_representations.length();
+  auto result = new ZoneGrowableArray<Location>(num_arguments);
+  result->FillWith(Location(), 0, num_arguments);
+  Location* data = result->data();
+
+  // Loop through all arguments and assign a register or a stack location.
+  intptr_t int_regs_used = 0;
+  intptr_t xmm_regs_used = 0;
+  intptr_t nth_stack_argument = 0;
+  bool on_stack;
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    on_stack = true;
+    switch (arg_representations.At(i)) {
+      case kUnboxedInt64:
+        if (int_regs_used < CallingConventions::kNumArgRegs) {
+          data[i] = Location::RegisterLocation(
+              CallingConventions::ArgumentRegisters[int_regs_used]);
+          int_regs_used++;
+          if (CallingConventions::kArgumentIntRegXorXmmReg) {
+            xmm_regs_used++;
+          }
+          on_stack = false;
+        }
+        break;
+      case kUnboxedDouble:
+        if (xmm_regs_used < CallingConventions::kNumXmmArgRegs) {
+          data[i] = Location::FpuRegisterLocation(
+              CallingConventions::XmmArgumentRegisters[xmm_regs_used]);
+          xmm_regs_used++;
+          if (CallingConventions::kArgumentIntRegXorXmmReg) {
+            int_regs_used++;
+          }
+          on_stack = false;
+        }
+        break;
+      default:
+        UNREACHABLE();
+    }
+    if (on_stack) {
+      data[i] = Location::StackSlot(nth_stack_argument, RSP);
+      nth_stack_argument++;
+    }
+  }
+  return result;
+}
+
+static intptr_t NumStackArguments(
+    const ZoneGrowableArray<Location>& locations) {
+  intptr_t num_arguments = locations.length();
+  intptr_t num_stack_arguments = 0;
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    if (locations.At(i).IsStackSlot()) {
+      num_stack_arguments++;
+    }
+  }
+  return num_stack_arguments;
+}
+
+// Input parameters:
+//   Register reg : a Null, or something else
+static void GenerateNotNullCheck(Assembler* assembler, Register reg) {
+  Label not_null;
+  Address throw_null_pointer_address =
+      Address(THR, Thread::OffsetFromThread(&kArgumentNullErrorRuntimeEntry));
+
+  __ CompareObject(reg, Object::null_object());
+  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
+
+  // TODO(dacoharkes): Create the message here and use
+  // kArgumentErrorRuntimeEntry to report which argument was null.
+  __ movq(CODE_REG, Address(THR, Thread::call_to_runtime_stub_offset()));
+  __ movq(RBX, throw_null_pointer_address);
+  __ movq(R10, Immediate(0));
+  __ call(Address(THR, Thread::call_to_runtime_entry_point_offset()));
+
+  __ Bind(&not_null);
+}
+
+// Saves an int64 in the thread so GC does not trip.
+//
+// Input parameters:
+//   Register src : a C int64
+static void GenerateSaveInt64GCSafe(Assembler* assembler, Register src) {
+  __ movq(Address(THR, Thread::unboxed_int64_runtime_arg_offset()), src);
+}
+
+// Loads an int64 from the thread.
+static void GenerateLoadInt64GCSafe(Assembler* assembler, Register dst) {
+  __ movq(dst, Address(THR, Thread::unboxed_int64_runtime_arg_offset()));
+}
+
+// Takes a Dart int and converts it to a C int64.
+//
+// Input parameters:
+//   Register reg : a Dart Null, Smi, or Mint
+// Output parameters:
+//   Register reg : a C int64
+// Invariant: keeps ArgumentRegisters and XmmArgumentRegisters intact
+void GenerateMarshalInt64(Assembler* assembler, Register reg) {
+  ASSERT(reg != TMP);
+  ASSERT((1 << TMP & CallingConventions::kArgumentRegisters) == 0);
+  Label done, not_smi;
+
+  // Exception on Null
+  GenerateNotNullCheck(assembler, reg);
+
+  // Smi or Mint?
+  __ movq(TMP, reg);
+  __ testq(TMP, Immediate(kSmiTagMask));
+  __ j(NOT_ZERO, &not_smi, Assembler::kNearJump);
+
+  // Smi
+  __ SmiUntag(reg);
+  __ jmp(&done, Assembler::kNearJump);
+
+  // Mint
+  __ Bind(&not_smi);
+  __ movq(reg, FieldAddress(reg, Mint::value_offset()));
+  __ Bind(&done);
+}
+
+// Takes a C int64 and converts it to a Dart int.
+//
+// Input parameters:
+//   RAX : a C int64
+// Output paramaters:
+//   RAX : a Dart Smi or Mint
+static void GenerateUnmarshalInt64(Assembler* assembler) {
+  const Class& mint_class =
+      Class::ZoneHandle(Isolate::Current()->object_store()->mint_class());
+  ASSERT(!mint_class.IsNull());
+  const auto& mint_allocation_stub =
+      Code::ZoneHandle(StubCode::GetAllocationStubForClass(mint_class));
+  ASSERT(!mint_allocation_stub.IsNull());
+  Label done;
+
+  // Try whether it fits in a Smi.
+  __ movq(TMP, RAX);
+  __ SmiTag(RAX);
+  __ j(NO_OVERFLOW, &done, Assembler::kNearJump);
+
+  // Mint
+  // Backup result value (to avoid GC).
+  GenerateSaveInt64GCSafe(assembler, TMP);
+
+  // Allocate object (can call into runtime).
+  __ Call(mint_allocation_stub);
+
+  // Store result value.
+  GenerateLoadInt64GCSafe(assembler, TMP);
+  __ movq(FieldAddress(RAX, Mint::value_offset()), TMP);
+
+  __ Bind(&done);
+}
+
+// Takes a Dart double and converts it into a C double.
+//
+// Input parameters:
+//   Register reg : a Dart Null or Double
+// Output parameters:
+//   XmmRegister xmm_reg : a C double
+// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
+static void GenerateMarshalDouble(Assembler* assembler,
+                                  Register reg,
+                                  XmmRegister xmm_reg) {
+  ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
+
+  // Throw a Dart Exception on Null.
+  GenerateNotNullCheck(assembler, reg);
+
+  __ movq(reg, FieldAddress(reg, Double::value_offset()));
+  __ movq(xmm_reg, reg);
+}
+
+// Takes a C double and converts it into a Dart double.
+//
+// Input parameters:
+//   XMM0 : a C double
+// Output parameters:
+//   RAX : a Dart Double
+static void GenerateUnmarshalDouble(Assembler* assembler) {
+  const auto& double_class =
+      Class::ZoneHandle(Isolate::Current()->object_store()->double_class());
+  ASSERT(!double_class.IsNull());
+  const auto& double_allocation_stub =
+      Code::ZoneHandle(StubCode::GetAllocationStubForClass(double_class));
+  ASSERT(!double_allocation_stub.IsNull());
+
+  // Backup result value (to avoid GC).
+  __ movq(RAX, XMM0);
+  GenerateSaveInt64GCSafe(assembler, RAX);
+
+  // Allocate object (can call into runtime).
+  __ Call(double_allocation_stub);
+
+  // Store the result value.
+  GenerateLoadInt64GCSafe(assembler, TMP);
+  __ movq(FieldAddress(RAX, Double::value_offset()), TMP);
+}
+
+// Takes a Dart double and converts into a C float.
+//
+// Input parameters:
+//   Register reg : a Dart double
+// Output parameters:
+//   XmmRegister xxmReg : a C float
+// Invariant: keeps ArgumentRegisters and other XmmArgumentRegisters intact
+static void GenerateMarshalFloat(Assembler* assembler,
+                                 Register reg,
+                                 XmmRegister xmm_reg) {
+  ASSERT((1 << reg & CallingConventions::kArgumentRegisters) == 0);
+
+  GenerateMarshalDouble(assembler, reg, xmm_reg);
+
+  __ cvtsd2ss(xmm_reg, xmm_reg);
+}
+
+// Takes a C float and converts it into a Dart double.
+//
+// Input parameters:
+//   XMM0 : a C float
+// Output paramaters:
+//   RAX : a Dart Double
+static void GenerateUnmarshalFloat(Assembler* assembler) {
+  __ cvtss2sd(XMM0, XMM0);
+  GenerateUnmarshalDouble(assembler);
+}
+
+// Takes a Dart ffi.Pointer and converts it into a C pointer.
+//
+// Input parameters:
+//   Register reg : a Dart ffi.Pointer or Null
+// Output parameters:
+//   Register reg : a C pointer
+static void GenerateMarshalPointer(Assembler* assembler, Register reg) {
+  Label done, not_null;
+
+  __ CompareObject(reg, Object::null_object());
+  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
+
+  // If null, the address is 0.
+  __ movq(reg, Immediate(0));
+  __ jmp(&done);
+
+  // If not null but a Pointer, load the address.
+  __ Bind(&not_null);
+  __ movq(reg, FieldAddress(reg, Pointer::address_offset()));
+  __ Bind(&done);
+}
+
+// Takes a C pointer and converts it into a Dart ffi.Pointer or Null.
+//
+// Input parameters:
+//   RAX : a C pointer
+// Outpot paramaters:
+//   RAX : a Dart ffi.Pointer or Null
+static void GenerateUnmarshalPointer(Assembler* assembler,
+                                     Address closure_dart,
+                                     const Class& pointer_class) {
+  Label done, not_null;
+  ASSERT(!pointer_class.IsNull());
+  const auto& pointer_allocation_stub =
+      Code::ZoneHandle(StubCode::GetAllocationStubForClass(pointer_class));
+  ASSERT(!pointer_allocation_stub.IsNull());
+
+  // If the address is 0, return a Dart Null.
+  __ cmpq(RAX, Immediate(0));
+  __ j(NOT_EQUAL, &not_null, Assembler::kNearJump);
+  __ LoadObject(RAX, Object::null_object());
+  __ jmp(&done);
+
+  // Backup result value (to avoid GC).
+  __ Bind(&not_null);
+  GenerateSaveInt64GCSafe(assembler, RAX);
+
+  // Allocate object (can call into runtime).
+  __ movq(TMP, closure_dart);
+  __ movq(TMP, FieldAddress(TMP, Closure::function_offset()));
+  __ movq(TMP, FieldAddress(TMP, Function::result_type_offset()));
+  __ pushq(FieldAddress(TMP, Type::arguments_offset()));
+  __ Call(pointer_allocation_stub);
+  __ popq(TMP);  // Pop type arguments.
+
+  // Store the result value.
+  GenerateLoadInt64GCSafe(assembler, RDX);
+  __ movq(FieldAddress(RAX, Pointer::address_offset()), RDX);
+  __ Bind(&done);
+}
+
+static void GenerateMarshalArgument(Assembler* assembler,
+                                    const AbstractType& arg_type,
+                                    Register reg,
+                                    XmmRegister xmm_reg) {
+  switch (arg_type.type_class_id()) {
+    case kFfiInt8Cid:
+    case kFfiInt16Cid:
+    case kFfiInt32Cid:
+    case kFfiInt64Cid:
+    case kFfiUint8Cid:
+    case kFfiUint16Cid:
+    case kFfiUint32Cid:
+    case kFfiUint64Cid:
+    case kFfiIntPtrCid:
+      // TODO(dacoharkes): Truncate and sign extend 8 bit and 16 bit, and write
+      // tests. https://github.com/dart-lang/sdk/issues/35787
+      GenerateMarshalInt64(assembler, reg);
+      return;
+    case kFfiFloatCid:
+      GenerateMarshalFloat(assembler, reg, xmm_reg);
+      return;
+    case kFfiDoubleCid:
+      GenerateMarshalDouble(assembler, reg, xmm_reg);
+      return;
+    case kFfiPointerCid:
+    default:  // Subtypes of Pointer.
+      GenerateMarshalPointer(assembler, reg);
+      return;
+  }
+}
+
+static void GenerateUnmarshalResult(Assembler* assembler,
+                                    const AbstractType& result_type,
+                                    Address closure_dart) {
+  switch (result_type.type_class_id()) {
+    case kFfiInt8Cid:
+    case kFfiInt16Cid:
+    case kFfiInt32Cid:
+    case kFfiInt64Cid:
+    case kFfiUint8Cid:
+    case kFfiUint16Cid:
+    case kFfiUint32Cid:
+    case kFfiUint64Cid:
+    case kFfiIntPtrCid:
+      GenerateUnmarshalInt64(assembler);
+      return;
+    case kFfiFloatCid:
+      GenerateUnmarshalFloat(assembler);
+      return;
+    case kFfiDoubleCid:
+      GenerateUnmarshalDouble(assembler);
+      return;
+    case kFfiPointerCid:
+    default:  // subtypes of Pointer
+      break;
+  }
+  Class& cls = Class::ZoneHandle(Thread::Current()->zone(),
+                                 Type::Cast(result_type).type_class());
+
+  GenerateUnmarshalPointer(assembler, closure_dart, cls);
+}
+
+// Generates a assembly for dart:ffi trampolines:
+// - marshal arguments
+// - put the arguments in registers and on the c stack
+// - invoke the c function
+// - (c result register is the same as dart, so keep in place)
+// - unmarshal c result
+// - return
+//
+// Input parameters:
+//   RSP + kWordSize *  num_arguments      : closure.
+//   RSP + kWordSize * (num_arguments - 1) : arg 1.
+//   RSP + kWordSize * (num_arguments - 2) : arg 2.
+//   RSP + kWordSize                       : arg n.
+// After entering stub:
+//   RBP = RSP (before stub) - kWordSize
+//   RBP + kWordSize * (num_arguments + 1) : closure.
+//   RBP + kWordSize *  num_arguments      : arg 1.
+//   RBP + kWordSize * (num_arguments - 1) : arg 2.
+//   RBP + kWordSize *  2                  : arg n.
+//
+// TODO(dacoharkes): Test truncation on non 64 bits ints and floats.
+void GenerateFfiTrampoline(Assembler* assembler, const Function& signature) {
+  ZoneGrowableArray<Representation>* arg_representations =
+      ArgumentRepresentations(signature);
+  ZoneGrowableArray<Location>* arg_locations =
+      ArgumentLocations(*arg_representations);
+
+  intptr_t num_dart_arguments = signature.num_fixed_parameters();
+  intptr_t num_arguments = num_dart_arguments - 1;  // ignore closure
+
+  __ EnterStubFrame();
+
+  // Save exit frame information to enable stack walking as we are about
+  // to transition to Dart VM C++ code.
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), RBP);
+
+#if defined(DEBUG)
+  {
+    Label ok;
+    // Check that we are always entering from Dart code.
+    __ movq(TMP, Immediate(VMTag::kDartCompiledTagId));
+    __ cmpq(TMP, Assembler::VMTagAddress());
+    __ j(EQUAL, &ok, Assembler::kNearJump);
+    __ Stop("Not coming from Dart code.");
+    __ Bind(&ok);
+  }
+#endif
+
+  // Reserve space for arguments and align frame before entering C++ world.
+  __ subq(RSP, Immediate(NumStackArguments(*arg_locations) * kWordSize));
+  if (OS::ActivationFrameAlignment() > 1) {
+    __ andq(RSP, Immediate(~(OS::ActivationFrameAlignment() - 1)));
+  }
+
+  // Prepare address for calling the C function.
+  Address closure_dart = Address(RBP, (num_dart_arguments + 1) * kWordSize);
+  __ movq(RBX, closure_dart);
+  __ movq(RBX, FieldAddress(RBX, Closure::context_offset()));
+  __ movq(RBX, FieldAddress(RBX, Context::variable_offset(0)));
+  GenerateMarshalInt64(assembler, RBX);  // Address is a Smi or Mint.
+
+  // Marshal arguments and store in the right register.
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    Representation rep = arg_representations->At(i);
+    Location loc = arg_locations->At(i);
+
+    // We do marshalling in the the target register or in RAX.
+    Register reg = loc.IsRegister() ? loc.reg() : RAX;
+    // For doubles and floats we use target xmm register or first non param reg.
+    FpuRegister xmm_reg = loc.IsFpuRegister()
+                              ? loc.fpu_reg()
+                              : CallingConventions::xmmFirstNonParameterReg;
+
+    // Load parameter from Dart stack.
+    __ movq(reg, Address(RBP, (num_arguments + 1 - i) * kWordSize));
+
+    // Marshal argument.
+    AbstractType& arg_type =
+        AbstractType::Handle(signature.ParameterTypeAt(i + 1));
+    GenerateMarshalArgument(assembler, arg_type, reg, xmm_reg);
+
+    // Store marshalled argument where c expects value.
+    if (loc.IsStackSlot()) {
+      if (rep == kUnboxedDouble) {
+        __ movq(reg, xmm_reg);
+      }
+      __ movq(loc.ToStackSlotAddress(), reg);
+    }
+  }
+
+  // Mark that the thread is executing VM code.
+  __ movq(Assembler::VMTagAddress(), RBX);
+
+  __ CallCFunction(RBX);
+
+  // Mark that the thread is executing Dart code.
+  __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
+
+  // Unmarshal result.
+  AbstractType& return_type = AbstractType::Handle(signature.result_type());
+  GenerateUnmarshalResult(assembler, return_type, closure_dart);
+
+  // Reset exit frame information in Isolate structure.
+  __ movq(Address(THR, Thread::top_exit_frame_info_offset()), Immediate(0));
+
+  __ LeaveStubFrame();
+
+  __ ret();
+}
+
+void GenerateFfiInverseTrampoline(Assembler* assembler,
+                                  const Function& signature,
+                                  void* dart_entry_point) {
+  ZoneGrowableArray<Representation>* arg_representations =
+      ArgumentRepresentations(signature);
+  ZoneGrowableArray<Location>* arg_locations =
+      ArgumentLocations(*arg_representations);
+
+  intptr_t num_dart_arguments = signature.num_fixed_parameters();
+  intptr_t num_arguments = num_dart_arguments - 1;  // Ignore closure.
+
+  // TODO(dacoharkes): Implement this.
+  // https://github.com/dart-lang/sdk/issues/35761
+  // Look at StubCode::GenerateInvokeDartCodeStub.
+
+  __ int3();
+
+  for (intptr_t i = 0; i < num_arguments; i++) {
+    Register reg = arg_locations->At(i).reg();
+    __ SmiTag(reg);
+  }
+
+  __ movq(RBX, Immediate(reinterpret_cast<intptr_t>(dart_entry_point)));
+
+  __ int3();
+
+  __ call(RBX);
+
+  __ int3();
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/flag_list.h b/runtime/vm/flag_list.h
index ab60d21..edd0226 100644
--- a/runtime/vm/flag_list.h
+++ b/runtime/vm/flag_list.h
@@ -92,6 +92,7 @@
     "Compile expressions with the Kernel front-end.")                          \
   P(enable_mirrors, bool, true,                                                \
     "Disable to make importing dart:mirrors an error.")                        \
+  P(enable_ffi, bool, true, "Disable to make importing dart:ffi an error.")    \
   P(fields_may_be_reset, bool, false,                                          \
     "Don't optimize away static field initialization")                         \
   C(force_clone_compiler_objects, false, false, bool, false,                   \
@@ -126,6 +127,8 @@
     "Initial size of new gen semi space in MB")                                \
   P(optimization_counter_threshold, int, 30000,                                \
     "Function's usage-counter value before it is optimized, -1 means never")   \
+  P(optimization_level, int, 2,                                                \
+    "Optimization level: 1 (favor size), 2 (default), 3 (favor speed)")        \
   P(old_gen_heap_size, int, kDefaultMaxOldGenHeapSize,                         \
     "Max size of old gen heap size in MB, or 0 for unlimited,"                 \
     "e.g: --old_gen_heap_size=1024 allows up to 1024MB old gen heap")          \
diff --git a/runtime/vm/frame_layout.h b/runtime/vm/frame_layout.h
index f77da40..53ddcc7 100644
--- a/runtime/vm/frame_layout.h
+++ b/runtime/vm/frame_layout.h
@@ -38,6 +38,9 @@
   // The offset (in words) from FP to the code object (if applicable).
   int code_from_fp;
 
+  // Entry and exit frame layout.
+  int exit_link_slot_from_entry_fp;
+
   // The number of fixed slots below the saved PC.
   int saved_below_pc() const { return -first_local_from_fp; }
 
diff --git a/runtime/vm/heap/become.cc b/runtime/vm/heap/become.cc
index 74a72dd..1b1823a 100644
--- a/runtime/vm/heap/become.cc
+++ b/runtime/vm/heap/become.cc
@@ -60,7 +60,7 @@
 }
 
 static void ForwardObjectTo(RawObject* before_obj, RawObject* after_obj) {
-  const intptr_t size_before = before_obj->Size();
+  const intptr_t size_before = before_obj->HeapSize();
 
   uword corpse_addr = reinterpret_cast<uword>(before_obj) - kHeapObjectTag;
   ForwardingCorpse* forwarder =
@@ -70,7 +70,7 @@
     FATAL("become: ForwardObjectTo failure.");
   }
   // Still need to be able to iterate over the forwarding corpse.
-  const intptr_t size_after = before_obj->Size();
+  const intptr_t size_after = before_obj->HeapSize();
   if (size_before != size_after) {
     FATAL("become: Before and after sizes do not match.");
   }
diff --git a/runtime/vm/heap/become.h b/runtime/vm/heap/become.h
index 20804ea..1b27798 100644
--- a/runtime/vm/heap/become.h
+++ b/runtime/vm/heap/become.h
@@ -25,7 +25,7 @@
   RawObject* target() const { return target_; }
   void set_target(RawObject* target) { target_ = target; }
 
-  intptr_t Size() {
+  intptr_t HeapSize() {
     intptr_t size = RawObject::SizeTag::decode(tags_);
     if (size != 0) return size;
     return *SizeAddress();
diff --git a/runtime/vm/heap/compactor.cc b/runtime/vm/heap/compactor.cc
index 6855871..e3073a0 100644
--- a/runtime/vm/heap/compactor.cc
+++ b/runtime/vm/heap/compactor.cc
@@ -425,7 +425,7 @@
   uword current = first_object;
   while (current < block_end) {
     RawObject* obj = RawObject::FromAddr(current);
-    intptr_t size = obj->Size();
+    intptr_t size = obj->HeapSize();
     if (obj->IsMarked()) {
       forwarding_block->RecordLive(current, size);
       ASSERT(static_cast<intptr_t>(forwarding_block->Lookup(current)) ==
@@ -455,7 +455,7 @@
   uword old_addr = first_object;
   while (old_addr < block_end) {
     RawObject* old_obj = RawObject::FromAddr(old_addr);
-    intptr_t size = old_obj->Size();
+    intptr_t size = old_obj->HeapSize();
     if (old_obj->IsMarked()) {
       uword new_addr = forwarding_block->Lookup(old_addr);
       if (new_addr != free_current_) {
diff --git a/runtime/vm/heap/freelist.cc b/runtime/vm/heap/freelist.cc
index 0da39c2..cacb13e 100644
--- a/runtime/vm/heap/freelist.cc
+++ b/runtime/vm/heap/freelist.cc
@@ -97,7 +97,7 @@
         // the call to SplitElementAfterAndEnqueue.
         // If the remainder size is zero, only the element itself needs to
         // be made writable.
-        intptr_t remainder_size = element->Size() - size;
+        intptr_t remainder_size = element->HeapSize() - size;
         intptr_t region_size =
             size + FreeListElement::HeaderSizeFor(remainder_size);
         VirtualMemory::Protect(reinterpret_cast<void*>(element), region_size,
@@ -121,10 +121,10 @@
   // reset the search budget.
   intptr_t tries_left = freelist_search_budget_ + (size >> kWordSizeLog2);
   while (current != NULL) {
-    if (current->Size() >= size) {
+    if (current->HeapSize() >= size) {
       // Found an element large enough to hold the requested size. Dequeue,
       // split and enqueue the remainder.
-      intptr_t remainder_size = current->Size() - size;
+      intptr_t remainder_size = current->HeapSize() - size;
       intptr_t region_size =
           size + FreeListElement::HeaderSizeFor(remainder_size);
       if (is_protected) {
@@ -306,10 +306,10 @@
   MallocDirectChainedHashMap<NumbersKeyValueTrait<IntptrPair> > map;
   FreeListElement* node;
   for (node = free_lists_[kNumLists]; node != NULL; node = node->next()) {
-    IntptrPair* pair = map.Lookup(node->Size());
+    IntptrPair* pair = map.Lookup(node->HeapSize());
     if (pair == NULL) {
       large_sizes += 1;
-      map.Insert(IntptrPair(node->Size(), 1));
+      map.Insert(IntptrPair(node->HeapSize(), 1));
     } else {
       pair->set_second(pair->second() + 1);
     }
@@ -345,7 +345,7 @@
   // Precondition required by AsElement and EnqueueElement: either
   // element->Size() == size, or else the (page containing the) header of
   // the remainder element starting at element + size is writable.
-  intptr_t remainder_size = element->Size() - size;
+  intptr_t remainder_size = element->HeapSize() - size;
   if (remainder_size == 0) return;
 
   uword remainder_address = reinterpret_cast<uword>(element) + size;
@@ -379,7 +379,7 @@
       freelist_search_budget_ + (minimum_size >> kWordSizeLog2);
   while (current != NULL) {
     FreeListElement* next = current->next();
-    if (current->Size() >= minimum_size) {
+    if (current->HeapSize() >= minimum_size) {
       if (previous == NULL) {
         free_lists_[kNumLists] = next;
       } else {
diff --git a/runtime/vm/heap/freelist.h b/runtime/vm/heap/freelist.h
index 26f2c9b..552c7a2 100644
--- a/runtime/vm/heap/freelist.h
+++ b/runtime/vm/heap/freelist.h
@@ -27,7 +27,7 @@
 
   void set_next(FreeListElement* next) { next_ = next; }
 
-  intptr_t Size() {
+  intptr_t HeapSize() {
     intptr_t size = RawObject::SizeTag::decode(tags_);
     if (size != 0) return size;
     return *SizeAddress();
diff --git a/runtime/vm/heap/heap.cc b/runtime/vm/heap/heap.cc
index c9fafe3..b6b1960 100644
--- a/runtime/vm/heap/heap.cc
+++ b/runtime/vm/heap/heap.cc
@@ -71,7 +71,7 @@
   if (size >= kObjectAlignment) {
     // ForwardingCorpse(forwarding to default null) will work as filler.
     ForwardingCorpse::AsForwarder(start, size);
-    ASSERT(RawObject::FromAddr(start)->Size() == size);
+    ASSERT(RawObject::FromAddr(start)->HeapSize() == size);
   }
 }
 
@@ -91,7 +91,7 @@
     return addr;
   }
 
-  intptr_t tlab_size = CalculateTLABSize();
+  intptr_t tlab_size = GetTLABSize();
   if ((tlab_size > 0) && (size > tlab_size)) {
     return AllocateOld(size, HeapPage::kData);
   }
@@ -101,8 +101,11 @@
     uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
     if (tlab_top != 0) {
       addr = new_space_.TryAllocateInTLAB(thread, size);
-      ASSERT(addr != 0);
-      return addr;
+      if (addr != 0) {  // but "leftover" TLAB could end smaller than tlab_size
+        return addr;
+      }
+      // Abandon "leftover" TLAB as well so we can start from scratch.
+      AbandonRemainingTLAB(thread);
     }
   }
 
@@ -112,7 +115,7 @@
   // from a different thread and will be racing to allocate the requested
   // memory with other threads being released after the collection.
   CollectGarbage(kNew);
-  tlab_size = CalculateTLABSize();
+
   uword tlab_top = new_space_.TryAllocateNewTLAB(thread, tlab_size);
   if (tlab_top != 0) {
     addr = new_space_.TryAllocateInTLAB(thread, size);
diff --git a/runtime/vm/heap/heap.h b/runtime/vm/heap/heap.h
index 05fd87c..7cdb876 100644
--- a/runtime/vm/heap/heap.h
+++ b/runtime/vm/heap/heap.h
@@ -285,7 +285,7 @@
 
   static const intptr_t kNewAllocatableSize = 256 * KB;
 
-  intptr_t CalculateTLABSize() {
+  intptr_t GetTLABSize() {
     // Inspired by V8 tlab size. More than threshold for old space allocation,
     // less then minimal(initial) new semi-space.
     const intptr_t size = 512 * KB;
diff --git a/runtime/vm/heap/marker.cc b/runtime/vm/heap/marker.cc
index cda05d6..c246f43 100644
--- a/runtime/vm/heap/marker.cc
+++ b/runtime/vm/heap/marker.cc
@@ -310,7 +310,7 @@
         !raw_key->IsMarked()) {
       // Key was white. Enqueue the weak property.
       EnqueueWeakProperty(raw_weak);
-      return raw_weak->Size();
+      return raw_weak->HeapSize();
     }
     // Key is gray or black. Make the weak property black.
     return raw_weak->VisitPointersNonvirtual(this);
@@ -322,7 +322,7 @@
       ASSERT(raw_obj->IsInstructions());
       RawInstructions* instr = static_cast<RawInstructions*>(raw_obj);
       if (TryAcquireMarkBit(instr)) {
-        intptr_t size = instr->Size();
+        intptr_t size = instr->HeapSize();
         marked_bytes_ += size;
         NOT_IN_PRODUCT(UpdateLiveOld(kInstructionsCid, size));
       }
@@ -368,12 +368,6 @@
   }
 
   static bool TryAcquireMarkBit(RawObject* raw_obj) {
-    // While it might seem this is redundant with TryAcquireMarkBit, we must
-    // do this check first to avoid attempting an atomic::fetch_and on the
-    // read-only vm-isolate or image pages, which can fault even if there is no
-    // change in the value.
-    if (raw_obj->IsMarked()) return false;
-
     if (!sync) {
       raw_obj->SetMarkBitUnsynchronized();
       return true;
@@ -383,17 +377,28 @@
   }
 
   void MarkObject(RawObject* raw_obj) {
-    // Fast exit if the raw object is a Smi.
+    // Fast exit if the raw object is immediate or in new space. No memory
+    // access.
     if (raw_obj->IsSmiOrNewObject()) {
       return;
     }
 
+    // While it might seem this is redundant with TryAcquireMarkBit, we must
+    // do this check first to avoid attempting an atomic::fetch_and on the
+    // read-only vm-isolate or image pages, which can fault even if there is no
+    // change in the value.
+    // Doing this before checking for an Instructions object avoids
+    // unnecessary queueing of pre-marked objects.
+    if (raw_obj->IsMarked()) {
+      return;
+    }
+
     intptr_t class_id = raw_obj->GetClassId();
     ASSERT(class_id != kFreeListElement);
 
     if (sync && UNLIKELY(class_id == kInstructionsCid)) {
-      // If this is the concurrent marker, instruction pages may be
-      // non-writable.
+      // If this is the concurrent marker, this object may be non-writable due
+      // to W^X (--write-protect-code).
       deferred_work_list_.Push(raw_obj);
       return;
     }
@@ -519,22 +524,50 @@
   store_buffer->PushBlock(writing, StoreBuffer::kIgnoreThreshold);
 }
 
-void GCMarker::IterateRoots(ObjectPointerVisitor* visitor,
-                            intptr_t slice_index,
-                            intptr_t num_slices) {
-  ASSERT(0 <= slice_index && slice_index < num_slices);
-  if ((slice_index == 0) || (num_slices <= 1)) {
-    TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessRoots");
-    isolate_->VisitObjectPointers(visitor,
-                                  ValidationPolicy::kDontValidateFrames);
-  }
-  if ((slice_index == 1) || (num_slices <= 1)) {
-    TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessNewSpace");
-    heap_->new_space()->VisitObjectPointers(visitor);
-  }
+enum RootSlices {
+  kIsolate = 0,
+  kNewSpace = 1,
+  kNumRootSlices = 2,
+};
 
-  // For now, we just distinguish two parts of the root set, so any remaining
-  // slices are empty.
+void GCMarker::ResetRootSlices() {
+  root_slices_not_started_ = kNumRootSlices;
+  root_slices_not_finished_ = kNumRootSlices;
+}
+
+void GCMarker::IterateRoots(ObjectPointerVisitor* visitor) {
+  for (;;) {
+    intptr_t task =
+        AtomicOperations::FetchAndDecrement(&root_slices_not_started_) - 1;
+    if (task < 0) {
+      return;  // No more tasks.
+    }
+
+    switch (task) {
+      case kIsolate: {
+        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessRoots");
+        isolate_->VisitObjectPointers(visitor,
+                                      ValidationPolicy::kDontValidateFrames);
+        break;
+      }
+      case kNewSpace: {
+        TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ProcessNewSpace");
+        heap_->new_space()->VisitObjectPointers(visitor);
+        break;
+      }
+      default:
+        FATAL1("%" Pd, task);
+        UNREACHABLE();
+    }
+
+    intptr_t remaining =
+        AtomicOperations::FetchAndDecrement(&root_slices_not_finished_) - 1;
+    if (remaining == 0) {
+      MonitorLocker ml(&root_slices_monitor_);
+      ml.Notify();
+      return;
+    }
+  }
 }
 
 void GCMarker::IterateWeakRoots(HandleVisitor* visitor) {
@@ -596,16 +629,12 @@
                    MarkingStack* marking_stack,
                    ThreadBarrier* barrier,
                    SyncMarkingVisitor* visitor,
-                   intptr_t task_index,
-                   intptr_t num_tasks,
                    uintptr_t* num_busy)
       : marker_(marker),
         isolate_(isolate),
         marking_stack_(marking_stack),
         barrier_(barrier),
         visitor_(visitor),
-        task_index_(task_index),
-        num_tasks_(num_tasks),
         num_busy_(num_busy) {}
 
   virtual void Run() {
@@ -617,7 +646,7 @@
       int64_t start = OS::GetCurrentMonotonicMicros();
 
       // Phase 1: Iterate over roots and drain marking stack in tasks.
-      marker_->IterateRoots(visitor_, task_index_, num_tasks_);
+      marker_->IterateRoots(visitor_);
 
       bool more_to_mark = false;
       do {
@@ -681,9 +710,8 @@
       int64_t stop = OS::GetCurrentMonotonicMicros();
       visitor_->AddMicros(stop - start);
       if (FLAG_log_marker_tasks) {
-        THR_Print("Task %" Pd " marked %" Pd " bytes in %" Pd64 " micros.\n",
-                  task_index_, visitor_->marked_bytes(),
-                  visitor_->marked_micros());
+        THR_Print("Task marked %" Pd " bytes in %" Pd64 " micros.\n",
+                  visitor_->marked_bytes(), visitor_->marked_micros());
       }
       marker_->FinalizeResultsFrom(visitor_);
 
@@ -701,8 +729,6 @@
   MarkingStack* marking_stack_;
   ThreadBarrier* barrier_;
   SyncMarkingVisitor* visitor_;
-  const intptr_t task_index_;
-  const intptr_t num_tasks_;
   uintptr_t* num_busy_;
 
   DISALLOW_COPY_AND_ASSIGN(ParallelMarkTask);
@@ -713,19 +739,11 @@
   ConcurrentMarkTask(GCMarker* marker,
                      Isolate* isolate,
                      PageSpace* page_space,
-                     SyncMarkingVisitor* visitor,
-                     intptr_t task_index,
-                     intptr_t num_tasks,
-                     Monitor* roots_monitor,
-                     intptr_t* root_tasks_remaining)
+                     SyncMarkingVisitor* visitor)
       : marker_(marker),
         isolate_(isolate),
         page_space_(page_space),
-        visitor_(visitor),
-        task_index_(task_index),
-        num_tasks_(num_tasks),
-        roots_monitor_(roots_monitor),
-        root_tasks_remaining_(root_tasks_remaining) {
+        visitor_(visitor) {
 #if defined(DEBUG)
     MonitorLocker ml(page_space_->tasks_lock());
     ASSERT(page_space_->phase() == PageSpace::kMarking);
@@ -740,20 +758,14 @@
       TIMELINE_FUNCTION_GC_DURATION(Thread::Current(), "ConcurrentMark");
       int64_t start = OS::GetCurrentMonotonicMicros();
 
-      marker_->IterateRoots(visitor_, task_index_, num_tasks_);
-      {
-        MonitorLocker ml(roots_monitor_);
-        (*root_tasks_remaining_)--;
-        ml.Notify();
-      }
+      marker_->IterateRoots(visitor_);
 
       visitor_->DrainMarkingStack();
       int64_t stop = OS::GetCurrentMonotonicMicros();
       visitor_->AddMicros(stop - start);
       if (FLAG_log_marker_tasks) {
-        THR_Print("Task %" Pd " marked %" Pd " bytes in %" Pd64 " micros.\n",
-                  task_index_, visitor_->marked_bytes(),
-                  visitor_->marked_micros());
+        THR_Print("Task marked %" Pd " bytes in %" Pd64 " micros.\n",
+                  visitor_->marked_bytes(), visitor_->marked_micros());
       }
     }
 
@@ -779,10 +791,6 @@
   Isolate* isolate_;
   PageSpace* page_space_;
   SyncMarkingVisitor* visitor_;
-  const intptr_t task_index_;
-  const intptr_t num_tasks_;
-  Monitor* const roots_monitor_;
-  intptr_t* root_tasks_remaining_;
 
   DISALLOW_COPY_AND_ASSIGN(ConcurrentMarkTask);
 };
@@ -869,8 +877,7 @@
         page_space->concurrent_marker_tasks() + num_tasks);
   }
 
-  Monitor roots_monitor;
-  intptr_t root_tasks_remaining = num_tasks;
+  ResetRootSlices();
   for (intptr_t i = 0; i < num_tasks; i++) {
     ASSERT(visitors_[i] == NULL);
     SkippedCodeFunctions* skipped_code_functions =
@@ -880,15 +887,14 @@
                                           skipped_code_functions);
 
     // Begin marking on a helper thread.
-    bool result = Dart::thread_pool()->Run(new ConcurrentMarkTask(
-        this, isolate_, page_space, visitors_[i], i, num_tasks, &roots_monitor,
-        &root_tasks_remaining));
+    bool result = Dart::thread_pool()->Run(
+        new ConcurrentMarkTask(this, isolate_, page_space, visitors_[i]));
     ASSERT(result);
   }
 
   // Wait for roots to be marked before exiting safepoint.
-  MonitorLocker ml(&roots_monitor);
-  while (root_tasks_remaining > 0) {
+  MonitorLocker ml(&root_slices_monitor_);
+  while (root_slices_not_finished_ > 0) {
     ml.Wait();
   }
 }
@@ -911,7 +917,8 @@
       UnsyncMarkingVisitor mark(isolate_, page_space, &marking_stack_,
                                 &deferred_marking_stack_,
                                 skipped_code_functions);
-      IterateRoots(&mark, 0, 1);
+      ResetRootSlices();
+      IterateRoots(&mark);
       mark.DrainMarkingStack();
       mark.FinalizeInstructions();
       {
@@ -926,6 +933,7 @@
     } else {
       ThreadBarrier barrier(num_tasks + 1, heap_->barrier(),
                             heap_->barrier_done());
+      ResetRootSlices();
       // Used to coordinate draining among tasks; all start out as 'busy'.
       uintptr_t num_busy = num_tasks;
       // Phase 1: Iterate over roots and drain marking stack in tasks.
@@ -942,9 +950,8 @@
               skipped_code_functions);
         }
 
-        bool result = Dart::thread_pool()->Run(
-            new ParallelMarkTask(this, isolate_, &marking_stack_, &barrier,
-                                 visitor, i, num_tasks, &num_busy));
+        bool result = Dart::thread_pool()->Run(new ParallelMarkTask(
+            this, isolate_, &marking_stack_, &barrier, visitor, &num_busy));
         ASSERT(result);
       }
       bool more_to_mark = false;
diff --git a/runtime/vm/heap/marker.h b/runtime/vm/heap/marker.h
index a95db6a..6108e21 100644
--- a/runtime/vm/heap/marker.h
+++ b/runtime/vm/heap/marker.h
@@ -47,9 +47,8 @@
  private:
   void Prologue();
   void Epilogue();
-  void IterateRoots(ObjectPointerVisitor* visitor,
-                    intptr_t slice_index,
-                    intptr_t num_slices);
+  void ResetRootSlices();
+  void IterateRoots(ObjectPointerVisitor* visitor);
   void IterateWeakRoots(HandleVisitor* visitor);
   template <class MarkingVisitorType>
   void IterateWeakReferences(MarkingVisitorType* visitor);
@@ -66,6 +65,10 @@
   MarkingStack deferred_marking_stack_;
   MarkingVisitorBase<true>** visitors_;
 
+  Monitor root_slices_monitor_;
+  intptr_t root_slices_not_started_;
+  intptr_t root_slices_not_finished_;
+
   Mutex stats_mutex_;
   uintptr_t marked_bytes_;
   int64_t marked_micros_;
diff --git a/runtime/vm/heap/pages.cc b/runtime/vm/heap/pages.cc
index d90c9ec..4ba70ca 100644
--- a/runtime/vm/heap/pages.cc
+++ b/runtime/vm/heap/pages.cc
@@ -113,7 +113,7 @@
   while (obj_addr < end_addr) {
     RawObject* raw_obj = RawObject::FromAddr(obj_addr);
     visitor->VisitObject(raw_obj);
-    obj_addr += raw_obj->Size();
+    obj_addr += raw_obj->HeapSize();
   }
   ASSERT(obj_addr == end_addr);
 }
@@ -197,7 +197,7 @@
   if (visitor->VisitRange(obj_addr, end_addr)) {
     while (obj_addr < end_addr) {
       RawObject* raw_obj = RawObject::FromAddr(obj_addr);
-      uword next_obj_addr = obj_addr + raw_obj->Size();
+      uword next_obj_addr = obj_addr + raw_obj->HeapSize();
       if (visitor->VisitRange(obj_addr, next_obj_addr) &&
           raw_obj->FindObject(visitor)) {
         return raw_obj;  // Found object, return it.
@@ -860,7 +860,7 @@
  public:
   explicit HeapMapAsJSONVisitor(JSONArray* array) : array_(array) {}
   virtual void VisitObject(RawObject* obj) {
-    array_->AddValue(obj->Size() / kObjectAlignment);
+    array_->AddValue(obj->HeapSize() / kObjectAlignment);
     array_->AddValue(obj->GetClassId());
   }
 
@@ -1297,7 +1297,7 @@
       return TryAllocateInFreshPage(size, HeapPage::kData, growth_policy,
                                     is_locked);
     }
-    intptr_t block_size = block->Size();
+    intptr_t block_size = block->HeapSize();
     if (remaining > 0) {
       if (is_locked) {
         freelist_[HeapPage::kData].FreeLocked(bump_top_, remaining);
@@ -1536,7 +1536,7 @@
   }
 }
 
-void PageSpaceController::EvaluateSnapshotLoad(SpaceUsage after) {
+void PageSpaceController::EvaluateAfterLoading(SpaceUsage after) {
   // Number of pages we can allocate and still be within the desired growth
   // ratio.
   intptr_t growth_in_pages =
@@ -1559,7 +1559,7 @@
 
   if (FLAG_log_growth) {
     THR_Print("%s: threshold=%" Pd "kB, idle_threshold=%" Pd
-              "kB, reason=snapshot\n",
+              "kB, reason=loaded\n",
               heap_->isolate()->name(), gc_threshold_in_words_ / KBInWords,
               idle_gc_threshold_in_words_ / KBInWords);
   }
diff --git a/runtime/vm/heap/pages.h b/runtime/vm/heap/pages.h
index 3020b92..321b0be 100644
--- a/runtime/vm/heap/pages.h
+++ b/runtime/vm/heap/pages.h
@@ -188,7 +188,7 @@
                                  SpaceUsage after,
                                  int64_t start,
                                  int64_t end);
-  void EvaluateSnapshotLoad(SpaceUsage after);
+  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) {
@@ -266,8 +266,8 @@
   bool AlmostNeedsGarbageCollection() const {
     return page_space_controller_.AlmostNeedsGarbageCollection(usage_);
   }
-  void EvaluateSnapshotLoad() {
-    page_space_controller_.EvaluateSnapshotLoad(usage_);
+  void EvaluateAfterLoading() {
+    page_space_controller_.EvaluateAfterLoading(usage_);
   }
 
   int64_t UsedInWords() const { return usage_.used_in_words; }
diff --git a/runtime/vm/heap/scavenger.cc b/runtime/vm/heap/scavenger.cc
index bd3240d..b6906ae 100644
--- a/runtime/vm/heap/scavenger.cc
+++ b/runtime/vm/heap/scavenger.cc
@@ -134,7 +134,7 @@
       // Get the new location of the object.
       new_addr = ForwardedAddr(header);
     } else {
-      intptr_t size = raw_obj->Size();
+      intptr_t size = raw_obj->HeapSize();
       NOT_IN_PRODUCT(intptr_t cid = raw_obj->GetClassId());
       NOT_IN_PRODUCT(ClassTable* class_table = isolate()->class_table());
       // Check whether object should be promoted.
@@ -768,7 +768,7 @@
     if (!IsForwarding(header)) {
       // Key is white.  Enqueue the weak property.
       EnqueueWeakProperty(raw_weak);
-      return raw_weak->Size();
+      return raw_weak->HeapSize();
     }
   }
   // Key is gray or black.  Make the weak property black.
@@ -892,7 +892,7 @@
   while (cur < top_) {
     RawObject* raw_obj = RawObject::FromAddr(cur);
     visitor->VisitObject(raw_obj);
-    cur += raw_obj->Size();
+    cur += raw_obj->HeapSize();
   }
 }
 
@@ -907,7 +907,7 @@
   if (visitor->VisitRange(cur, top_)) {
     while (cur < top_) {
       RawObject* raw_obj = RawObject::FromAddr(cur);
-      uword next = cur + raw_obj->Size();
+      uword next = cur + raw_obj->HeapSize();
       if (visitor->VisitRange(cur, next) && raw_obj->FindObject(visitor)) {
         return raw_obj;  // Found object, return it.
       }
@@ -926,6 +926,15 @@
   uword result = top_;
   intptr_t remaining = end_ - top_;
   if (remaining < size) {
+    // Grab whatever is remaining
+    size = remaining;
+  } else {
+    // Reduce TLAB size so we land at even TLAB size for future TLABs.
+    intptr_t survived_size = UsedInWords() * kWordSize;
+    size -= survived_size % size;
+  }
+  size = Utils::RoundDown(size, kObjectAlignment);
+  if (size == 0) {
     return 0;
   }
   ASSERT(to_->Contains(result));
diff --git a/runtime/vm/heap/sweeper.cc b/runtime/vm/heap/sweeper.cc
index 7474009..b1e385f 100644
--- a/runtime/vm/heap/sweeper.cc
+++ b/runtime/vm/heap/sweeper.cc
@@ -34,10 +34,10 @@
     if (raw_obj->IsMarked()) {
       // Found marked object. Clear the mark bit and update swept bytes.
       raw_obj->ClearMarkBit();
-      obj_size = raw_obj->Size();
+      obj_size = raw_obj->HeapSize();
       used_in_bytes += obj_size;
     } else {
-      uword free_end = current + raw_obj->Size();
+      uword free_end = current + raw_obj->HeapSize();
       while (free_end < end) {
         RawObject* next_obj = RawObject::FromAddr(free_end);
         if (next_obj->IsMarked()) {
@@ -45,7 +45,7 @@
           break;
         }
         // Expand the free block by the size of this object.
-        free_end += next_obj->Size();
+        free_end += next_obj->HeapSize();
       }
       obj_size = free_end - current;
       if (is_executable) {
@@ -86,17 +86,17 @@
   ASSERT(HeapPage::Of(raw_obj) == page);
   if (raw_obj->IsMarked()) {
     raw_obj->ClearMarkBit();
-    words_to_end = (raw_obj->Size() >> kWordSizeLog2);
+    words_to_end = (raw_obj->HeapSize() >> kWordSizeLog2);
   }
 #ifdef DEBUG
   // String::MakeExternal and Array::MakeFixedLength create trailing filler
   // objects, but they are always unreachable. Verify that they are not marked.
-  uword current = RawObject::ToAddr(raw_obj) + raw_obj->Size();
+  uword current = RawObject::ToAddr(raw_obj) + raw_obj->HeapSize();
   uword end = page->object_end();
   while (current < end) {
     RawObject* cur_obj = RawObject::FromAddr(current);
     ASSERT(!cur_obj->IsMarked());
-    intptr_t obj_size = cur_obj->Size();
+    intptr_t obj_size = cur_obj->HeapSize();
     memset(reinterpret_cast<void*>(current), Heap::kZapByte, obj_size);
     current += obj_size;
   }
diff --git a/runtime/vm/image_snapshot.cc b/runtime/vm/image_snapshot.cc
index 70adef8..838e2b7 100644
--- a/runtime/vm/image_snapshot.cc
+++ b/runtime/vm/image_snapshot.cc
@@ -43,7 +43,7 @@
   ASSERT(!obj->IsSmi());
 
   uword body = RawObject::ToAddr(obj) + sizeof(RawObject);
-  uword end = RawObject::ToAddr(obj) + obj->Size();
+  uword end = RawObject::ToAddr(obj) + obj->HeapSize();
 
   uint32_t hash = obj->GetClassId();
   // Don't include the header. Objects in the image are pre-marked, but objects
@@ -65,8 +65,8 @@
     return false;
   }
 
-  intptr_t heap_size = a->Size();
-  if (b->Size() != heap_size) {
+  intptr_t heap_size = a->HeapSize();
+  if (b->HeapSize() != heap_size) {
     return false;
   }
 
@@ -106,7 +106,7 @@
           RawInstructions* instructions = Code::InstructionsOf(code);
           const intptr_t offset = next_text_offset_;
           instructions_.Add(InstructionsData(instructions, code, offset));
-          next_text_offset_ += instructions->Size();
+          next_text_offset_ += instructions->HeapSize();
           ASSERT(heap_->GetObjectId(instructions) == 0);
           heap_->SetObjectId(instructions, offset);
           break;
@@ -141,7 +141,7 @@
     pair.object = raw_obj;
     pair.offset = offset;
     map->Insert(pair);
-    obj_addr += raw_obj->Size();
+    obj_addr += raw_obj->HeapSize();
   }
   ASSERT(obj_addr == end_addr);
 }
@@ -172,7 +172,7 @@
 
   offset = next_text_offset_;
   heap_->SetObjectId(instructions, offset);
-  next_text_offset_ += instructions->Size();
+  next_text_offset_ += instructions->HeapSize();
   instructions_.Add(InstructionsData(instructions, code, offset));
 
   return offset;
@@ -189,7 +189,7 @@
 }
 
 uint32_t ImageWriter::GetDataOffsetFor(RawObject* raw_object) {
-  intptr_t heap_size = raw_object->Size();
+  intptr_t heap_size = raw_object->HeapSize();
   intptr_t offset = next_data_offset_;
   next_data_offset_ += heap_size;
   objects_.Add(ObjectData(raw_object));
@@ -223,11 +223,6 @@
   js.OpenArray();
   for (intptr_t i = 0; i < instructions_.length(); i++) {
     auto& data = instructions_[i];
-    if (data.code_->IsNull()) {
-      // TODO(34650): Type testing stubs are added to the serializer without
-      // their Code.
-      continue;
-    }
     owner = data.code_->owner();
     js.OpenObject();
     if (owner.IsFunction()) {
@@ -239,7 +234,7 @@
       js.PrintPropertyStr("c", name);
     }
     js.PrintProperty("n", data.code_->QualifiedName());
-    js.PrintProperty("s", data.insns_->Size());
+    js.PrintProperty("s", data.insns_->raw()->HeapSize());
     js.CloseObject();
   }
   js.CloseArray();
@@ -334,7 +329,7 @@
 
     NoSafepointScope no_safepoint;
     uword start = reinterpret_cast<uword>(obj.raw()) - kHeapObjectTag;
-    uword end = start + obj.raw()->Size();
+    uword end = start + obj.raw()->HeapSize();
 
     // Write object header with the mark and VM heap bits set.
     uword marked_tags = obj.raw()->ptr()->tags_;
@@ -475,10 +470,10 @@
                                             "Instructions",
                                             /*name=*/nullptr);
       profile_writer_->AttributeBytesTo({offset_space_, offset},
-                                        insns.raw()->Size());
+                                        insns.raw()->HeapSize());
     }
 
-    ASSERT(insns.raw()->Size() % sizeof(uint64_t) == 0);
+    ASSERT(insns.raw()->HeapSize() % sizeof(uint64_t) == 0);
 
     // 1. Write from the header to the entry point.
     {
@@ -554,7 +549,7 @@
       NoSafepointScope no_safepoint;
       uword beginning = reinterpret_cast<uword>(insns.raw_ptr());
       uword entry = beginning + Instructions::HeaderSize();
-      uword payload_size = insns.raw()->Size() - insns.HeaderSize();
+      uword payload_size = insns.raw()->HeapSize() - insns.HeaderSize();
       uword end = entry + payload_size;
 
       ASSERT(Utils::IsAligned(beginning, sizeof(uword)));
@@ -564,7 +559,7 @@
       text_offset += WriteByteSequence(entry, end);
     }
 
-    ASSERT((text_offset - instr_start) == insns.raw()->Size());
+    ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
   }
 
   FrameUnwindEpilogue();
@@ -755,7 +750,7 @@
     beginning += sizeof(uword);
     text_offset += WriteByteSequence(beginning, end);
 
-    ASSERT((text_offset - instr_start) == insns.raw()->Size());
+    ASSERT((text_offset - instr_start) == insns.raw()->HeapSize());
   }
 }
 
diff --git a/runtime/vm/interpreter.cc b/runtime/vm/interpreter.cc
index 1e1c0f1..1500348 100644
--- a/runtime/vm/interpreter.cc
+++ b/runtime/vm/interpreter.cc
@@ -813,8 +813,7 @@
   callee_fp[kKBCSavedCallerPcSlotFromFp] = reinterpret_cast<RawObject*>(*pc);
   callee_fp[kKBCSavedCallerFpSlotFromFp] = reinterpret_cast<RawObject*>(*FP);
   pp_ = bytecode->ptr()->object_pool_;
-  *pc =
-      reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_->ptr()->data_);
+  *pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
   pc_ = reinterpret_cast<uword>(*pc);  // For the profiler.
   *FP = callee_fp;
   fp_ = callee_fp;  // For the profiler.
@@ -909,7 +908,7 @@
 
   const intptr_t kCheckedArgs = 1;
   RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+  RawArray* cache = icdata->ptr()->entries_->ptr();
 
   const intptr_t type_args_len =
       InterpreterHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
@@ -954,7 +953,7 @@
 
   const intptr_t kCheckedArgs = 2;
   RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+  RawArray* cache = icdata->ptr()->entries_->ptr();
 
   const intptr_t type_args_len =
       InterpreterHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
@@ -1388,8 +1387,7 @@
 
   // Ready to start executing bytecode. Load entry point and corresponding
   // object pool.
-  pc =
-      reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_->ptr()->data_);
+  pc = reinterpret_cast<uint32_t*>(bytecode->ptr()->instructions_);
   pc_ = reinterpret_cast<uword>(pc);  // For the profiler.
   fp_ = FP;                           // For the profiler.
   pp_ = bytecode->ptr()->object_pool_;
@@ -1805,12 +1803,14 @@
   {
     BYTECODE(IndirectStaticCall, A_D);
 
+#ifndef PRODUCT
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     // Invoke target function.
     {
@@ -1818,7 +1818,7 @@
       // Look up the function in the ICData.
       RawObject* ic_data_obj = SP[0];
       RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
-      RawObject** data = ic_data->ptr()->ic_data_->ptr()->data();
+      RawObject** data = ic_data->ptr()->entries_->ptr()->data();
       InterpreterHelpers::IncrementICUsageCount(data, 0, 0);
       SP[0] = data[ICData::TargetIndexFor(ic_data->ptr()->state_bits_ & 0x3)];
       RawObject** call_base = SP - argc;
@@ -1833,14 +1833,46 @@
   }
 
   {
-    BYTECODE(InterfaceCall, A_D);
+    BYTECODE(DirectCall, A_D);
 
+#ifndef PRODUCT
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
+
+    // Invoke target function.
+    {
+      const uint16_t argc = rA;
+      const uint16_t kidx = rD;
+
+      InterpreterHelpers::IncrementUsageCounter(FrameFunction(FP));
+      *++SP = LOAD_CONSTANT(kidx);
+      RawObject** call_base = SP - argc;
+      RawObject** call_top = SP;
+      argdesc_ = static_cast<RawArray*>(LOAD_CONSTANT(kidx + 1));
+      if (!Invoke(thread, call_base, call_top, &pc, &FP, &SP)) {
+        HANDLE_EXCEPTION;
+      }
+    }
+
+    DISPATCH();
+  }
+
+  {
+    BYTECODE(InterfaceCall, A_D);
+
+#ifndef PRODUCT
+    // Check if single stepping.
+    if (thread->isolate()->single_step()) {
+      Exit(thread, FP, SP + 1, pc);
+      NativeArguments args(thread, 0, NULL, NULL);
+      INVOKE_RUNTIME(DRT_SingleStepHandler, args);
+    }
+#endif  // !PRODUCT
 
     {
       const uint16_t argc = rA;
@@ -1864,12 +1896,14 @@
   {
     BYTECODE(DynamicCall, A_D);
 
+#ifndef PRODUCT
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     {
       const uint16_t argc = rA;
diff --git a/runtime/vm/isolate.h b/runtime/vm/isolate.h
index a7961bb..086831b 100644
--- a/runtime/vm/isolate.h
+++ b/runtime/vm/isolate.h
@@ -376,7 +376,6 @@
     ASSERT(debugger_ != NULL);
     return debugger_;
   }
-#endif
 
   void set_single_step(bool value) { single_step_ = value; }
   bool single_step() const { return single_step_; }
@@ -384,7 +383,6 @@
     return OFFSET_OF(Isolate, single_step_);
   }
 
-#if !defined(PRODUCT)
   bool ResumeRequest() const {
     return ResumeRequestBit::decode(isolate_flags_);
   }
diff --git a/runtime/vm/isolate_reload.cc b/runtime/vm/isolate_reload.cc
index 81b77be..381a50b 100644
--- a/runtime/vm/isolate_reload.cc
+++ b/runtime/vm/isolate_reload.cc
@@ -2269,10 +2269,14 @@
 
       interface_types = cls.interfaces();
       if (!interface_types.IsNull()) {
+        const intptr_t mixin_index = cls.is_transformed_mixin_application()
+                                         ? interface_types.Length() - 1
+                                         : -1;
         for (intptr_t j = 0; j < interface_types.Length(); ++j) {
           interface_type ^= interface_types.At(j);
           interface_class = interface_type.type_class();
-          interface_class.AddDirectImplementor(cls);
+          interface_class.AddDirectImplementor(
+              cls, /* is_mixin = */ i == mixin_index);
         }
       }
     }
diff --git a/runtime/vm/kernel.cc b/runtime/vm/kernel.cc
index c5d5442..edf12af 100644
--- a/runtime/vm/kernel.cc
+++ b/runtime/vm/kernel.cc
@@ -298,6 +298,7 @@
   auto& temp_function = Function::Handle(zone);
   for (intptr_t i = 0; i < libs.Length(); i++) {
     lib ^= libs.At(i);
+    lib.EnsureTopLevelClassIsFinalized();
     DictionaryIterator it(lib);
     while (it.HasNext()) {
       entry = it.GetNext();
diff --git a/runtime/vm/kernel_binary.h b/runtime/vm/kernel_binary.h
index 8473fec..85ed239 100644
--- a/runtime/vm/kernel_binary.h
+++ b/runtime/vm/kernel_binary.h
@@ -245,7 +245,12 @@
 
   intptr_t ReadSLEB128() {
     const uint8_t* buffer = this->buffer();
-    return Utils::DecodeSLEB128(buffer, size_, &offset_);
+    return Utils::DecodeSLEB128<intptr_t>(buffer, size_, &offset_);
+  }
+
+  int64_t ReadSLEB128AsInt64() {
+    const uint8_t* buffer = this->buffer();
+    return Utils::DecodeSLEB128<int64_t>(buffer, size_, &offset_);
   }
 
   /**
diff --git a/runtime/vm/kernel_loader.cc b/runtime/vm/kernel_loader.cc
index b94c500..9817832 100644
--- a/runtime/vm/kernel_loader.cc
+++ b/runtime/vm/kernel_loader.cc
@@ -112,6 +112,15 @@
   DISALLOW_COPY_AND_ASSIGN(SimpleExpressionConverter);
 };
 
+RawArray* KernelLoader::MakeFieldsArray() {
+  const intptr_t len = fields_.length();
+  const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
+  for (intptr_t i = 0; i < len; i++) {
+    res.SetAt(i, *fields_[i]);
+  }
+  return res.raw();
+}
+
 RawArray* KernelLoader::MakeFunctionsArray() {
   const intptr_t len = functions_.length();
   const Array& res = Array::Handle(zone_, Array::New(len, Heap::kOld));
@@ -185,7 +194,7 @@
               0),
       type_translator_(&helper_, &active_class_, /* finalize= */ false),
       inferred_type_metadata_helper_(&helper_),
-      bytecode_metadata_helper_(&helper_, &type_translator_, &active_class_),
+      bytecode_metadata_helper_(&helper_, &active_class_),
       external_name_class_(Class::Handle(Z)),
       external_name_field_(Field::Handle(Z)),
       potential_natives_(GrowableObjectArray::Handle(Z)),
@@ -370,7 +379,7 @@
       helper_(zone_, &translation_helper_, script, kernel_data, 0),
       type_translator_(&helper_, &active_class_, /* finalize= */ false),
       inferred_type_metadata_helper_(&helper_),
-      bytecode_metadata_helper_(&helper_, &type_translator_, &active_class_),
+      bytecode_metadata_helper_(&helper_, &active_class_),
       external_name_class_(Class::Handle(Z)),
       external_name_field_(Field::Handle(Z)),
       potential_natives_(GrowableObjectArray::Handle(Z)),
@@ -891,7 +900,6 @@
 
   LibraryIndex library_index(library_kernel_data_);
   intptr_t class_count = library_index.class_count();
-  intptr_t procedure_count = library_index.procedure_count();
 
   library_helper.ReadUntilIncluding(LibraryHelper::kName);
   library.SetName(H.DartSymbolObfuscate(library_helper.name_index_));
@@ -960,13 +968,47 @@
       classes.Add(klass, Heap::kOld);
     }
   }
-  helper_.SetOffset(next_class_offset);
+
+  if (loading_native_wrappers_library_ || !register_class) {
+    FinishTopLevelClassLoading(toplevel_class, library, library_index);
+  }
+
+  if (FLAG_enable_mirrors && annotation_count > 0) {
+    ASSERT(annotations_kernel_offset > 0);
+    library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource,
+                               annotations_kernel_offset);
+  }
+
+  if (register_class) {
+    classes.Add(toplevel_class, Heap::kOld);
+  }
+  if (!library.Loaded()) library.SetLoaded();
+
+  return library.raw();
+}
+
+void KernelLoader::FinishTopLevelClassLoading(
+    const Class& toplevel_class,
+    const Library& library,
+    const LibraryIndex& library_index) {
+  if (toplevel_class.is_loaded()) {
+    return;
+  }
+
+  TIMELINE_DURATION(Thread::Current(), Isolate, "FinishTopLevelClassLoading");
+
+  // Offsets within library index are whole program offsets and not
+  // relative to the library.
+  const intptr_t correction = correction_offset_ - library_kernel_offset_;
+  helper_.SetOffset(library_index.ClassOffset(library_index.class_count()) +
+                    correction);
 
   fields_.Clear();
   functions_.Clear();
   ActiveClassScope active_class_scope(&active_class_, &toplevel_class);
+
   // Load toplevel fields.
-  intptr_t field_count = helper_.ReadListLength();  // read list length.
+  const intptr_t field_count = helper_.ReadListLength();  // read list length.
   for (intptr_t i = 0; i < field_count; ++i) {
     intptr_t field_offset = helper_.ReaderOffset() - correction_offset_;
     ActiveMemberScope active_member_scope(&active_class_, NULL);
@@ -993,7 +1035,7 @@
     // In the VM all const fields are implicitly final whereas in Kernel they
     // are not final because they are not explicitly declared that way.
     const bool is_final = field_helper.IsConst() || field_helper.IsFinal();
-    Field& field = Field::Handle(
+    const Field& field = Field::Handle(
         Z,
         Field::NewTopLevel(name, is_final, field_helper.IsConst(), script_class,
                            field_helper.position_, field_helper.end_position_));
@@ -1017,31 +1059,45 @@
       library.AddFieldMetadata(field, TokenPosition::kNoSource, field_offset);
     }
     fields_.Add(&field);
-    library.AddObject(field, name);
   }
-  toplevel_class.AddFields(fields_);
+
+  ASSERT(!toplevel_class.is_loaded());
 
   // Load toplevel procedures.
-  intptr_t next_procedure_offset = library_index.ProcedureOffset(0);
+  intptr_t next_procedure_offset =
+      library_index.ProcedureOffset(0) + correction;
+  const intptr_t procedure_count = library_index.procedure_count();
   for (intptr_t i = 0; i < procedure_count; ++i) {
     helper_.SetOffset(next_procedure_offset);
-    next_procedure_offset = library_index.ProcedureOffset(i + 1);
+    next_procedure_offset = library_index.ProcedureOffset(i + 1) + correction;
     LoadProcedure(library, toplevel_class, false, next_procedure_offset);
+    // LoadProcedure calls Library::GetMetadata which invokes Dart code
+    // which may recursively trigger class finalization and
+    // FinishTopLevelClassLoading.
+    // In such case, return immediately and avoid overwriting already finalized
+    // functions with freshly loaded and not yet finalized.
+    if (toplevel_class.is_loaded()) {
+      return;
+    }
   }
 
-  if (FLAG_enable_mirrors && annotation_count > 0) {
-    ASSERT(annotations_kernel_offset > 0);
-    library.AddLibraryMetadata(toplevel_class, TokenPosition::kNoSource,
-                               annotations_kernel_offset);
-  }
-
+  toplevel_class.SetFields(Array::Handle(MakeFieldsArray()));
   toplevel_class.SetFunctions(Array::Handle(MakeFunctionsArray()));
-  if (register_class) {
-    classes.Add(toplevel_class, Heap::kOld);
-  }
-  if (!library.Loaded()) library.SetLoaded();
 
-  return library.raw();
+  String& name = String::Handle(Z);
+  for (intptr_t i = 0, n = fields_.length(); i < n; ++i) {
+    const Field* field = fields_.At(i);
+    name = field->name();
+    library.AddObject(*field, name);
+  }
+  for (intptr_t i = 0, n = functions_.length(); i < n; ++i) {
+    const Function* function = functions_.At(i);
+    name = function->name();
+    library.AddObject(*function, name);
+  }
+
+  ASSERT(!toplevel_class.is_loaded());
+  toplevel_class.set_is_loaded(true);
 }
 
 void KernelLoader::LoadLibraryImportsAndExports(Library* library,
@@ -1109,6 +1165,10 @@
         target_library.url() == Symbols::DartMirrors().raw()) {
       H.ReportError("import of dart:mirrors with --enable-mirrors=false");
     }
+    if (!Api::ffiEnabled() &&
+        target_library.url() == Symbols::DartFfi().raw()) {
+      H.ReportError("import of dart:ffi with --enable-ffi=false");
+    }
     String& prefix = H.DartSymbolPlain(dependency_helper.name_index_);
     ns = Namespace::New(target_library, show_names, hide_names);
     if (dependency_helper.flags_ & LibraryDependencyHelper::Export) {
@@ -1338,6 +1398,10 @@
                                       intptr_t class_offset,
                                       const ClassIndex& class_index,
                                       ClassHelper* class_helper) {
+  if (klass.is_loaded()) {
+    return;
+  }
+
   TIMELINE_DURATION(Thread::Current(), Isolate, "FinishClassLoading");
 
   fields_.Clear();
@@ -1425,7 +1489,7 @@
           TokenPosition::kNoSource, TokenPosition::kNoSource);
       fields_.Add(&deleted_enum_sentinel);
     }
-    klass.AddFields(fields_);
+    klass.SetFields(Array::Handle(Z, MakeFieldsArray()));
   }
 
   class_helper->ReadUntilExcluding(ClassHelper::kConstructors);
@@ -1500,6 +1564,8 @@
     }
   }
 
+  ASSERT(!klass.is_loaded());
+
   // Everything up til the procedures are skipped implicitly, and class_helper
   // is no longer used.
 
@@ -1513,13 +1579,23 @@
     helper_.SetOffset(next_procedure_offset);
     next_procedure_offset = class_index.ProcedureOffset(i + 1) + correction;
     LoadProcedure(library, klass, true, next_procedure_offset);
+    // LoadProcedure calls Library::GetMetadata which invokes Dart code
+    // which may recursively trigger class finalization and FinishClassLoading.
+    // In such case, return immediately and avoid overwriting already finalized
+    // functions with freshly loaded and not yet finalized.
+    if (klass.is_loaded()) {
+      return;
+    }
   }
 
   klass.SetFunctions(Array::Handle(MakeFunctionsArray()));
+
+  ASSERT(!klass.is_loaded());
+  klass.set_is_loaded(true);
 }
 
 void KernelLoader::FinishLoading(const Class& klass) {
-  ASSERT(klass.kernel_offset() > 0);
+  ASSERT(klass.IsTopLevel() || (klass.kernel_offset() > 0));
 
   Zone* zone = Thread::Current()->zone();
   const Script& script = Script::Handle(zone, klass.script());
@@ -1531,10 +1607,17 @@
   const intptr_t library_kernel_offset = library.kernel_offset();
   ASSERT(library_kernel_offset > 0);
 
-  const intptr_t class_offset = klass.kernel_offset();
   KernelLoader kernel_loader(script, library_kernel_data,
                              library_kernel_offset);
   LibraryIndex library_index(library_kernel_data);
+
+  if (klass.IsTopLevel()) {
+    ASSERT(klass.raw() == toplevel_class.raw());
+    kernel_loader.FinishTopLevelClassLoading(klass, library, library_index);
+    return;
+  }
+
+  const intptr_t class_offset = klass.kernel_offset();
   ClassIndex class_index(
       library_kernel_data, class_offset,
       // Class offsets in library index are whole program offsets.
@@ -1765,14 +1848,6 @@
   // function_node_helper are no longer used.
   helper_.SetOffset(procedure_end);
 
-  if (!in_class) {
-    library.AddObject(function, name);
-    ASSERT(!Object::Handle(
-                Z, library.LookupObjectAllowPrivate(
-                       H.DartProcedureName(procedure_helper.canonical_name_)))
-                .IsNull());
-  }
-
   if (annotation_count > 0) {
     library.AddFunctionMetadata(function, TokenPosition::kNoSource,
                                 procedure_offset);
@@ -2098,6 +2173,9 @@
 RawFunction* CreateFieldInitializerFunction(Thread* thread,
                                             Zone* zone,
                                             const Field& field) {
+  if (field.Initializer() != Function::null()) {
+    return field.Initializer();
+  }
   String& init_name = String::Handle(zone, field.name());
   init_name = Symbols::FromConcat(thread, Symbols::InitPrefix(), init_name);
 
@@ -2130,9 +2208,11 @@
                           initializer_owner, TokenPosition::kNoSource));
   initializer_fun.set_kernel_offset(field.kernel_offset());
   initializer_fun.set_result_type(AbstractType::Handle(zone, field.type()));
-  initializer_fun.set_is_debuggable(false);
   initializer_fun.set_is_reflectable(false);
   initializer_fun.set_is_inlinable(false);
+  initializer_fun.set_token_pos(field.token_pos());
+  initializer_fun.set_end_token_pos(field.end_token_pos());
+  field.SetInitializer(initializer_fun);
   return initializer_fun.raw();
 }
 
diff --git a/runtime/vm/kernel_loader.h b/runtime/vm/kernel_loader.h
index e162a3a2..6554706 100644
--- a/runtime/vm/kernel_loader.h
+++ b/runtime/vm/kernel_loader.h
@@ -178,6 +178,10 @@
 
   RawLibrary* LoadLibrary(intptr_t index);
 
+  void FinishTopLevelClassLoading(const Class& toplevel_class,
+                                  const Library& library,
+                                  const LibraryIndex& library_index);
+
   static void FinishLoading(const Class& klass);
 
   void ReadObfuscationProhibitions();
@@ -277,6 +281,7 @@
                      bool in_class,
                      intptr_t procedure_end);
 
+  RawArray* MakeFieldsArray();
   RawArray* MakeFunctionsArray();
 
   RawScript* LoadScriptAt(intptr_t index);
@@ -320,9 +325,9 @@
 
   void EnsurePragmaClassIsLookedUp() {
     if (pragma_class_.IsNull()) {
-      const Library& internal_lib =
-          Library::Handle(zone_, dart::Library::InternalLibrary());
-      pragma_class_ = internal_lib.LookupClass(Symbols::Pragma());
+      const Library& core_lib =
+          Library::Handle(zone_, dart::Library::CoreLibrary());
+      pragma_class_ = core_lib.LookupLocalClass(Symbols::Pragma());
       ASSERT(!pragma_class_.IsNull());
     }
   }
diff --git a/runtime/vm/megamorphic_cache_table.cc b/runtime/vm/megamorphic_cache_table.cc
index 4595b9c..c07452f 100644
--- a/runtime/vm/megamorphic_cache_table.cc
+++ b/runtime/vm/megamorphic_cache_table.cc
@@ -53,9 +53,9 @@
   // The miss handler for a class ID not found in the table is invoked as a
   // normal Dart function.
   ObjectPoolBuilder object_pool_builder;
-  const Code& code = Code::Handle(
-      StubCode::Generate("_stub_MegamorphicMiss", &object_pool_builder,
-                         StubCode::GenerateMegamorphicMissStub));
+  const Code& code = Code::Handle(StubCode::Generate(
+      "_stub_MegamorphicMiss", &object_pool_builder,
+      compiler::StubCodeCompiler::GenerateMegamorphicMissStub));
 
   const auto& object_pool =
       ObjectPool::Handle(ObjectPool::NewFromBuilder(object_pool_builder));
@@ -92,7 +92,8 @@
   ASSERT(FLAG_precompiled_mode && FLAG_use_bare_instructions);
 
   const Code& code = Code::Handle(StubCode::Generate(
-      "_stub_MegamorphicMiss", wrapper, StubCode::GenerateMegamorphicMissStub));
+      "_stub_MegamorphicMiss", wrapper,
+      compiler::StubCodeCompiler::GenerateMegamorphicMissStub));
   code.set_exception_handlers(Object::empty_exception_handlers());
 
   auto object_store = isolate->object_store();
diff --git a/runtime/vm/native_arguments.h b/runtime/vm/native_arguments.h
index 251740e..86d7be5 100644
--- a/runtime/vm/native_arguments.h
+++ b/runtime/vm/native_arguments.h
@@ -155,7 +155,7 @@
       // null vector represents infinite list of dynamics
       return Type::dynamic_type().raw();
     }
-    return TypeArguments::Handle(NativeTypeArgs()).TypeAt(index);
+    return type_args.TypeAt(index);
   }
 
   void SetReturn(const Object& value) const { *retval_ = value.raw(); }
diff --git a/runtime/vm/native_entry.cc b/runtime/vm/native_entry.cc
index ff77ded..569b402 100644
--- a/runtime/vm/native_entry.cc
+++ b/runtime/vm/native_entry.cc
@@ -20,6 +20,14 @@
 
 namespace dart {
 
+void DartNativeThrowTypeArgumentCountException(int num_type_args,
+                                               int num_type_args_expected) {
+  const String& error = String::Handle(String::NewFormatted(
+      "Wrong number of type arguments (%i), expected %i type arguments",
+      num_type_args, num_type_args_expected));
+  Exceptions::ThrowArgumentError(error);
+}
+
 void DartNativeThrowArgumentException(const Instance& instance) {
   const Array& __args__ = Array::Handle(Array::New(1));
   __args__.SetAt(0, instance);
diff --git a/runtime/vm/native_entry.h b/runtime/vm/native_entry.h
index 0892258..a4a5ee5 100644
--- a/runtime/vm/native_entry.h
+++ b/runtime/vm/native_entry.h
@@ -73,9 +73,22 @@
   static RawObject* DN_Helper##name(Isolate* isolate, Thread* thread,          \
                                     Zone* zone, NativeArguments* arguments)
 
-// Helper that throws an argument exception.
+// Helpers that throw an argument exception.
+void DartNativeThrowTypeArgumentCountException(int num_type_args,
+                                               int num_type_args_expected);
 void DartNativeThrowArgumentException(const Instance& instance);
 
+// Native should throw an exception if the wrong number of type arguments is
+// passed.
+#define NATIVE_TYPE_ARGUMENT_COUNT(expected)                                   \
+  int __num_type_arguments = arguments->NativeTypeArgCount();                  \
+  if (__num_type_arguments != expected) {                                      \
+    DartNativeThrowTypeArgumentCountException(__num_type_arguments, expected); \
+  }
+
+#define GET_NATIVE_TYPE_ARGUMENT(name, value)                                  \
+  AbstractType& name = AbstractType::Handle(value);
+
 // Natives should throw an exception if an illegal argument or null is passed.
 // type name = value.
 #define GET_NON_NULL_NATIVE_ARGUMENT(type, name, value)                        \
diff --git a/runtime/vm/object.cc b/runtime/vm/object.cc
index b53d63a..318379e 100644
--- a/runtime/vm/object.cc
+++ b/runtime/vm/object.cc
@@ -128,6 +128,8 @@
 RawClass* Object::signature_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::redirection_data_class_ =
     reinterpret_cast<RawClass*>(RAW_NULL);
+RawClass* Object::ffi_trampoline_data_class_ =
+    reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::field_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::script_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
 RawClass* Object::library_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -582,6 +584,9 @@
   cls = Class::New<RedirectionData>();
   redirection_data_class_ = cls.raw();
 
+  cls = Class::New<FfiTrampolineData>();
+  ffi_trampoline_data_class_ = cls.raw();
+
   cls = Class::New<Field>();
   field_class_ = cls.raw();
 
@@ -957,6 +962,7 @@
   closure_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   signature_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   redirection_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
+  ffi_trampoline_data_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   field_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   script_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
   library_class_ = reinterpret_cast<RawClass*>(RAW_NULL);
@@ -1056,6 +1062,7 @@
   SET_CLASS_NAME(closure_data, ClosureData);
   SET_CLASS_NAME(signature_data, SignatureData);
   SET_CLASS_NAME(redirection_data, RedirectionData);
+  SET_CLASS_NAME(ffi_trampoline_data, FfiTrampolineData);
   SET_CLASS_NAME(field, Field);
   SET_CLASS_NAME(script, Script);
   SET_CLASS_NAME(library, LibraryClass);
@@ -1119,9 +1126,9 @@
       String::SetCachedHash(str, hash);
     }
     intptr_t size = OneByteString::UnroundedSize(str);
-    ASSERT(size <= str->Size());
+    ASSERT(size <= str->HeapSize());
     memset(reinterpret_cast<void*>(RawObject::ToAddr(str) + size), 0,
-           str->Size() - size);
+           str->HeapSize() - size);
   } else if (cid == kTwoByteStringCid) {
     RawTwoByteString* str = static_cast<RawTwoByteString*>(object);
     if (String::GetCachedHash(str) == 0) {
@@ -1130,9 +1137,9 @@
     }
     ASSERT(String::GetCachedHash(str) != 0);
     intptr_t size = TwoByteString::UnroundedSize(str);
-    ASSERT(size <= str->Size());
+    ASSERT(size <= str->HeapSize());
     memset(reinterpret_cast<void*>(RawObject::ToAddr(str) + size), 0,
-           str->Size() - size);
+           str->HeapSize() - size);
   } else if (cid == kExternalOneByteStringCid) {
     RawExternalOneByteString* str =
         static_cast<RawExternalOneByteString*>(object);
@@ -1150,21 +1157,21 @@
   } else if (cid == kCodeSourceMapCid) {
     RawCodeSourceMap* map = CodeSourceMap::RawCast(object);
     intptr_t size = CodeSourceMap::UnroundedSize(map);
-    ASSERT(size <= map->Size());
+    ASSERT(size <= map->HeapSize());
     memset(reinterpret_cast<void*>(RawObject::ToAddr(map) + size), 0,
-           map->Size() - size);
+           map->HeapSize() - size);
   } else if (cid == kStackMapCid) {
     RawStackMap* map = StackMap::RawCast(object);
     intptr_t size = StackMap::UnroundedSize(map);
-    ASSERT(size <= map->Size());
+    ASSERT(size <= map->HeapSize());
     memset(reinterpret_cast<void*>(RawObject::ToAddr(map) + size), 0,
-           map->Size() - size);
+           map->HeapSize() - size);
   } else if (cid == kPcDescriptorsCid) {
     RawPcDescriptors* desc = PcDescriptors::RawCast(object);
     intptr_t size = PcDescriptors::UnroundedSize(desc);
-    ASSERT(size <= desc->Size());
+    ASSERT(size <= desc->HeapSize());
     memset(reinterpret_cast<void*>(RawObject::ToAddr(desc) + size), 0,
-           desc->Size() - size);
+           desc->HeapSize() - size);
   }
 }
 
@@ -1814,6 +1821,51 @@
     type_args = type_args.Canonicalize();
     object_store->set_type_argument_string_string(type_args);
 
+    lib = Library::LookupLibrary(thread, Symbols::DartFfi());
+    if (lib.IsNull()) {
+      lib = Library::NewLibraryHelper(Symbols::DartFfi(), true);
+      lib.SetLoadRequested();
+      lib.Register(thread);
+    }
+    object_store->set_bootstrap_library(ObjectStore::kFfi, lib);
+
+    cls = Class::New<Instance>(kFfiNativeTypeCid);
+    cls.set_num_type_arguments(0);
+    cls.set_num_own_type_arguments(0);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    object_store->set_ffi_native_type_class(cls);
+    RegisterClass(cls, Symbols::FfiNativeType(), lib);
+
+#define REGISTER_FFI_TYPE_MARKER(clazz)                                        \
+  cls = Class::New<Instance>(kFfi##clazz##Cid);                                \
+  cls.set_num_type_arguments(0);                                               \
+  cls.set_num_own_type_arguments(0);                                           \
+  cls.set_is_prefinalized();                                                   \
+  pending_classes.Add(cls);                                                    \
+  RegisterClass(cls, Symbols::Ffi##clazz(), lib);
+    CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_TYPE_MARKER);
+#undef REGISTER_FFI_TYPE_MARKER
+
+    cls = Class::New<Instance>(kFfiNativeFunctionCid);
+    cls.set_type_arguments_field_offset(Pointer::type_arguments_offset());
+    cls.set_num_type_arguments(1);
+    cls.set_num_own_type_arguments(1);
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    RegisterClass(cls, Symbols::FfiNativeFunction(), lib);
+
+    cls = Class::NewPointerClass(kFfiPointerCid);
+    object_store->set_ffi_pointer_class(cls);
+    pending_classes.Add(cls);
+    RegisterClass(cls, Symbols::FfiPointer(), lib);
+
+    cls = Class::New<DynamicLibrary>(kFfiDynamicLibraryCid);
+    cls.set_instance_size(DynamicLibrary::InstanceSize());
+    cls.set_is_prefinalized();
+    pending_classes.Add(cls);
+    RegisterClass(cls, Symbols::FfiDynamicLibrary(), lib);
+
     // Finish the initialization by compiling the bootstrap scripts containing
     // the base interfaces and the implementation of the internal classes.
     const Error& error = Error::Handle(
@@ -1827,7 +1879,7 @@
     ClassFinalizer::VerifyBootstrapClasses();
 
     // Set up the intrinsic state of all functions (core, math and typed data).
-    Intrinsifier::InitializeState();
+    compiler::Intrinsifier::InitializeState();
 
     // Set up recognized state of all functions (core, math and typed data).
     MethodRecognizer::InitializeState();
@@ -1898,6 +1950,20 @@
     CLASS_LIST_TYPED_DATA(REGISTER_EXT_TYPED_DATA_CLASS);
 #undef REGISTER_EXT_TYPED_DATA_CLASS
 
+    cls = Class::New<Instance>(kFfiNativeTypeCid);
+    object_store->set_ffi_native_type_class(cls);
+
+#define REGISTER_FFI_CLASS(clazz) cls = Class::New<Instance>(kFfi##clazz##Cid);
+    CLASS_LIST_FFI_TYPE_MARKER(REGISTER_FFI_CLASS);
+#undef REGISTER_FFI_CLASS
+
+    cls = Class::New<Instance>(kFfiNativeFunctionCid);
+
+    cls = Class::NewPointerClass(kFfiPointerCid);
+    object_store->set_ffi_pointer_class(cls);
+
+    cls = Class::New<DynamicLibrary>(kFfiDynamicLibraryCid);
+
     cls = Class::New<Instance>(kByteBufferCid);
 
     cls = Class::New<Integer>();
@@ -2120,7 +2186,7 @@
 
 RawObject* Object::Clone(const Object& orig, Heap::Space space) {
   const Class& cls = Class::Handle(orig.clazz());
-  intptr_t size = orig.raw()->Size();
+  intptr_t size = orig.raw()->HeapSize();
   RawObject* raw_clone = Object::Allocate(cls.id(), size, space);
   NoSafepointScope no_safepoint;
   // Copy the body of the original into the clone.
@@ -3660,6 +3726,17 @@
   return result.raw();
 }
 
+RawClass* Class::NewPointerClass(intptr_t class_id) {
+  ASSERT(RawObject::IsFfiPointerClassId(class_id));
+  intptr_t instance_size = Pointer::InstanceSize();
+  Class& result = Class::Handle(New<Pointer>(class_id));
+  result.set_instance_size(instance_size);
+  result.set_type_arguments_field_offset(Pointer::type_arguments_offset());
+  result.set_next_field_offset(Pointer::NextFieldOffset());
+  result.set_is_prefinalized();
+  return result.raw();
+}
+
 void Class::set_name(const String& value) const {
   ASSERT(raw_ptr()->name_ == String::null());
   ASSERT(value.IsSymbol());
@@ -3733,6 +3810,11 @@
     case kExternalTypedDataFloat64ArrayCid:
       return Symbols::Float64List().raw();
 
+    case kFfiPointerCid:
+      return Symbols::FfiPointer().raw();
+    case kFfiDynamicLibraryCid:
+      return Symbols::FfiDynamicLibrary().raw();
+
 #if !defined(PRODUCT)
     case kNullCid:
       return Symbols::Null().raw();
@@ -3754,6 +3836,8 @@
       return Symbols::SignatureData().raw();
     case kRedirectionDataCid:
       return Symbols::RedirectionData().raw();
+    case kFfiTrampolineDataCid:
+      return Symbols::FfiTrampolineData().raw();
     case kFieldCid:
       return Symbols::Field().raw();
     case kScriptCid:
@@ -3950,6 +4034,10 @@
   set_state_bits(IsAllocatedBit::update(value, raw_ptr()->state_bits_));
 }
 
+void Class::set_is_loaded(bool value) const {
+  set_state_bits(IsLoadedBit::update(value, raw_ptr()->state_bits_));
+}
+
 void Class::set_is_finalized() const {
   ASSERT(!is_finalized());
   set_state_bits(
@@ -3974,12 +4062,8 @@
   StorePointer(&raw_ptr()->interfaces_, value.raw());
 }
 
-RawClass* Class::GetPatchClass() const {
-  const Library& lib = Library::Handle(library());
-  return lib.GetPatchClass(String::Handle(Name()));
-}
-
-void Class::AddDirectImplementor(const Class& implementor) const {
+void Class::AddDirectImplementor(const Class& implementor,
+                                 bool is_mixin) const {
   ASSERT(is_implemented());
   ASSERT(!implementor.IsNull());
   GrowableObjectArray& direct_implementors =
@@ -3990,8 +4074,14 @@
   }
 #if defined(DEBUG)
   // Verify that the same class is not added twice.
-  for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
-    ASSERT(direct_implementors.At(i) != implementor.raw());
+  // The only exception is mixins: when mixin application is transformed,
+  // mixin is added to the end of interfaces list and may be duplicated:
+  //   class X = A with B implements B;
+  // This is rare and harmless.
+  if (!is_mixin) {
+    for (intptr_t i = 0; i < direct_implementors.Length(); i++) {
+      ASSERT(direct_implementors.At(i) != implementor.raw());
+    }
   }
 #endif
   direct_implementors.Add(implementor, Heap::kOld);
@@ -4563,16 +4653,6 @@
   return Field::null();
 }
 
-RawLibraryPrefix* Class::LookupLibraryPrefix(const String& name) const {
-  Zone* zone = Thread::Current()->zone();
-  const Library& lib = Library::Handle(zone, library());
-  const Object& obj = Object::Handle(zone, lib.LookupLocalObject(name));
-  if (!obj.IsNull() && obj.IsLibraryPrefix()) {
-    return LibraryPrefix::Cast(obj).raw();
-  }
-  return LibraryPrefix::null();
-}
-
 const char* Class::ToCString() const {
   const Library& lib = Library::Handle(library());
   const char* library_name = lib.IsNull() ? "" : lib.ToCString();
@@ -5018,9 +5098,19 @@
 }
 
 RawAbstractType* TypeArguments::TypeAt(intptr_t index) const {
+  ASSERT(!IsNull());
   return *TypeAddr(index);
 }
 
+RawAbstractType* TypeArguments::TypeAtNullSafe(intptr_t index) const {
+  if (IsNull()) {
+    // null vector represents infinite list of dynamics
+    return Type::dynamic_type().raw();
+  }
+  ASSERT((index >= 0) && (index < Length()));
+  return TypeAt(index);
+}
+
 void TypeArguments::SetTypeAt(intptr_t index, const AbstractType& value) const {
   ASSERT(!IsCanonical());
   StorePointer(TypeAddr(index), value.raw());
@@ -5888,9 +5978,11 @@
   ASSERT(!obj.IsNull());
   if (IsSignatureFunction()) {
     return SignatureData::Cast(obj).signature_type();
-  } else {
-    ASSERT(IsClosureFunction());
+  } else if (IsClosureFunction()) {
     return ClosureData::Cast(obj).signature_type();
+  } else {
+    ASSERT(IsFfiTrampoline());
+    return FfiTrampolineData::Cast(obj).signature_type();
   }
 }
 
@@ -5941,9 +6033,11 @@
   if (IsSignatureFunction()) {
     SignatureData::Cast(obj).set_signature_type(value);
     ASSERT(!value.IsCanonical() || (value.signature() == this->raw()));
-  } else {
-    ASSERT(IsClosureFunction());
+  } else if (IsClosureFunction()) {
     ClosureData::Cast(obj).set_signature_type(value);
+  } else {
+    ASSERT(IsFfiTrampoline());
+    FfiTrampolineData::Cast(obj).set_signature_type(value);
   }
 }
 
@@ -6078,6 +6172,7 @@
 //   native function:         Array[0] = String native name
 //                            Array[1] = Function implicit closure function
 //   regular function:        Function for implicit closure function
+//   ffi trampoline function: FfiTrampolineData  (Dart->C)
 void Function::set_data(const Object& value) const {
   StorePointer(&raw_ptr()->data_, value.raw());
 }
@@ -6391,7 +6486,8 @@
   }
   if ((k == RawFunction::kClosureFunction) ||
       (k == RawFunction::kImplicitClosureFunction) ||
-      (k == RawFunction::kSignatureFunction)) {
+      (k == RawFunction::kSignatureFunction) ||
+      (k == RawFunction::kFfiTrampoline)) {
     return 1;  // Closure object.
   }
   if (!is_static()) {
@@ -7080,6 +7176,10 @@
     const SignatureData& data =
         SignatureData::Handle(SignatureData::New(space));
     result.set_data(data);
+  } else if (kind == RawFunction::kFfiTrampoline) {
+    const FfiTrampolineData& data =
+        FfiTrampolineData::Handle(FfiTrampolineData::New());
+    result.set_data(data);
   } else {
     // Functions other than signature functions have no reason to be allocated
     // in new space.
@@ -8019,6 +8119,27 @@
                      target_fun.IsNull() ? "null" : target_fun.ToCString());
 }
 
+void FfiTrampolineData::set_signature_type(const Type& value) const {
+  StorePointer(&raw_ptr()->signature_type_, value.raw());
+}
+
+RawFfiTrampolineData* FfiTrampolineData::New() {
+  ASSERT(Object::ffi_trampoline_data_class() != Class::null());
+  RawObject* raw =
+      Object::Allocate(FfiTrampolineData::kClassId,
+                       FfiTrampolineData::InstanceSize(), Heap::kOld);
+  return reinterpret_cast<RawFfiTrampolineData*>(raw);
+}
+
+const char* FfiTrampolineData::ToCString() const {
+  Type& signature_type = Type::Handle(this->signature_type());
+  String& signature_type_name =
+      String::Handle(signature_type.UserVisibleName());
+  return OS::SCreate(
+      Thread::Current()->zone(), "TrampolineData: signature=%s",
+      signature_type_name.IsNull() ? "null" : signature_type_name.ToCString());
+}
+
 RawField* Field::CloneFromOriginal() const {
   return this->Clone(*this);
 }
@@ -8470,14 +8591,13 @@
   return value.raw() == Object::sentinel().raw();
 }
 
-void Field::SetPrecompiledInitializer(const Function& initializer) const {
+void Field::SetInitializer(const Function& initializer) const {
   ASSERT(IsOriginal());
-  StorePointer(&raw_ptr()->initializer_.precompiled_, initializer.raw());
+  StorePointer(&raw_ptr()->initializer_, initializer.raw());
 }
 
-bool Field::HasPrecompiledInitializer() const {
-  return raw_ptr()->initializer_.precompiled_->IsHeapObject() &&
-         raw_ptr()->initializer_.precompiled_->IsFunction();
+bool Field::HasInitializer() const {
+  return raw_ptr()->initializer_ != Function::null();
 }
 
 RawError* Field::EvaluateInitializer() const {
@@ -8705,8 +8825,9 @@
   const intptr_t type_arguments_offset = cls.type_arguments_field_offset();
   ASSERT(type_arguments_offset != Class::kNoTypeArguments);
   if (StaticTypeExactnessState::CanRepresentAsTriviallyExact(
-          type_arguments_offset)) {
-    return StaticTypeExactnessState::TriviallyExact(type_arguments_offset);
+          type_arguments_offset / kWordSize)) {
+    return StaticTypeExactnessState::TriviallyExact(type_arguments_offset /
+                                                    kWordSize);
   } else {
     return StaticTypeExactnessState::NotExact();
   }
@@ -8844,7 +8965,7 @@
     return "not-exact";
   } else if (IsTriviallyExact()) {
     return Thread::Current()->zone()->PrintToString(
-        "trivially-exact(%" Pd ")", GetTypeArgumentsOffsetInWords());
+        "trivially-exact(%hhu)", GetTypeArgumentsOffsetInWords());
   } else if (IsHasExactSuperType()) {
     return "has-exact-super-type";
   } else if (IsHasExactSuperClass()) {
@@ -9618,50 +9739,6 @@
   return error.raw();
 }
 
-void Library::AddPatchClass(const Class& cls) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
-  ASSERT(cls.is_patch());
-  ASSERT(GetPatchClass(String::Handle(cls.Name())) == Class::null());
-  const GrowableObjectArray& patch_classes =
-      GrowableObjectArray::Handle(this->patch_classes());
-  patch_classes.Add(cls);
-}
-
-RawClass* Library::GetPatchClass(const String& name) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
-  const GrowableObjectArray& patch_classes =
-      GrowableObjectArray::Handle(this->patch_classes());
-  Object& obj = Object::Handle();
-  for (intptr_t i = 0; i < patch_classes.Length(); i++) {
-    obj = patch_classes.At(i);
-    if (obj.IsClass() &&
-        (Class::Cast(obj).Name() == name.raw())) {  // Names are canonicalized.
-      return Class::RawCast(obj.raw());
-    }
-  }
-  return Class::null();
-}
-
-void Library::RemovePatchClass(const Class& cls) const {
-  ASSERT(Thread::Current()->IsMutatorThread());
-  ASSERT(cls.is_patch());
-  const GrowableObjectArray& patch_classes =
-      GrowableObjectArray::Handle(this->patch_classes());
-  const intptr_t num_classes = patch_classes.Length();
-  intptr_t i = 0;
-  while (i < num_classes) {
-    if (cls.raw() == patch_classes.At(i)) break;
-    i++;
-  }
-  if (i == num_classes) return;
-  // Replace the entry with the script. We keep the script so that
-  // Library::LoadedScripts() can find it without having to iterate
-  // over the members of each class.
-  ASSERT(i < num_classes);  // We must have found a class.
-  const Script& patch_script = Script::Handle(cls.script());
-  patch_classes.SetAt(i, patch_script);
-}
-
 static RawString* MakeClassMetaName(Thread* thread,
                                     Zone* zone,
                                     const Class& cls) {
@@ -9872,6 +9949,7 @@
   if (FLAG_use_lib_cache && LookupResolvedNamesCache(name, &obj)) {
     return obj.raw();
   }
+  EnsureTopLevelClassIsFinalized();
   obj = LookupLocalObject(name);
   if (!obj.IsNull()) {
     // Names that are in this library's dictionary and are unmangled
@@ -10159,18 +10237,6 @@
   return Object::null();
 }
 
-void Library::ReplaceObject(const Object& obj, const String& name) const {
-  ASSERT(!Compiler::IsBackgroundCompilation());
-  ASSERT(obj.IsClass() || obj.IsFunction() || obj.IsField());
-  ASSERT(LookupLocalObject(name) != Object::null());
-
-  intptr_t index;
-  LookupEntry(name, &index);
-  // The value is guaranteed to be found.
-  const Array& dict = Array::Handle(dictionary());
-  dict.SetAt(index, obj);
-}
-
 void Library::AddClass(const Class& cls) const {
   ASSERT(!Compiler::IsBackgroundCompilation());
   const String& class_name = String::Handle(cls.Name());
@@ -10297,6 +10363,22 @@
   return Script::null();
 }
 
+void Library::EnsureTopLevelClassIsFinalized() const {
+  if (toplevel_class() == Object::null()) {
+    return;
+  }
+  Thread* thread = Thread::Current();
+  const Class& cls = Class::Handle(thread->zone(), toplevel_class());
+  if (cls.is_finalized()) {
+    return;
+  }
+  const Error& error =
+      Error::Handle(thread->zone(), cls.EnsureIsFinalized(thread));
+  if (!error.IsNull()) {
+    Exceptions::PropagateError(error);
+  }
+}
+
 RawObject* Library::LookupLocalObject(const String& name) const {
   intptr_t index;
   return LookupEntry(name, &index);
@@ -10304,6 +10386,7 @@
 
 RawObject* Library::LookupLocalOrReExportObject(const String& name) const {
   intptr_t index;
+  EnsureTopLevelClassIsFinalized();
   const Object& result = Object::Handle(LookupEntry(name, &index));
   if (!result.IsNull() && !result.IsLibraryPrefix()) {
     return result.raw();
@@ -10312,6 +10395,7 @@
 }
 
 RawField* Library::LookupFieldAllowPrivate(const String& name) const {
+  EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupObjectAllowPrivate(name));
   if (obj.IsField()) {
     return Field::Cast(obj).raw();
@@ -10320,6 +10404,7 @@
 }
 
 RawField* Library::LookupLocalField(const String& name) const {
+  EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
   if (obj.IsField()) {
     return Field::Cast(obj).raw();
@@ -10328,6 +10413,7 @@
 }
 
 RawFunction* Library::LookupFunctionAllowPrivate(const String& name) const {
+  EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupObjectAllowPrivate(name));
   if (obj.IsFunction()) {
     return Function::Cast(obj).raw();
@@ -10336,6 +10422,7 @@
 }
 
 RawFunction* Library::LookupLocalFunction(const String& name) const {
+  EnsureTopLevelClassIsFinalized();
   Object& obj = Object::Handle(LookupLocalObjectAllowPrivate(name));
   if (obj.IsFunction()) {
     return Function::Cast(obj).raw();
@@ -10433,7 +10520,10 @@
 }
 
 RawClass* Library::LookupClass(const String& name) const {
-  Object& obj = Object::Handle(ResolveName(name));
+  Object& obj = Object::Handle(LookupLocalObject(name));
+  if (obj.IsNull() && !ShouldBePrivate(name)) {
+    obj = LookupImportedObject(name);
+  }
   if (obj.IsClass()) {
     return Class::Cast(obj).raw();
   }
@@ -10521,31 +10611,6 @@
   return Namespace::RawCast(import_list.At(index));
 }
 
-bool Library::ImportsCorelib() const {
-  Zone* zone = Thread::Current()->zone();
-  Library& imported = Library::Handle(zone);
-  intptr_t count = num_imports();
-  for (int i = 0; i < count; i++) {
-    imported = ImportLibraryAt(i);
-    if (imported.IsCoreLibrary()) {
-      return true;
-    }
-  }
-  LibraryPrefix& prefix = LibraryPrefix::Handle(zone);
-  LibraryPrefixIterator it(*this);
-  while (it.HasNext()) {
-    prefix = it.GetNext();
-    count = prefix.num_imports();
-    for (int i = 0; i < count; i++) {
-      imported = prefix.GetLibrary(i);
-      if (imported.IsCoreLibrary()) {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
 void Library::DropDependenciesAndCaches() const {
   StorePointer(&raw_ptr()->imports_, Object::empty_array().raw());
   StorePointer(&raw_ptr()->exports_, Object::empty_array().raw());
@@ -10661,7 +10726,6 @@
   result.set_native_entry_resolver(NULL);
   result.set_native_entry_symbol_resolver(NULL);
   result.set_is_in_fullsnapshot(false);
-  result.StoreNonPointer(&result.raw_ptr()->corelib_imported_, true);
   if (dart_private_scheme) {
     // Never debug dart:_ libraries.
     result.set_debuggable(false);
@@ -11242,6 +11306,10 @@
   return Isolate::Current()->object_store()->developer_library();
 }
 
+RawLibrary* Library::FfiLibrary() {
+  return Isolate::Current()->object_store()->ffi_library();
+}
+
 RawLibrary* Library::InternalLibrary() {
   return Isolate::Current()->object_store()->_internal_library();
 }
@@ -11698,6 +11766,8 @@
     }
   }
 
+  lib.EnsureTopLevelClassIsFinalized();
+
   intptr_t ignore = 0;
   // Lookup the name in the library's symbols.
   Object& obj = Object::Handle(zone, lib.LookupEntry(name, &ignore));
@@ -11798,6 +11868,10 @@
   return Script::RawCast(script);
 }
 
+void KernelProgramInfo::set_scripts(const Array& scripts) const {
+  StorePointer(&raw_ptr()->scripts_, scripts.raw());
+}
+
 void KernelProgramInfo::set_constants(const Array& constants) const {
   StorePointer(&raw_ptr()->constants_, constants.raw());
 }
@@ -12192,7 +12266,7 @@
 intptr_t PcDescriptors::DecodeInteger(intptr_t* byte_index) const {
   NoSafepointScope no_safepoint;
   const uint8_t* data = raw_ptr()->data();
-  return Utils::DecodeSLEB128(data, Length(), byte_index);
+  return Utils::DecodeSLEB128<intptr_t>(data, Length(), byte_index);
 }
 
 RawObjectPool* ObjectPool::New(intptr_t len) {
@@ -12948,7 +13022,7 @@
 void ICData::ResetSwitchable(Zone* zone) const {
   ASSERT(NumArgsTested() == 1);
   ASSERT(!IsTrackingExactness());
-  set_ic_data_array(Array::Handle(zone, CachedEmptyICDataArray(1, false)));
+  set_entries(Array::Handle(zone, CachedEmptyICDataArray(1, false)));
 }
 
 const char* ICData::ToCString() const {
@@ -13017,9 +13091,9 @@
 #endif
 }
 
-void ICData::set_ic_data_array(const Array& value) const {
+void ICData::set_entries(const Array& value) const {
   ASSERT(!value.IsNull());
-  StorePointer<RawArray*, MemoryOrder::kRelease>(&raw_ptr()->ic_data_,
+  StorePointer<RawArray*, MemoryOrder::kRelease>(&raw_ptr()->entries_,
                                                  value.raw());
 }
 
@@ -13096,7 +13170,7 @@
 }
 
 intptr_t ICData::Length() const {
-  return (Smi::Value(ic_data()->ptr()->length_) / TestEntryLength());
+  return (Smi::Value(entries()->ptr()->length_) / TestEntryLength());
 }
 
 intptr_t ICData::NumberOfChecks() const {
@@ -13176,7 +13250,7 @@
   const intptr_t len = Length();
   ASSERT(index >= 0);
   ASSERT(index < len);
-  Array& data = Array::Handle(ic_data());
+  Array& data = Array::Handle(entries());
   const intptr_t start = index * TestEntryLength();
   const intptr_t end = start + TestEntryLength();
   for (intptr_t i = start; i < end; i++) {
@@ -13202,7 +13276,7 @@
   ASSERT(IsSentinelAt(len - 1));
   if (NumArgsTested() == 0) {
     // No type feedback is being collected.
-    const Array& data = Array::Handle(ic_data());
+    const Array& data = Array::Handle(entries());
     // Static calls with no argument checks hold only one target and the
     // sentinel value.
     ASSERT(len == 2);
@@ -13216,7 +13290,7 @@
     data.SetAt(1, value);
   } else {
     // Type feedback on arguments is being collected.
-    const Array& data = Array::Handle(ic_data());
+    const Array& data = Array::Handle(entries());
 
     // Fill all but the first entry with the sentinel.
     for (intptr_t i = len - 1; i > 0; i--) {
@@ -13293,7 +13367,7 @@
   // Can add only once.
   const intptr_t old_num = NumberOfChecks();
   ASSERT(old_num == 0);
-  Array& data = Array::Handle(ic_data());
+  Array& data = Array::Handle(entries());
   const intptr_t new_len = data.Length() + TestEntryLength();
   data = Array::Grow(data, new_len, Heap::kOld);
   WriteSentinel(data, TestEntryLength());
@@ -13306,7 +13380,7 @@
   data.SetAt(data_pos, value);
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
-  set_ic_data_array(data);
+  set_entries(data);
 }
 
 bool ICData::ValidateInterceptor(const Function& target) const {
@@ -13336,7 +13410,7 @@
   ASSERT(NumArgsTested() > 1);  // Otherwise use 'AddReceiverCheck'.
   ASSERT(class_ids.length() == NumArgsTested());
   const intptr_t old_num = NumberOfChecks();
-  Array& data = Array::Handle(ic_data());
+  Array& data = Array::Handle(entries());
   // ICData of static calls with NumArgsTested() > 0 have initially a
   // dummy set of cids entered (see ICData::AddTarget). That entry is
   // overwritten by first real type feedback data.
@@ -13377,11 +13451,11 @@
   data.SetAt(data_pos++, value);
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
-  set_ic_data_array(data);
+  set_entries(data);
 }
 
 RawArray* ICData::Grow(intptr_t* index) const {
-  Array& data = Array::Handle(ic_data());
+  Array& data = Array::Handle(entries());
   // Last entry in array should be a sentinel and will be the new entry
   // that can be updated after growing.
   *index = Length() - 1;
@@ -13456,14 +13530,14 @@
   }
   // Multithreaded access to ICData requires setting of array to be the last
   // operation.
-  set_ic_data_array(data);
+  set_entries(data);
 }
 
 StaticTypeExactnessState ICData::GetExactnessAt(intptr_t index) const {
   if (!IsTrackingExactness()) {
     return StaticTypeExactnessState::NotTracking();
   }
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   intptr_t data_pos = index * TestEntryLength();
   return StaticTypeExactnessState::Decode(
       Smi::Value(Smi::RawCast(data.At(data_pos + NumArgsTested() + 2))));
@@ -13476,7 +13550,7 @@
   ASSERT(class_ids != NULL);
   ASSERT(target != NULL);
   class_ids->Clear();
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   intptr_t data_pos = index * TestEntryLength();
   for (intptr_t i = 0; i < NumArgsTested(); i++) {
     class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++))));
@@ -13486,7 +13560,7 @@
 
 bool ICData::IsSentinelAt(intptr_t index) const {
   ASSERT(index < Length());
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t entry_length = TestEntryLength();
   intptr_t data_pos = index * TestEntryLength();
   for (intptr_t i = 0; i < entry_length; i++) {
@@ -13504,7 +13578,7 @@
   ASSERT(class_ids != NULL);
   ASSERT(!IsSentinelAt(index));
   class_ids->Clear();
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   intptr_t data_pos = index * TestEntryLength();
   for (intptr_t i = 0; i < NumArgsTested(); i++) {
     class_ids->Add(Smi::Value(Smi::RawCast(data.At(data_pos++))));
@@ -13517,7 +13591,7 @@
   ASSERT(class_id != NULL);
   ASSERT(target != NULL);
   ASSERT(NumArgsTested() == 1);
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos = index * TestEntryLength();
   *class_id = Smi::Value(Smi::RawCast(data.At(data_pos)));
   *target ^= data.At(data_pos + 1);
@@ -13525,7 +13599,7 @@
 
 intptr_t ICData::GetCidAt(intptr_t index) const {
   ASSERT(NumArgsTested() == 1);
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos = index * TestEntryLength();
   return Smi::Value(Smi::RawCast(data.At(data_pos)));
 }
@@ -13541,17 +13615,17 @@
   ASSERT(!IsSentinelAt(index));
   const intptr_t data_pos = index * TestEntryLength();
   NoSafepointScope no_safepoint;
-  RawArray* raw_data = ic_data();
+  RawArray* raw_data = entries();
   return Smi::Value(Smi::RawCast(raw_data->ptr()->data()[data_pos]));
 }
 
 RawFunction* ICData::GetTargetAt(intptr_t index) const {
   ASSERT(Isolate::Current()->compilation_allowed());
   const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
-  ASSERT(Object::Handle(Array::Handle(ic_data()).At(data_pos)).IsFunction());
+  ASSERT(Object::Handle(Array::Handle(entries()).At(data_pos)).IsFunction());
 
   NoSafepointScope no_safepoint;
-  RawArray* raw_data = ic_data();
+  RawArray* raw_data = entries();
   return reinterpret_cast<RawFunction*>(raw_data->ptr()->data()[data_pos]);
 }
 
@@ -13559,7 +13633,7 @@
   const intptr_t data_pos = index * TestEntryLength() + NumArgsTested();
 
   NoSafepointScope no_safepoint;
-  RawArray* raw_data = ic_data();
+  RawArray* raw_data = entries();
   return raw_data->ptr()->data()[data_pos];
 }
 
@@ -13573,7 +13647,7 @@
   ASSERT(0 <= value);
   ASSERT(value <= Smi::kMaxValue);
 
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos =
       index * TestEntryLength() + CountIndexFor(NumArgsTested());
   data.SetAt(data_pos, Smi::Handle(Smi::New(value)));
@@ -13581,7 +13655,7 @@
 
 intptr_t ICData::GetCountAt(intptr_t index) const {
   ASSERT(Isolate::Current()->compilation_allowed());
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos =
       index * TestEntryLength() + CountIndexFor(NumArgsTested());
   intptr_t value = Smi::Value(Smi::RawCast(data.At(data_pos)));
@@ -13605,7 +13679,7 @@
 
 void ICData::SetCodeAt(intptr_t index, const Code& value) const {
   ASSERT(!Isolate::Current()->compilation_allowed());
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos =
       index * TestEntryLength() + CodeIndexFor(NumArgsTested());
   data.SetAt(data_pos, value);
@@ -13613,7 +13687,7 @@
 
 void ICData::SetEntryPointAt(intptr_t index, const Smi& value) const {
   ASSERT(!Isolate::Current()->compilation_allowed());
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   const intptr_t data_pos =
       index * TestEntryLength() + EntryPointIndexFor(NumArgsTested());
   data.SetAt(data_pos, value);
@@ -13748,7 +13822,7 @@
     pos += result.TestEntryLength();
   }
   WriteSentinel(data, result.TestEntryLength());
-  result.set_ic_data_array(data);
+  result.set_entries(data);
   ASSERT(result.NumberOfChecksIs(aggregate.length()));
   return result.raw();
 }
@@ -13906,7 +13980,7 @@
 }
 
 bool ICData::IsImmutable() const {
-  const Array& data = Array::Handle(ic_data());
+  const Array& data = Array::Handle(entries());
   return data.IsImmutable();
 }
 
@@ -13936,7 +14010,7 @@
       zone,
       NewDescriptor(zone, owner, target_name, arguments_descriptor, deopt_id,
                     num_args_tested, rebind_rule, static_receiver_type));
-  result.set_ic_data_array(Array::Handle(
+  result.set_entries(Array::Handle(
       zone,
       CachedEmptyICDataArray(num_args_tested, result.IsTrackingExactness())));
   return result.raw();
@@ -13963,7 +14037,7 @@
       from.NumArgsTested(), from.rebind_rule(),
       AbstractType::Handle(from.StaticReceiverType())));
   // Clone entry array.
-  const Array& from_array = Array::Handle(zone, from.ic_data());
+  const Array& from_array = Array::Handle(zone, from.entries());
   const intptr_t len = from_array.Length();
   const Array& cloned_array = Array::Handle(zone, Array::New(len, Heap::kOld));
   Object& obj = Object::Handle(zone);
@@ -13971,7 +14045,7 @@
     obj = from_array.At(i);
     cloned_array.SetAt(i, obj);
   }
-  result.set_ic_data_array(cloned_array);
+  result.set_entries(cloned_array);
   // Copy deoptimization reasons.
   result.SetDeoptReasons(from.DeoptReasons());
   return result.raw();
@@ -14435,7 +14509,8 @@
     if (FLAG_write_protect_code) {
       uword address = RawObject::ToAddr(instrs.raw());
       VirtualMemory::Protect(reinterpret_cast<void*>(address),
-                             instrs.raw()->Size(), VirtualMemory::kReadExecute);
+                             instrs.raw()->HeapSize(),
+                             VirtualMemory::kReadExecute);
     }
   }
   CPU::FlushICache(instrs.PayloadStart(), instrs.Size());
@@ -14769,27 +14844,6 @@
 #endif
 }
 
-void Bytecode::set_instructions(const ExternalTypedData& instructions) const {
-#if !defined(DART_PRECOMPILED_RUNTIME)
-  ASSERT(Thread::Current()->IsMutatorThread());
-  // The interpreter requires the instructions to be aligned.
-  ASSERT(Utils::IsAligned(instructions.DataAddr(0), sizeof(KBCInstr)));
-  StorePointer(&raw_ptr()->instructions_, instructions.raw());
-#else
-  UNREACHABLE();
-#endif
-}
-
-uword Bytecode::PayloadStart() const {
-  const ExternalTypedData& instr = ExternalTypedData::Handle(instructions());
-  return reinterpret_cast<uword>(instr.DataAddr(0));
-}
-
-intptr_t Bytecode::Size() const {
-  const ExternalTypedData& instr = ExternalTypedData::Handle(instructions());
-  return instr.LengthInBytes();
-}
-
 void Bytecode::Disassemble(DisassemblyFormatter* formatter) const {
 #if !defined(PRODUCT) || defined(FORCE_INCLUDE_DISASSEMBLER)
 #if !defined(DART_PRECOMPILED_RUNTIME)
@@ -14809,7 +14863,9 @@
 }
 
 #if !defined(DART_PRECOMPILED_RUNTIME)
-RawBytecode* Bytecode::New(const ExternalTypedData& instructions,
+RawBytecode* Bytecode::New(uword instructions,
+                           intptr_t instructions_size,
+                           intptr_t instructions_offset,
                            const ObjectPool& object_pool) {
   ASSERT(Object::bytecode_class() != Class::null());
   Bytecode& result = Bytecode::Handle();
@@ -14818,9 +14874,11 @@
     RawObject* raw = Object::Allocate(Bytecode::kClassId, size, Heap::kOld);
     NoSafepointScope no_safepoint;
     result ^= raw;
-    result.set_pc_descriptors(Object::empty_descriptors());
     result.set_instructions(instructions);
+    result.set_instructions_size(instructions_size);
     result.set_object_pool(object_pool);
+    result.set_pc_descriptors(Object::empty_descriptors());
+    result.set_instructions_binary_offset(instructions_offset);
     result.set_source_positions_binary_offset(0);
   }
   return result.raw();
@@ -20053,7 +20111,7 @@
 RawArray* Array::New(intptr_t len, Heap::Space space) {
   ASSERT(Isolate::Current()->object_store()->array_class() != Class::null());
   RawArray* result = New(kClassId, len, space);
-  if (result->Size() > Heap::kNewAllocatableSize) {
+  if (result->HeapSize() > Heap::kNewAllocatableSize) {
     ASSERT(result->IsOldObject());
     result->SetCardRememberedBitUnsynchronized();
   }
@@ -20718,21 +20776,6 @@
   return result.raw();
 }
 
-RawTypedData* TypedData::EmptyUint32Array(Thread* thread) {
-  ASSERT(thread != NULL);
-  Isolate* isolate = thread->isolate();
-  ASSERT(isolate != NULL);
-  ASSERT(isolate->object_store() != NULL);
-  if (isolate->object_store()->empty_uint32_array() != TypedData::null()) {
-    // Already created.
-    return isolate->object_store()->empty_uint32_array();
-  }
-  const TypedData& array = TypedData::Handle(
-      thread->zone(), TypedData::New(kTypedDataUint32ArrayCid, 0, Heap::kOld));
-  isolate->object_store()->set_empty_uint32_array(array);
-  return array.raw();
-}
-
 const char* TypedData::ToCString() const {
   switch (GetClassId()) {
 #define CASE_TYPED_DATA_CLASS(clazz)                                           \
@@ -20774,6 +20817,75 @@
   return "ExternalTypedData";
 }
 
+RawPointer* Pointer::New(const AbstractType& type_arg,
+                         uint8_t* c_memory_address,
+                         intptr_t cid,
+                         Heap::Space space) {
+  Thread* thread = Thread::Current();
+  Zone* zone = thread->zone();
+  TypeArguments& type_args = TypeArguments::Handle(zone);
+  type_args = TypeArguments::New(1);
+  type_args.SetTypeAt(Pointer::kNativeTypeArgPos, type_arg);
+  type_args ^= type_args.Canonicalize();
+
+  const Class& cls = Class::Handle(Isolate::Current()->class_table()->At(cid));
+  cls.EnsureIsFinalized(Thread::Current());
+
+  Pointer& result = Pointer::Handle(zone);
+  result ^= Object::Allocate(cid, Pointer::InstanceSize(), space);
+  NoSafepointScope no_safepoint;
+  result.SetTypeArguments(type_args);
+  result.SetCMemoryAddress(c_memory_address);
+
+  return result.raw();
+}
+
+const char* Pointer::ToCString() const {
+  TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+  String& type_args_name = String::Handle(type_args.UserVisibleName());
+  return OS::SCreate(Thread::Current()->zone(), "Pointer%s: address=%p",
+                     type_args_name.ToCString(), GetCMemoryAddress());
+}
+
+RawDynamicLibrary* DynamicLibrary::New(void* handle, Heap::Space space) {
+  DynamicLibrary& result = DynamicLibrary::Handle();
+  result ^= Object::Allocate(kFfiDynamicLibraryCid,
+                             DynamicLibrary::InstanceSize(), space);
+  NoSafepointScope no_safepoint;
+  result.SetHandle(handle);
+  return result.raw();
+}
+
+bool Pointer::IsPointer(const Instance& obj) {
+  ASSERT(!obj.IsNull());
+
+  // fast path for predefined classes
+  intptr_t cid = obj.raw()->GetClassId();
+  if (RawObject::IsFfiPointerClassId(cid)) {
+    return true;
+  }
+
+  // slow check for subtyping
+  const Class& pointer_class = Class::ZoneHandle(
+      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);
+  AbstractType& type = AbstractType::Handle(obj.GetType(Heap::kNew));
+  return type.IsSubtypeOf(pointer_type, Heap::kNew);
+}
+
+bool Instance::IsPointer() const {
+  return Pointer::IsPointer(*this);
+}
+
+const char* DynamicLibrary::ToCString() const {
+  return OS::SCreate(Thread::Current()->zone(), "DynamicLibrary: handle=%p",
+                     GetHandle());
+}
+
 RawCapability* Capability::New(uint64_t id, Heap::Space space) {
   Capability& result = Capability::Handle();
   {
diff --git a/runtime/vm/object.h b/runtime/vm/object.h
index 8f789d9..e426c9d0 100644
--- a/runtime/vm/object.h
+++ b/runtime/vm/object.h
@@ -29,6 +29,7 @@
 #include "vm/os.h"
 #include "vm/raw_object.h"
 #include "vm/report.h"
+#include "vm/static_type_exactness_state.h"
 #include "vm/tags.h"
 #include "vm/thread.h"
 #include "vm/token_position.h"
@@ -430,6 +431,9 @@
   static RawClass* closure_data_class() { return closure_data_class_; }
   static RawClass* signature_data_class() { return signature_data_class_; }
   static RawClass* redirection_data_class() { return redirection_data_class_; }
+  static RawClass* ffi_trampoline_data_class() {
+    return ffi_trampoline_data_class_;
+  }
   static RawClass* field_class() { return field_class_; }
   static RawClass* script_class() { return script_class_; }
   static RawClass* library_class() { return library_class_; }
@@ -677,6 +681,8 @@
   static RawClass* closure_data_class_;    // Class of ClosureData vm obj.
   static RawClass* signature_data_class_;  // Class of SignatureData vm obj.
   static RawClass* redirection_data_class_;  // Class of RedirectionData vm obj.
+  static RawClass* ffi_trampoline_data_class_;  // Class of FfiTrampolineData
+                                                // vm obj.
   static RawClass* field_class_;             // Class of the Field vm object.
   static RawClass* script_class_;        // Class of the Script vm object.
   static RawClass* library_class_;       // Class of the Library vm object.
@@ -837,6 +843,9 @@
     StoreNonPointer(&raw_ptr()->id_, value);
   }
   static intptr_t id_offset() { return OFFSET_OF(RawClass, id_); }
+  static intptr_t num_type_arguments_offset() {
+    return OFFSET_OF(RawClass, num_type_arguments_);
+  }
 
   RawString* Name() const;
   RawString* ScrubbedName() const;
@@ -949,20 +958,15 @@
   // classes.
   RawClass* SuperClass(bool original_classes = false) const;
 
-  RawClass* GetPatchClass() const;
-
   // Interfaces is an array of Types.
   RawArray* interfaces() const { return raw_ptr()->interfaces_; }
   void set_interfaces(const Array& value) const;
-  static intptr_t interfaces_offset() {
-    return OFFSET_OF(RawClass, interfaces_);
-  }
 
   // Returns the list of classes directly implementing this class.
   RawGrowableObjectArray* direct_implementors() const {
     return raw_ptr()->direct_implementors_;
   }
-  void AddDirectImplementor(const Class& subclass) const;
+  void AddDirectImplementor(const Class& subclass, bool is_mixin) const;
   void ClearDirectImplementors() const;
 
   // Returns the list of classes having this class as direct superclass.
@@ -1082,8 +1086,6 @@
   RawField* LookupInstanceFieldAllowPrivate(const String& name) const;
   RawField* LookupStaticFieldAllowPrivate(const String& name) const;
 
-  RawLibraryPrefix* LookupLibraryPrefix(const String& name) const;
-
   RawDouble* LookupCanonicalDouble(Zone* zone, double value) const;
   RawMint* LookupCanonicalMint(Zone* zone, int64_t value) const;
 
@@ -1171,6 +1173,9 @@
   }
   void set_is_allocated(bool value) const;
 
+  bool is_loaded() const { return IsLoadedBit::decode(raw_ptr()->state_bits_); }
+  void set_is_loaded(bool value) const;
+
   uint16_t num_native_fields() const { return raw_ptr()->num_native_fields_; }
   void set_num_native_fields(uint16_t value) const {
     StoreNonPointer(&raw_ptr()->num_native_fields_, value);
@@ -1260,6 +1265,9 @@
   // Allocate the raw ExternalTypedData classes.
   static RawClass* NewExternalTypedDataClass(intptr_t class_id);
 
+  // Allocate the raw Pointer classes.
+  static RawClass* NewPointerClass(intptr_t class_id);
+
   // Register code that has used CHA for optimization.
   // TODO(srdjan): Also register kind of CHA optimization (e.g.: leaf class,
   // leaf method, ...).
@@ -1335,6 +1343,7 @@
     kEnumBit,
     kTransformedMixinApplicationBit,
     kIsAllocatedBit,
+    kIsLoadedBit,
   };
   class ConstBit : public BitField<uint16_t, bool, kConstBit, 1> {};
   class ImplementedBit : public BitField<uint16_t, bool, kImplementedBit, 1> {};
@@ -1355,6 +1364,7 @@
   class TransformedMixinApplicationBit
       : public BitField<uint16_t, bool, kTransformedMixinApplicationBit, 1> {};
   class IsAllocatedBit : public BitField<uint16_t, bool, kIsAllocatedBit, 1> {};
+  class IsLoadedBit : public BitField<uint16_t, bool, kIsLoadedBit, 1> {};
 
   void set_name(const String& value) const;
   void set_user_name(const String& value) const;
@@ -1390,9 +1400,6 @@
 
   int16_t num_type_arguments() const { return raw_ptr()->num_type_arguments_; }
   void set_num_type_arguments(intptr_t value) const;
-  static intptr_t num_type_arguments_offset() {
-    return OFFSET_OF(RawClass, num_type_arguments_);
-  }
 
  public:
   bool has_pragma() const {
@@ -1543,134 +1550,6 @@
   friend class Class;
 };
 
-// Representation of a state of runtime tracking of static type exactness for
-// a particular location in the program (e.g. exactness of type annotation
-// on a field).
-//
-// Given the static type G<T0, ..., Tn> we say that it is exact iff any
-// values that can be observed at this location has runtime type T such that
-// type arguments of T at G are exactly <T0, ..., Tn>.
-//
-// Currently we only support tracking for locations that are also known
-// to be monomorphic with respect to the actual class of the values it contains.
-//
-// Important: locations should never switch from tracked (kIsTriviallyExact,
-// kHasExactSuperType, kHasExactSuperClass, kNotExact) to not tracked
-// (kNotTracking) or the other way around because that would affect unoptimized
-// graphs generated by graph builder and skew deopt ids.
-class StaticTypeExactnessState final {
- public:
-  // Values stored in the location with static type G<T0, ..., Tn> are all
-  // instances of C<T0, ..., Tn> and C<U0, ..., Un> at G has type parameters
-  // <U0, ..., Un>.
-  //
-  // For trivially exact types we can simply compare type argument
-  // vectors as pointers to check exactness. That's why we represent
-  // trivially exact locations as offset in words to the type arguments of
-  // class C. All other states are represented as non-positive values.
-  //
-  // Note: we are ignoring the type argument vector sharing optimization for
-  // now.
-  static inline StaticTypeExactnessState TriviallyExact(
-      intptr_t type_arguments_offset) {
-    ASSERT((type_arguments_offset > 0) &&
-           Utils::IsAligned(type_arguments_offset, kWordSize) &&
-           Utils::IsInt(8, type_arguments_offset / kWordSize));
-    return StaticTypeExactnessState(type_arguments_offset / kWordSize);
-  }
-
-  static inline bool CanRepresentAsTriviallyExact(
-      intptr_t type_arguments_offset) {
-    return Utils::IsInt(8, type_arguments_offset / kWordSize);
-  }
-
-  // Values stored in the location with static type G<T0, ..., Tn> are all
-  // instances of class C<...> and C<U0, ..., Un> at G has type
-  // parameters <T0, ..., Tn> for any <U0, ..., Un> - that is C<...> has a
-  // supertype G<T0, ..., Tn>.
-  //
-  // For such locations we can simply check if the value stored
-  // is an instance of an expected class and we don't have to look at
-  // type arguments carried by the instance.
-  //
-  // We distinguish situations where we know that G is a superclass of C from
-  // situations where G might be superinterface of C - because in the first
-  // type arguments of G give us constant prefix of type arguments of C.
-  static inline StaticTypeExactnessState HasExactSuperType() {
-    return StaticTypeExactnessState(kHasExactSuperType);
-  }
-
-  static inline StaticTypeExactnessState HasExactSuperClass() {
-    return StaticTypeExactnessState(kHasExactSuperClass);
-  }
-
-  // Values stored in the location don't fall under either kIsTriviallyExact
-  // or kHasExactSuperType categories.
-  //
-  // Note: that does not imply that static type annotation is not exact
-  // according to a broader definition, e.g. location might simply be
-  // polymorphic and store instances of multiple different types.
-  // However for simplicity we don't track such cases yet.
-  static inline StaticTypeExactnessState NotExact() {
-    return StaticTypeExactnessState(kNotExact);
-  }
-
-  // The location does not track exactness of its static type at runtime.
-  static inline StaticTypeExactnessState NotTracking() {
-    return StaticTypeExactnessState(kNotTracking);
-  }
-
-  static inline StaticTypeExactnessState Unitialized() {
-    return StaticTypeExactnessState(kUninitialized);
-  }
-
-  static StaticTypeExactnessState Compute(const Type& static_type,
-                                          const Instance& value,
-                                          bool print_trace = false);
-
-  bool IsTracking() const { return value_ != kNotTracking; }
-  bool IsUninitialized() const { return value_ == kUninitialized; }
-  bool IsHasExactSuperClass() const { return value_ == kHasExactSuperClass; }
-  bool IsHasExactSuperType() const { return value_ == kHasExactSuperType; }
-  bool IsTriviallyExact() const { return value_ > kUninitialized; }
-  bool NeedsFieldGuard() const { return value_ >= kUninitialized; }
-  bool IsExactOrUninitialized() const { return value_ > kNotExact; }
-  bool IsExact() const {
-    return IsTriviallyExact() || IsHasExactSuperType() ||
-           IsHasExactSuperClass();
-  }
-
-  const char* ToCString() const;
-
-  StaticTypeExactnessState CollapseSuperTypeExactness() const {
-    return IsHasExactSuperClass() ? HasExactSuperType() : *this;
-  }
-
-  static inline StaticTypeExactnessState Decode(int8_t value) {
-    return StaticTypeExactnessState(value);
-  }
-
-  int8_t Encode() const { return value_; }
-  intptr_t GetTypeArgumentsOffsetInWords() const {
-    ASSERT(IsTriviallyExact());
-    return value_;
-  }
-
-  static constexpr int8_t kUninitialized = 0;
-
- private:
-  static constexpr int8_t kNotTracking = -4;
-  static constexpr int8_t kNotExact = -3;
-  static constexpr int8_t kHasExactSuperType = -2;
-  static constexpr int8_t kHasExactSuperClass = -1;
-
-  explicit StaticTypeExactnessState(int8_t value) : value_(value) {}
-
-  int8_t value_;
-
-  DISALLOW_ALLOCATION();
-};
-
 // Object holding information about an IC: test classes and their
 // corresponding targets. The owner of the ICData can be either the function
 // or the original ICData object. In case of background compilation we
@@ -1819,7 +1698,7 @@
     return OFFSET_OF(RawICData, args_descriptor_);
   }
 
-  static intptr_t ic_data_offset() { return OFFSET_OF(RawICData, ic_data_); }
+  static intptr_t entries_offset() { return OFFSET_OF(RawICData, entries_); }
 
   static intptr_t owner_offset() { return OFFSET_OF(RawICData, owner_); }
 
@@ -1983,8 +1862,8 @@
  private:
   static RawICData* New();
 
-  RawArray* ic_data() const {
-    return AtomicOperations::LoadAcquire(&raw_ptr()->ic_data_);
+  RawArray* entries() const {
+    return AtomicOperations::LoadAcquire(&raw_ptr()->entries_);
   }
 
   // Grows the array and also sets the argument to the index that should be used
@@ -1996,7 +1875,7 @@
   void set_arguments_descriptor(const Array& value) const;
   void set_deopt_id(intptr_t value) const;
   void SetNumArgsTested(intptr_t value) const;
-  void set_ic_data_array(const Array& value) const;
+  void set_entries(const Array& value) const;
   void set_state_bits(uint32_t bits) const;
 
   bool ValidateInterceptor(const Function& target) const;
@@ -2254,6 +2133,10 @@
 
   static intptr_t code_offset() { return OFFSET_OF(RawFunction, code_); }
 
+  static intptr_t result_type_offset() {
+    return OFFSET_OF(RawFunction, result_type_);
+  }
+
   static intptr_t entry_point_offset() {
     return OFFSET_OF(RawFunction, entry_point_);
   }
@@ -2680,6 +2563,14 @@
            RawFunction::kSignatureFunction;
   }
 
+  // Returns true if this function represents an ffi trampoline.
+  bool IsFfiTrampoline() const { return kind() == RawFunction::kFfiTrampoline; }
+  static bool IsFfiTrampoline(RawFunction* function) {
+    NoSafepointScope no_safepoint;
+    return KindBits::decode(function->ptr()->kind_tag_) ==
+           RawFunction::kFfiTrampoline;
+  }
+
   bool IsAsyncFunction() const { return modifier() == RawFunction::kAsync; }
 
   bool IsAsyncClosure() const {
@@ -3081,6 +2972,25 @@
 
 enum class EntryPointPragma { kAlways, kNever, kGetterOnly, kSetterOnly };
 
+class FfiTrampolineData : public Object {
+ public:
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawFfiTrampolineData));
+  }
+
+ private:
+  // Signature type of this closure function.
+  RawType* signature_type() const { return raw_ptr()->signature_type_; }
+  void set_signature_type(const Type& value) const;
+
+  static RawFfiTrampolineData* New();
+
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData, Object);
+  friend class Class;
+  friend class Function;
+  friend class HeapProfiler;
+};
+
 class Field : public Object {
  public:
   RawField* Original() const;
@@ -3349,11 +3259,9 @@
 
   DART_WARN_UNUSED_RESULT RawError* EvaluateInitializer() const;
 
-  RawFunction* PrecompiledInitializer() const {
-    return raw_ptr()->initializer_.precompiled_;
-  }
-  void SetPrecompiledInitializer(const Function& initializer) const;
-  bool HasPrecompiledInitializer() const;
+  RawFunction* Initializer() const { return raw_ptr()->initializer_; }
+  void SetInitializer(const Function& initializer) const;
+  bool HasInitializer() const;
 
   // For static fields only. Constructs a closure that gets/sets the
   // field value.
@@ -3643,10 +3551,6 @@
   void SetLoadError(const Instance& error) const;
   RawInstance* TransitiveLoadError() const;
 
-  void AddPatchClass(const Class& cls) const;
-  RawClass* GetPatchClass(const String& name) const;
-  void RemovePatchClass(const Class& cls) const;
-
   static intptr_t InstanceSize() {
     return RoundedAllocationSize(sizeof(RawLibrary));
   }
@@ -3686,12 +3590,9 @@
   // more regular.
   void AddClass(const Class& cls) const;
   void AddObject(const Object& obj, const String& name) const;
-  void ReplaceObject(const Object& obj, const String& name) const;
   RawObject* LookupReExport(const String& name,
                             ZoneGrowableArray<intptr_t>* visited = NULL) const;
   RawObject* LookupObjectAllowPrivate(const String& name) const;
-  RawObject* LookupLocalObjectAllowPrivate(const String& name) const;
-  RawObject* LookupLocalObject(const String& name) const;
   RawObject* LookupLocalOrReExportObject(const String& name) const;
   RawObject* LookupImportedObject(const String& name) const;
   RawClass* LookupClass(const String& name) const;
@@ -3765,7 +3666,6 @@
   intptr_t num_imports() const { return raw_ptr()->num_imports_; }
   RawNamespace* ImportAt(intptr_t index) const;
   RawLibrary* ImportLibraryAt(intptr_t index) const;
-  bool ImportsCorelib() const;
 
   void DropDependenciesAndCaches() const;
 
@@ -3811,8 +3711,6 @@
     StoreNonPointer(&raw_ptr()->is_dart_scheme_, value);
   }
 
-  bool IsCoreLibrary() const { return raw() == CoreLibrary(); }
-
   // Includes 'dart:async', 'dart:typed_data', etc.
   bool IsAnyCoreLibrary() const;
 
@@ -3843,6 +3741,7 @@
   static RawLibrary* CoreLibrary();
   static RawLibrary* CollectionLibrary();
   static RawLibrary* DeveloperLibrary();
+  static RawLibrary* FfiLibrary();
   static RawLibrary* InternalLibrary();
   static RawLibrary* IsolateLibrary();
   static RawLibrary* MathLibrary();
@@ -3894,6 +3793,9 @@
   // for a top level getter 'name' that returns a closure.
   RawObject* GetFunctionClosure(const String& name) const;
 
+  // Ensures that all top-level functions and variables (fields) are loaded.
+  void EnsureTopLevelClassIsFinalized() const;
+
  private:
   static const int kInitialImportsCapacity = 4;
   static const int kImportsCapacityIncrement = 8;
@@ -3932,6 +3834,8 @@
   void RehashDictionary(const Array& old_dict, intptr_t new_dict_size) const;
   static RawLibrary* NewLibraryHelper(const String& url, bool import_core_lib);
   RawObject* LookupEntry(const String& name, intptr_t* index) const;
+  RawObject* LookupLocalObjectAllowPrivate(const String& name) const;
+  RawObject* LookupLocalObject(const String& name) const;
 
   void AllocatePrivateKey() const;
 
@@ -4028,6 +3932,7 @@
   void set_constants_table(const ExternalTypedData& value) const;
 
   RawArray* scripts() const { return raw_ptr()->scripts_; }
+  void set_scripts(const Array& scripts) const;
 
   RawArray* constants() const { return raw_ptr()->constants_; }
   void set_constants(const Array& constants) const;
@@ -5220,11 +5125,10 @@
 
 class Bytecode : public Object {
  public:
-  RawExternalTypedData* instructions() const {
-    return raw_ptr()->instructions_;
-  }
-  uword PayloadStart() const;
-  intptr_t Size() const;
+  uword instructions() const { return raw_ptr()->instructions_; }
+
+  uword PayloadStart() const { return instructions(); }
+  intptr_t Size() const { return raw_ptr()->instructions_size_; }
 
   RawObjectPool* object_pool() const { return raw_ptr()->object_pool_; }
 
@@ -5265,7 +5169,9 @@
     return RoundedAllocationSize(sizeof(RawBytecode));
   }
 #if !defined(DART_PRECOMPILED_RUNTIME)
-  static RawBytecode* New(const ExternalTypedData& instructions,
+  static RawBytecode* New(uword instructions,
+                          intptr_t instructions_size,
+                          intptr_t instructions_offset,
                           const ObjectPool& object_pool);
 #endif
 
@@ -5273,6 +5179,13 @@
 
   TokenPosition GetTokenIndexOfPC(uword pc) const;
 
+  intptr_t instructions_binary_offset() const {
+    return raw_ptr()->instructions_binary_offset_;
+  }
+  void set_instructions_binary_offset(intptr_t value) const {
+    StoreNonPointer(&raw_ptr()->instructions_binary_offset_, value);
+  }
+
   intptr_t source_positions_binary_offset() const {
     return raw_ptr()->source_positions_binary_offset_;
   }
@@ -5303,15 +5216,22 @@
   static RawBytecode* FindCode(uword pc);
 
  private:
+  void set_instructions(uword instructions) const {
+    // The interpreter requires the instructions to be aligned.
+    ASSERT(Utils::IsAligned(instructions, sizeof(uint32_t)));
+    StoreNonPointer(&raw_ptr()->instructions_, instructions);
+  }
+  void set_instructions_size(intptr_t size) const {
+    StoreNonPointer(&raw_ptr()->instructions_size_, size);
+  }
   void set_object_pool(const ObjectPool& object_pool) const {
     StorePointer(&raw_ptr()->object_pool_, object_pool.raw());
   }
 
+  friend class BytecodeDeserializationCluster;
   friend class RawObject;  // For RawObject::SizeFromClass().
   friend class RawBytecode;
 
-  void set_instructions(const ExternalTypedData& instructions) const;
-
   FINAL_HEAP_OBJECT_IMPLEMENTATION(Bytecode, Object);
   friend class Class;
   friend class SnapshotWriter;
@@ -5855,6 +5775,14 @@
   static intptr_t DataOffsetFor(intptr_t cid);
   static intptr_t ElementSizeFor(intptr_t cid);
 
+  // Pointers may be subtyped, but their subtypes may not get extra fields.
+  // The subtype runtime representation has exactly the same object layout,
+  // only the class_id is different. So, it is safe to use subtype instances in
+  // Pointer handles.
+  virtual bool IsPointer() const;
+
+  static intptr_t NextFieldOffset() { return sizeof(RawInstance); }
+
  protected:
 #ifndef PRODUCT
   virtual void PrintSharedInstanceJSON(JSONObject* jsobj, bool ref) const;
@@ -5876,8 +5804,6 @@
   }
   bool IsValidFieldOffset(intptr_t offset) const;
 
-  static intptr_t NextFieldOffset() { return sizeof(RawInstance); }
-
   // The following raw methods are used for morphing.
   // They are needed due to the extraction of the class in IsValidFieldOffset.
   RawObject** RawFieldAddrAtOffset(intptr_t offset) const {
@@ -5895,6 +5821,7 @@
   friend class ByteBuffer;
   friend class Class;
   friend class Closure;
+  friend class Pointer;
   friend class DeferredObject;
   friend class RegExp;
   friend class SnapshotWriter;
@@ -5973,6 +5900,7 @@
 
   intptr_t Length() const;
   RawAbstractType* TypeAt(intptr_t index) const;
+  RawAbstractType* TypeAtNullSafe(intptr_t index) const;
   static intptr_t type_at_offset(intptr_t index) {
     return OFFSET_OF_RETURNED_VALUE(RawTypeArguments, types) +
            index * kWordSize;
@@ -8301,8 +8229,6 @@
     return RawObject::IsTypedDataClassId(cid);
   }
 
-  static RawTypedData* EmptyUint32Array(Thread* thread);
-
  protected:
   void SetLength(intptr_t value) const {
     StoreSmi(&raw_ptr()->length_, Smi::New(value));
@@ -8529,6 +8455,81 @@
   };
 };
 
+class Pointer : public Instance {
+ public:
+  static RawPointer* New(const AbstractType& type_arg,
+                         uint8_t* c_memory_address,
+                         intptr_t class_id = kFfiPointerCid,
+                         Heap::Space space = Heap::kNew);
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawPointer));
+  }
+
+  static bool IsPointer(const Instance& obj);
+
+  uint8_t* GetCMemoryAddress() const {
+    ASSERT(!IsNull());
+    return raw_ptr()->c_memory_address_;
+  }
+
+  void SetCMemoryAddress(uint8_t* value) const {
+    StoreNonPointer(&raw_ptr()->c_memory_address_, value);
+  }
+
+  static intptr_t type_arguments_offset() {
+    return OFFSET_OF(RawPointer, type_arguments_);
+  }
+
+  static intptr_t address_offset() {
+    return OFFSET_OF(RawPointer, c_memory_address_);
+  }
+
+  static intptr_t NextFieldOffset() { return sizeof(RawPointer); }
+
+  static const intptr_t kNativeTypeArgPos = 0;
+
+  // Fetches the NativeType type argument.
+  RawAbstractType* type_argument() const {
+    TypeArguments& type_args = TypeArguments::Handle(GetTypeArguments());
+    return type_args.TypeAtNullSafe(Pointer::kNativeTypeArgPos);
+  }
+
+ private:
+  HEAP_OBJECT_IMPLEMENTATION(Pointer, Instance);
+
+  friend class Class;
+};
+
+class DynamicLibrary : public Instance {
+ public:
+  static RawDynamicLibrary* New(void* handle, Heap::Space space = Heap::kNew);
+
+  static intptr_t InstanceSize() {
+    return RoundedAllocationSize(sizeof(RawDynamicLibrary));
+  }
+
+  static bool IsDynamicLibrary(const Instance& obj) {
+    ASSERT(!obj.IsNull());
+    intptr_t cid = obj.raw()->GetClassId();
+    return RawObject::IsFfiDynamicLibraryClassId(cid);
+  }
+
+  void* GetHandle() const {
+    ASSERT(!IsNull());
+    return raw_ptr()->handle_;
+  }
+
+  void SetHandle(void* value) const {
+    StoreNonPointer(&raw_ptr()->handle_, value);
+  }
+
+ private:
+  FINAL_HEAP_OBJECT_IMPLEMENTATION(DynamicLibrary, Instance);
+
+  friend class Class;
+};
+
 // Corresponds to
 // - "new Map()",
 // - non-const map literals, and
@@ -9131,8 +9132,9 @@
   ASSERT(is_static());  // Valid only for static dart fields.
   StorePointer(&raw_ptr()->value_.static_value_, value.raw());
   if (save_initial_value) {
-    ASSERT(!HasPrecompiledInitializer());
-    StorePointer(&raw_ptr()->initializer_.saved_value_, value.raw());
+#if !defined(DART_PRECOMPILED_RUNTIME)
+    StorePointer(&raw_ptr()->saved_initial_value_, value.raw());
+#endif
   }
 }
 
diff --git a/runtime/vm/object_graph.cc b/runtime/vm/object_graph.cc
index 6edb424..6b7cda3 100644
--- a/runtime/vm/object_graph.cc
+++ b/runtime/vm/object_graph.cc
@@ -135,7 +135,7 @@
   ASSERT(child.obj == *child.ptr);
   uword child_ptr_addr = reinterpret_cast<uword>(child.ptr);
   intptr_t offset = child_ptr_addr - parent_start;
-  if (offset > 0 && offset < parent.obj->Size()) {
+  if (offset > 0 && offset < parent.obj->HeapSize()) {
     ASSERT(Utils::IsAligned(offset, kWordSize));
     return offset >> kWordSizeLog2;
   } else {
@@ -272,7 +272,7 @@
     if (ShouldSkip(obj)) {
       return kBacktrack;
     }
-    size_ += obj->Size();
+    size_ += obj->HeapSize();
     return kProceed;
   }
 
@@ -475,7 +475,7 @@
           uword source_start = RawObject::ToAddr(source_);
           uword current_ptr_addr = reinterpret_cast<uword>(current_ptr);
           intptr_t offset = current_ptr_addr - source_start;
-          if (offset > 0 && offset < source_->Size()) {
+          if (offset > 0 && offset < source_->HeapSize()) {
             ASSERT(Utils::IsAligned(offset, kWordSize));
             *scratch_ = Smi::New(offset >> kWordSizeLog2);
           } else {
@@ -583,7 +583,7 @@
     if ((roots_ == ObjectGraph::kVM) || obj.IsField() || obj.IsInstance() ||
         obj.IsContext()) {
       // Each object is a header + a zero-terminated list of its neighbors.
-      WriteHeader(raw_obj, raw_obj->Size(), obj.GetClassId(), stream_);
+      WriteHeader(raw_obj, raw_obj->HeapSize(), obj.GetClassId(), stream_);
       raw_obj->VisitPointers(&ptr_writer_);
       stream_->WriteUnsigned(0);
       ++count_;
diff --git a/runtime/vm/object_graph_test.cc b/runtime/vm/object_graph_test.cc
index 72cffef..c4f1515 100644
--- a/runtime/vm/object_graph_test.cc
+++ b/runtime/vm/object_graph_test.cc
@@ -23,7 +23,7 @@
       return kBacktrack;
     }
     ++count_;
-    size_ += obj->Size();
+    size_ += obj->HeapSize();
     return kProceed;
   }
 
@@ -52,10 +52,10 @@
   b.SetAt(0, c);
   b.SetAt(1, d);
   a.SetAt(11, d);
-  intptr_t a_size = a.raw()->Size();
-  intptr_t b_size = b.raw()->Size();
-  intptr_t c_size = c.raw()->Size();
-  intptr_t d_size = d.raw()->Size();
+  intptr_t a_size = a.raw()->HeapSize();
+  intptr_t b_size = b.raw()->HeapSize();
+  intptr_t c_size = c.raw()->HeapSize();
+  intptr_t d_size = d.raw()->HeapSize();
   {
     // No more allocation; raw pointers ahead.
     SafepointOperationScope safepoint(thread);
diff --git a/runtime/vm/object_reload.cc b/runtime/vm/object_reload.cc
index 4082a1b..ffd3cb9 100644
--- a/runtime/vm/object_reload.cc
+++ b/runtime/vm/object_reload.cc
@@ -725,7 +725,7 @@
         // count.
         ClearCountAt(0);
         WriteSentinelAt(1);
-        const Array& array = Array::Handle(ic_data());
+        const Array& array = Array::Handle(entries());
         array.Truncate(2 * TestEntryLength());
         return;
       }
@@ -733,7 +733,7 @@
     }
     const Array& data_array = Array::Handle(
         zone, CachedEmptyICDataArray(num_args, tracking_exactness));
-    set_ic_data_array(data_array);
+    set_entries(data_array);
     return;
   } else if (rule == kNoRebind || rule == kNSMDispatch) {
     // TODO(30877) we should account for addition/removal of NSM.
diff --git a/runtime/vm/object_service.cc b/runtime/vm/object_service.cc
index c0c1152..1562714 100644
--- a/runtime/vm/object_service.cc
+++ b/runtime/vm/object_service.cc
@@ -43,7 +43,7 @@
   }
   if (!ref) {
     if (raw()->IsHeapObject()) {
-      jsobj->AddProperty("size", raw()->Size());
+      jsobj->AddProperty("size", raw()->HeapSize());
     } else {
       jsobj->AddProperty("size", (intptr_t)0);
     }
@@ -349,6 +349,10 @@
   Object::PrintJSONImpl(stream, ref);
 }
 
+void FfiTrampolineData::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  Object::PrintJSONImpl(stream, ref);
+}
+
 void Field::PrintJSONImpl(JSONStream* stream, bool ref) const {
   JSONObject jsobj(stream);
   Class& cls = Class::Handle(Owner());
@@ -758,7 +762,7 @@
   }
   jsobj.AddProperty("_argumentsDescriptor",
                     Object::Handle(arguments_descriptor()));
-  jsobj.AddProperty("_entries", Object::Handle(ic_data()));
+  jsobj.AddProperty("_entries", Object::Handle(entries()));
 }
 
 void ICData::PrintToJSONArray(const JSONArray& jsarray,
@@ -1416,6 +1420,20 @@
   }
 }
 
+void Pointer::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // TODO(dacoharkes): what is the JSONStream used for?
+  // should it fail because it's not supported?
+  // or should it print something reasonable as default?
+  Instance::PrintJSONImpl(stream, ref);
+}
+
+void DynamicLibrary::PrintJSONImpl(JSONStream* stream, bool ref) const {
+  // TODO(dacoharkes): what is the JSONStream used for?
+  // should it fail because it's not supported?
+  // or should it print something reasonable as default?
+  Instance::PrintJSONImpl(stream, ref);
+}
+
 void Capability::PrintJSONImpl(JSONStream* stream, bool ref) const {
   Instance::PrintJSONImpl(stream, ref);
 }
diff --git a/runtime/vm/object_store.h b/runtime/vm/object_store.h
index 855db28..a4f0227 100644
--- a/runtime/vm/object_store.h
+++ b/runtime/vm/object_store.h
@@ -22,6 +22,7 @@
   M(Collection, collection)                                                    \
   M(Convert, convert)                                                          \
   M(Developer, developer)                                                      \
+  M(Ffi, ffi)                                                                  \
   M(Internal, _internal)                                                       \
   M(Isolate, isolate)                                                          \
   M(Math, math)                                                                \
@@ -89,6 +90,7 @@
   RW(Library, collection_library)                                              \
   RW(Library, convert_library)                                                 \
   RW(Library, developer_library)                                               \
+  RW(Library, ffi_library)                                                     \
   RW(Library, _internal_library)                                               \
   RW(Library, isolate_library)                                                 \
   RW(Library, math_library)                                                    \
@@ -111,7 +113,6 @@
   RW(UnhandledException, preallocated_unhandled_exception)                     \
   RW(StackTrace, preallocated_stack_trace)                                     \
   RW(Function, lookup_port_handler)                                            \
-  RW(TypedData, empty_uint32_array)                                            \
   RW(Function, handle_message_function)                                        \
   RW(Function, growable_list_factory)                                          \
   RW(Function, simple_instance_of_function)                                    \
@@ -138,6 +139,8 @@
   RW(Array, code_order_table)                                                  \
   RW(Array, obfuscation_map)                                                   \
   RW(GrowableObjectArray, changed_in_last_reload)                              \
+  RW(Class, ffi_pointer_class)                                                 \
+  RW(Class, ffi_native_type_class)                                             \
 // Please remember the last entry must be referred in the 'to' function below.
 
 // The object store is a per isolate instance which stores references to
@@ -230,7 +233,7 @@
                           DECLARE_OBJECT_STORE_FIELD)
 #undef DECLARE_OBJECT_STORE_FIELD
   RawObject** to() {
-    return reinterpret_cast<RawObject**>(&changed_in_last_reload_);
+    return reinterpret_cast<RawObject**>(&ffi_pointer_class_);
   }
   RawObject** to_snapshot(Snapshot::Kind kind) {
     switch (kind) {
diff --git a/runtime/vm/program_visitor.cc b/runtime/vm/program_visitor.cc
index ec0513f..8260a86 100644
--- a/runtime/vm/program_visitor.cc
+++ b/runtime/vm/program_visitor.cc
@@ -81,8 +81,8 @@
     fields_ = cls.fields();
     for (intptr_t j = 0; j < fields_.Length(); j++) {
       field_ ^= fields_.At(j);
-      if (field_.is_static() && field_.HasPrecompiledInitializer()) {
-        function_ ^= field_.PrecompiledInitializer();
+      if (field_.is_static() && field_.HasInitializer()) {
+        function_ ^= field_.Initializer();
         visitor_->Visit(function_);
       }
     }
@@ -115,6 +115,7 @@
   }
 }
 
+#if !defined(DART_PRECOMPILED_RUNTIME)
 void ProgramVisitor::BindStaticCalls() {
 #if !defined(TARGET_ARCH_DBC)
   if (FLAG_precompiled_mode) {
@@ -308,6 +309,7 @@
     explicit DedupPcDescriptorsVisitor(Zone* zone)
         : zone_(zone),
           canonical_pc_descriptors_(),
+          bytecode_(Bytecode::Handle(zone)),
           code_(Code::Handle(zone)),
           pc_descriptor_(PcDescriptors::Handle(zone)) {}
 
@@ -317,6 +319,14 @@
     }
 
     void Visit(const Function& function) {
+      bytecode_ = function.bytecode();
+      if (!bytecode_.IsNull()) {
+        pc_descriptor_ = bytecode_.pc_descriptors();
+        if (!pc_descriptor_.IsNull()) {
+          pc_descriptor_ = DedupPcDescriptor(pc_descriptor_);
+          bytecode_.set_pc_descriptors(pc_descriptor_);
+        }
+      }
       if (!function.HasCode()) {
         return;
       }
@@ -341,6 +351,7 @@
    private:
     Zone* zone_;
     PcDescriptorsSet canonical_pc_descriptors_;
+    Bytecode& bytecode_;
     Code& code_;
     PcDescriptors& pc_descriptor_;
   };
@@ -380,7 +391,6 @@
 
 typedef DirectChainedHashMap<TypedDataKeyValueTrait> TypedDataSet;
 
-#if !defined(DART_PRECOMPILED_RUNTIME)
 void ProgramVisitor::DedupDeoptEntries() {
   class DedupDeoptEntriesVisitor : public FunctionVisitor {
    public:
@@ -437,7 +447,6 @@
   DedupDeoptEntriesVisitor visitor(Thread::Current()->zone());
   ProgramVisitor::VisitFunctions(&visitor);
 }
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 #if defined(DART_PRECOMPILER)
 void ProgramVisitor::DedupCatchEntryMovesMaps() {
@@ -876,8 +885,10 @@
   ProgramVisitor::VisitFunctions(&visitor);
 #endif  // defined(DART_PRECOMPILER)
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 void ProgramVisitor::Dedup() {
+#if !defined(DART_PRECOMPILED_RUNTIME)
   Thread* thread = Thread::Current();
   StackZone stack_zone(thread);
   HANDLESCOPE(thread);
@@ -901,6 +912,7 @@
     DedupInstructions();
   }
 #endif
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 }
 
 }  // namespace dart
diff --git a/runtime/vm/program_visitor.h b/runtime/vm/program_visitor.h
index 5583cc3..3ba3539 100644
--- a/runtime/vm/program_visitor.h
+++ b/runtime/vm/program_visitor.h
@@ -30,11 +30,12 @@
   static void Dedup();
 
  private:
+#if !defined(DART_PRECOMPILED_RUNTIME)
   static void BindStaticCalls();
   static void ShareMegamorphicBuckets();
   static void DedupStackMaps();
   static void DedupPcDescriptors();
-  NOT_IN_PRECOMPILED(static void DedupDeoptEntries());
+  static void DedupDeoptEntries();
 #if defined(DART_PRECOMPILER)
   static void DedupCatchEntryMovesMaps();
 #endif
@@ -42,6 +43,7 @@
   static void DedupLists();
   static void DedupInstructions();
   static void DedupInstructionsWithSameMetadata();
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
 }  // namespace dart
diff --git a/runtime/vm/raw_object.cc b/runtime/vm/raw_object.cc
index cce58b2..7735f4d 100644
--- a/runtime/vm/raw_object.cc
+++ b/runtime/vm/raw_object.cc
@@ -42,7 +42,7 @@
       FATAL1("New object has kOldAndNotMarkedBit: %x\n", tags);
     }
     if (OldAndNotRememberedBit::decode(tags)) {
-      FATAL1("Mew object has kOldAndNotRememberedBit: %x\n", tags);
+      FATAL1("New object has kOldAndNotRememberedBit: %x\n", tags);
     }
   } else {
     if (NewBit::decode(tags)) {
@@ -61,16 +61,20 @@
     // Null class not yet initialized; skip.
     return;
   }
-  intptr_t size = SizeTag::decode(tags);
-  if (size != 0 && size != SizeFromClass()) {
-    FATAL1("Inconsistent class size encountered %" Pd "\n", size);
+  intptr_t size_from_tags = SizeTag::decode(tags);
+  intptr_t size_from_class = HeapSizeFromClass();
+  if ((size_from_tags != 0) && (size_from_tags != size_from_class)) {
+    FATAL3(
+        "Inconsistent size encountered "
+        "cid: %" Pd ", size_from_tags: %" Pd ", size_from_class: %" Pd "\n",
+        class_id, size_from_tags, size_from_class);
   }
 }
 
 // Can't look at the class object because it can be called during
 // compaction when the class objects are moving. Can use the class
 // id in the header and the sizes in the Class Table.
-intptr_t RawObject::SizeFromClass() const {
+intptr_t RawObject::HeapSizeFromClass() const {
   // Only reasonable to be called on heap objects.
   ASSERT(IsHeapObject());
 
@@ -143,6 +147,9 @@
         break;
       }
 #undef SIZE_FROM_CLASS
+    case kFfiPointerCid:
+      instance_size = Pointer::InstanceSize();
+      break;
     case kTypeArgumentsCid: {
       const RawTypeArguments* raw_array =
           reinterpret_cast<const RawTypeArguments*>(this);
@@ -187,13 +194,13 @@
     case kFreeListElement: {
       uword addr = RawObject::ToAddr(this);
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
-      instance_size = element->Size();
+      instance_size = element->HeapSize();
       break;
     }
     case kForwardingCorpse: {
       uword addr = RawObject::ToAddr(this);
       ForwardingCorpse* element = reinterpret_cast<ForwardingCorpse*>(addr);
-      instance_size = element->Size();
+      instance_size = element->HeapSize();
       break;
     }
     default: {
@@ -278,20 +285,30 @@
       break;
     }
 #undef RAW_VISITPOINTERS
+    case kFfiPointerCid: {
+      RawPointer* raw_obj = reinterpret_cast<RawPointer*>(this);
+      size = RawPointer::VisitPointerPointers(raw_obj, visitor);
+      break;
+    }
+    case kFfiDynamicLibraryCid: {
+      RawDynamicLibrary* raw_obj = reinterpret_cast<RawDynamicLibrary*>(this);
+      size = RawDynamicLibrary::VisitDynamicLibraryPointers(raw_obj, visitor);
+      break;
+    }
     case kFreeListElement: {
       uword addr = RawObject::ToAddr(this);
       FreeListElement* element = reinterpret_cast<FreeListElement*>(addr);
-      size = element->Size();
+      size = element->HeapSize();
       break;
     }
     case kForwardingCorpse: {
       uword addr = RawObject::ToAddr(this);
       ForwardingCorpse* forwarder = reinterpret_cast<ForwardingCorpse*>(addr);
-      size = forwarder->Size();
+      size = forwarder->HeapSize();
       break;
     }
     case kNullCid:
-      size = Size();
+      size = HeapSize();
       break;
     default:
       OS::PrintErr("Class Id: %" Pd "\n", class_id);
@@ -301,13 +318,13 @@
 
 #if defined(DEBUG)
   ASSERT(size != 0);
-  const intptr_t expected_size = Size();
+  const intptr_t expected_size = HeapSize();
 
-  // In general we expect that visitors return exactly the same size that Size
-  // would compute. However in case of Arrays we might have a discrepancy when
-  // concurrently visiting an array that is being shrunk with
+  // In general we expect that visitors return exactly the same size that
+  // HeapSize would compute. However in case of Arrays we might have a
+  // discrepancy when concurrently visiting an array that is being shrunk with
   // Array::MakeFixedLength: the visitor might have visited the full array while
-  // here we are observing a smaller Size().
+  // here we are observing a smaller HeapSize().
   ASSERT(size == expected_size ||
          (class_id == kArrayCid && size > expected_size));
   return size;  // Prefer larger size.
@@ -391,6 +408,7 @@
 REGULAR_VISITOR(ClosureData)
 REGULAR_VISITOR(SignatureData)
 REGULAR_VISITOR(RedirectionData)
+REGULAR_VISITOR(FfiTrampolineData)
 REGULAR_VISITOR(Field)
 REGULAR_VISITOR(Script)
 REGULAR_VISITOR(Library)
@@ -435,6 +453,8 @@
 NULL_VISITOR(Bool)
 NULL_VISITOR(Capability)
 NULL_VISITOR(SendPort)
+REGULAR_VISITOR(Pointer)
+NULL_VISITOR(DynamicLibrary)
 VARIABLE_NULL_VISITOR(Instructions, Instructions::Size(raw_obj))
 VARIABLE_NULL_VISITOR(PcDescriptors, raw_obj->ptr()->length_)
 VARIABLE_NULL_VISITOR(CodeSourceMap, raw_obj->ptr()->length_)
@@ -556,9 +576,8 @@
 bool RawBytecode::ContainsPC(RawObject* raw_obj, uword pc) {
   if (raw_obj->IsBytecode()) {
     RawBytecode* raw_bytecode = static_cast<RawBytecode*>(raw_obj);
-    RawExternalTypedData* bytes = raw_bytecode->ptr()->instructions_;
-    uword start = reinterpret_cast<uword>(bytes->ptr()->data_);
-    uword size = Smi::Value(bytes->ptr()->length_);
+    uword start = raw_bytecode->ptr()->instructions_;
+    uword size = raw_bytecode->ptr()->instructions_size_;
     return (pc - start) < size;
   }
   return false;
diff --git a/runtime/vm/raw_object.h b/runtime/vm/raw_object.h
index 2cea309..3fecf1c 100644
--- a/runtime/vm/raw_object.h
+++ b/runtime/vm/raw_object.h
@@ -344,6 +344,11 @@
   CLASS_LIST_TYPED_DATA(DEFINE_IS_CID)
 #undef DEFINE_IS_CID
 
+#define DEFINE_IS_CID(clazz)                                                   \
+  bool IsFfi##clazz() const { return ((GetClassId() == kFfi##clazz##Cid)); }
+  CLASS_LIST_FFI(DEFINE_IS_CID)
+#undef DEFINE_IS_CID
+
   bool IsStringInstance() const { return IsStringClassId(GetClassId()); }
   bool IsRawNull() const { return GetClassId() == kNullCid; }
   bool IsDartInstance() const {
@@ -363,17 +368,18 @@
     return IsHeapObject() ? GetClassId() : static_cast<intptr_t>(kSmiCid);
   }
 
-  intptr_t Size() const {
+  intptr_t HeapSize() const {
+    ASSERT(IsHeapObject());
     uint32_t tags = ptr()->tags_;
     intptr_t result = SizeTag::decode(tags);
     if (result != 0) {
 #if defined(DEBUG)
       // TODO(22501) Array::MakeFixedLength has a race with this code: we might
       // have loaded tags field and then MakeFixedLength could have updated it
-      // leading to inconsistency between SizeFromClass() and
+      // leading to inconsistency between HeapSizeFromClass() and
       // SizeTag::decode(tags). We are working around it by reloading tags_ and
       // recomputing size from tags.
-      const intptr_t size_from_class = SizeFromClass();
+      const intptr_t size_from_class = HeapSizeFromClass();
       if ((result > size_from_class) && (GetClassId() == kArrayCid) &&
           (ptr()->tags_ != tags)) {
         result = SizeTag::decode(ptr()->tags_);
@@ -382,13 +388,13 @@
 #endif
       return result;
     }
-    result = SizeFromClass();
+    result = HeapSizeFromClass();
     ASSERT(result > SizeTag::kMaxSizeTag);
     return result;
   }
 
   bool Contains(uword addr) const {
-    intptr_t this_size = Size();
+    intptr_t this_size = HeapSize();
     uword this_addr = RawObject::ToAddr(this);
     return (addr >= this_addr) && (addr < (this_addr + this_size));
   }
@@ -407,7 +413,7 @@
     }
 
     // Calculate the first and last raw object pointer fields.
-    intptr_t instance_size = Size();
+    intptr_t instance_size = HeapSize();
     uword obj_addr = ToAddr(this);
     uword from = obj_addr + sizeof(RawObject);
     uword to = obj_addr + instance_size - kWordSize;
@@ -428,7 +434,7 @@
     }
 
     // Calculate the first and last raw object pointer fields.
-    intptr_t instance_size = Size();
+    intptr_t instance_size = HeapSize();
     uword obj_addr = ToAddr(this);
     uword from = obj_addr + sizeof(RawObject);
     uword to = obj_addr + instance_size - kWordSize;
@@ -470,6 +476,15 @@
   static bool IsTypedDataClassId(intptr_t index);
   static bool IsTypedDataViewClassId(intptr_t index);
   static bool IsExternalTypedDataClassId(intptr_t index);
+  static bool IsFfiNativeTypeTypeClassId(intptr_t index);
+  static bool IsFfiPointerClassId(intptr_t index);
+  static bool IsFfiTypeClassId(intptr_t index);
+  static bool IsFfiTypeIntClassId(intptr_t index);
+  static bool IsFfiTypeDoubleClassId(intptr_t index);
+  static bool IsFfiTypeVoidClassId(intptr_t index);
+  static bool IsFfiTypeNativeFunctionClassId(intptr_t index);
+  static bool IsFfiDynamicLibraryClassId(intptr_t index);
+  static bool IsFfiClassId(intptr_t index);
   static bool IsInternalVMdefinedClassId(intptr_t index);
   static bool IsVariableSizeClassId(intptr_t index);
   static bool IsImplicitFieldClassId(intptr_t index);
@@ -493,7 +508,7 @@
   intptr_t VisitPointersPredefined(ObjectPointerVisitor* visitor,
                                    intptr_t class_id);
 
-  intptr_t SizeFromClass() const;
+  intptr_t HeapSizeFromClass() const;
 
   intptr_t GetClassId() const {
     uint32_t tags = ptr()->tags_;
@@ -663,7 +678,9 @@
   friend class CidRewriteVisitor;
   friend class Closure;
   friend class Code;
+  friend class Pointer;
   friend class Double;
+  friend class DynamicLibrary;
   friend class ForwardPointersVisitor;  // StorePointer
   friend class FreeListElement;
   friend class Function;
@@ -854,6 +871,7 @@
     kDynamicInvocationForwarder,  // represents forwarder which performs type
                                   // checks for arguments of a dynamic
                                   // invocation.
+    kFfiTrampoline,
   };
 
   enum AsyncModifier {
@@ -1001,6 +1019,15 @@
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 };
 
+class RawFfiTrampolineData : public RawObject {
+ private:
+  RAW_HEAP_OBJECT_IMPLEMENTATION(FfiTrampolineData);
+
+  VISIT_FROM(RawObject*, signature_type_);
+  RawType* signature_type_;
+  VISIT_TO(RawObject*, signature_type_);
+};
+
 class RawField : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Field);
 
@@ -1013,15 +1040,13 @@
     RawInstance* static_value_;  // Value for static fields.
     RawSmi* offset_;             // Offset in words for instance fields.
   } value_;
-  union {
-    // When precompiling we need to save the static initializer function here
-    // so that code for it can be generated.
-    RawFunction* precompiled_;  // Static initializer function - precompiling.
-    // When generating script snapshots after running the application it is
-    // necessary to save the initial value of static fields so that we can
-    // restore the value back to the original initial value.
-    RawInstance* saved_value_;  // Saved initial value - static fields.
-  } initializer_;
+  RawFunction* initializer_;  // Static initializer function.
+  // When generating APPJIT snapshots after running the application it is
+  // necessary to save the initial value of static fields so that we can
+  // restore the value back to the original initial value.
+  NOT_IN_PRECOMPILED(
+      RawInstance*
+          saved_initial_value_);  // Saved initial value - static fields.
   RawSmi* guarded_list_length_;
   RawArray* dependent_code_;
   RawObject** to_snapshot(Snapshot::Kind kind) {
@@ -1161,7 +1186,6 @@
   classid_t index_;       // Library id number.
   uint16_t num_imports_;  // Number of entries in imports_.
   int8_t load_state_;     // Of type LibraryState.
-  bool corelib_imported_;
   bool is_dart_scheme_;
   bool debuggable_;          // True if debugger can stop in library.
   bool is_in_fullsnapshot_;  // True if library is in a full snapshot.
@@ -1314,16 +1338,19 @@
 class RawBytecode : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Bytecode);
 
+  uword instructions_;
+  intptr_t instructions_size_;
+
   VISIT_FROM(RawObject*, object_pool_);
   RawObjectPool* object_pool_;
-  RawExternalTypedData* instructions_;
   RawFunction* function_;
   RawExceptionHandlers* exception_handlers_;
   RawPcDescriptors* pc_descriptors_;
   VISIT_TO(RawObject*, pc_descriptors_);
   RawObject** to_snapshot(Snapshot::Kind kind) { return to(); }
 
-  intptr_t source_positions_binary_offset_;
+  int32_t instructions_binary_offset_;
+  int32_t source_positions_binary_offset_;
 
   static bool ContainsPC(RawObject* raw_obj, uword pc);
 
@@ -1673,8 +1700,8 @@
 class RawICData : public RawObject {
   RAW_HEAP_OBJECT_IMPLEMENTATION(ICData);
 
-  VISIT_FROM(RawObject*, ic_data_);
-  RawArray* ic_data_;          // Contains class-ids, target and count.
+  VISIT_FROM(RawObject*, entries_);
+  RawArray* entries_;          // Contains class-ids, target and count.
   RawString* target_name_;     // Name of target function.
   RawArray* args_descriptor_;  // Arguments descriptor.
   // Static type of the receiver. If it is set then we are performing
@@ -1833,7 +1860,7 @@
 };
 
 class RawAbstractType : public RawInstance {
- protected:
+ public:
   enum TypeState {
     kAllocated,                // Initial state.
     kBeingFinalized,           // In the process of being finalized.
@@ -1841,6 +1868,7 @@
     kFinalizedUninstantiated,  // Uninstantiated type ready for use.
   };
 
+ protected:
   uword type_test_stub_entry_point_;  // Accessed from generated code.
   RawCode* type_test_stub_;  // Must be the last field, since subclasses use it
                              // in their VISIT_FROM.
@@ -2211,6 +2239,24 @@
   friend class RawBytecode;
 };
 
+class RawPointer : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(Pointer);
+  VISIT_FROM(RawCompressed, type_arguments_)
+  RawTypeArguments* type_arguments_;
+  VISIT_TO(RawCompressed, type_arguments_)
+  uint8_t* c_memory_address_;
+
+  friend class Pointer;
+};
+
+class RawDynamicLibrary : public RawInstance {
+  RAW_HEAP_OBJECT_IMPLEMENTATION(DynamicLibrary);
+  VISIT_NOTHING();
+  void* handle_;
+
+  friend class DynamicLibrary;
+};
+
 // VM implementations of the basic types in the isolate.
 class RawCapability : public RawInstance {
   RAW_HEAP_OBJECT_IMPLEMENTATION(Capability);
@@ -2481,6 +2527,56 @@
           index <= kExternalTypedDataFloat64x2ArrayCid);
 }
 
+inline bool RawObject::IsFfiNativeTypeTypeClassId(intptr_t index) {
+  return index == kFfiNativeTypeCid;
+}
+
+inline bool RawObject::IsFfiTypeClassId(intptr_t index) {
+  // Make sure this is updated when new Ffi types are added.
+  COMPILE_ASSERT(kFfiNativeFunctionCid == kFfiPointerCid + 1 &&
+                 kFfiInt8Cid == kFfiPointerCid + 2 &&
+                 kFfiInt16Cid == kFfiPointerCid + 3 &&
+                 kFfiInt32Cid == kFfiPointerCid + 4 &&
+                 kFfiInt64Cid == kFfiPointerCid + 5 &&
+                 kFfiUint8Cid == kFfiPointerCid + 6 &&
+                 kFfiUint16Cid == kFfiPointerCid + 7 &&
+                 kFfiUint32Cid == kFfiPointerCid + 8 &&
+                 kFfiUint64Cid == kFfiPointerCid + 9 &&
+                 kFfiIntPtrCid == kFfiPointerCid + 10 &&
+                 kFfiFloatCid == kFfiPointerCid + 11 &&
+                 kFfiDoubleCid == kFfiPointerCid + 12 &&
+                 kFfiVoidCid == kFfiPointerCid + 13);
+  return (index >= kFfiPointerCid && index <= kFfiVoidCid);
+}
+
+inline bool RawObject::IsFfiTypeIntClassId(intptr_t index) {
+  return (index >= kFfiInt8Cid && index <= kFfiIntPtrCid);
+}
+
+inline bool RawObject::IsFfiTypeDoubleClassId(intptr_t index) {
+  return (index >= kFfiFloatCid && index <= kFfiDoubleCid);
+}
+
+inline bool RawObject::IsFfiPointerClassId(intptr_t index) {
+  return index == kFfiPointerCid;
+}
+
+inline bool RawObject::IsFfiTypeVoidClassId(intptr_t index) {
+  return index == kFfiVoidCid;
+}
+
+inline bool RawObject::IsFfiTypeNativeFunctionClassId(intptr_t index) {
+  return index == kFfiNativeFunctionCid;
+}
+
+inline bool RawObject::IsFfiClassId(intptr_t index) {
+  return (index >= kFfiPointerCid && index <= kFfiVoidCid);
+}
+
+inline bool RawObject::IsFfiDynamicLibraryClassId(intptr_t index) {
+  return index == kFfiDynamicLibraryCid;
+}
+
 inline bool RawObject::IsInternalVMdefinedClassId(intptr_t index) {
   return ((index < kNumPredefinedCids) &&
           !RawObject::IsImplicitFieldClassId(index));
diff --git a/runtime/vm/raw_object_fields.cc b/runtime/vm/raw_object_fields.cc
index e76edeb..7332edb 100644
--- a/runtime/vm/raw_object_fields.cc
+++ b/runtime/vm/raw_object_fields.cc
@@ -56,6 +56,7 @@
   F(Field, guarded_list_length_)                                               \
   F(Field, dependent_code_)                                                    \
   F(Field, type_test_cache_)                                                   \
+  F(Field, initializer_)                                                       \
   F(Script, url_)                                                              \
   F(Script, resolved_url_)                                                     \
   F(Script, compile_time_constants_)                                           \
@@ -113,7 +114,7 @@
   F(SingleTargetCache, target_)                                                \
   F(UnlinkedCall, target_name_)                                                \
   F(UnlinkedCall, args_descriptor_)                                            \
-  F(ICData, ic_data_)                                                          \
+  F(ICData, entries_)                                                          \
   F(ICData, target_name_)                                                      \
   F(ICData, args_descriptor_)                                                  \
   F(ICData, owner_)                                                            \
@@ -138,11 +139,14 @@
   F(TypeArguments, length_)                                                    \
   F(TypeArguments, hash_)                                                      \
   F(AbstractType, type_test_stub_)                                             \
+  F(Type, type_test_stub_)                                                     \
   F(Type, type_class_id_)                                                      \
   F(Type, arguments_)                                                          \
   F(Type, hash_)                                                               \
   F(Type, signature_)                                                          \
+  F(TypeRef, type_test_stub_)                                                  \
   F(TypeRef, type_)                                                            \
+  F(TypeParameter, type_test_stub_)                                            \
   F(TypeParameter, name_)                                                      \
   F(TypeParameter, hash_)                                                      \
   F(TypeParameter, bound_)                                                     \
@@ -182,7 +186,11 @@
   F(WeakProperty, key_)                                                        \
   F(WeakProperty, value_)                                                      \
   F(MirrorReference, referent_)                                                \
-  F(UserTag, label_)
+  F(UserTag, label_)                                                           \
+  F(Pointer, type_arguments_)                                                  \
+  F(Pointer, c_memory_address_)                                                \
+  F(DynamicLibrary, handle_)                                                   \
+  F(FfiTrampolineData, signature_type_)
 
 OffsetsTable::OffsetsTable(Zone* zone) : cached_offsets_(zone) {
   for (intptr_t i = 0; offsets_table[i].class_id != -1; ++i) {
diff --git a/runtime/vm/raw_object_snapshot.cc b/runtime/vm/raw_object_snapshot.cc
index 0424d5c..2222f8d 100644
--- a/runtime/vm/raw_object_snapshot.cc
+++ b/runtime/vm/raw_object_snapshot.cc
@@ -467,6 +467,22 @@
   UNREACHABLE();
 }
 
+RawFfiTrampolineData* FfiTrampolineData::ReadFrom(SnapshotReader* reader,
+                                                  intptr_t object_id,
+                                                  intptr_t tags,
+                                                  Snapshot::Kind kind,
+                                                  bool as_reference) {
+  UNREACHABLE();
+  return FfiTrampolineData::null();
+}
+
+void RawFfiTrampolineData::WriteTo(SnapshotWriter* writer,
+                                   intptr_t object_id,
+                                   Snapshot::Kind kind,
+                                   bool as_reference) {
+  UNREACHABLE();
+}
+
 RawFunction* Function::ReadFrom(SnapshotReader* reader,
                                 intptr_t object_id,
                                 intptr_t tags,
@@ -1967,6 +1983,38 @@
       IsolateMessageTypedDataFinalizer);
 }
 
+RawPointer* Pointer::ReadFrom(SnapshotReader* reader,
+                              intptr_t object_id,
+                              intptr_t tags,
+                              Snapshot::Kind kind,
+                              bool as_reference) {
+  FATAL("Snapshotting Pointers is not supported");
+  UNREACHABLE();
+}
+
+void RawPointer::WriteTo(SnapshotWriter* writer,
+                         intptr_t object_id,
+                         Snapshot::Kind kind,
+                         bool as_reference) {
+  FATAL("Snapshotting Pointers is not supported");
+}
+
+RawDynamicLibrary* DynamicLibrary::ReadFrom(SnapshotReader* reader,
+                                            intptr_t object_id,
+                                            intptr_t tags,
+                                            Snapshot::Kind kind,
+                                            bool as_reference) {
+  FATAL("Snapshotting DynamicLibraries is not supported");
+  UNREACHABLE();
+}
+
+void RawDynamicLibrary::WriteTo(SnapshotWriter* writer,
+                                intptr_t object_id,
+                                Snapshot::Kind kind,
+                                bool as_reference) {
+  FATAL("Snapshotting DynamicLibraries is not supported");
+}
+
 RawCapability* Capability::ReadFrom(SnapshotReader* reader,
                                     intptr_t object_id,
                                     intptr_t tags,
diff --git a/runtime/vm/regexp_interpreter.cc b/runtime/vm/regexp_interpreter.cc
index 8b960b0..c83f474 100644
--- a/runtime/vm/regexp_interpreter.cc
+++ b/runtime/vm/regexp_interpreter.cc
@@ -136,7 +136,7 @@
   intptr_t max_size() const { return kBacktrackStackSize; }
 
  private:
-  static const intptr_t kBacktrackStackSize = 10000;
+  static const intptr_t kBacktrackStackSize = 1 << 16;
 
   intptr_t* data_;
 
diff --git a/runtime/vm/runtime_entry.cc b/runtime/vm/runtime_entry.cc
index c6cee03..e707f06 100644
--- a/runtime/vm/runtime_entry.cc
+++ b/runtime/vm/runtime_entry.cc
@@ -195,6 +195,11 @@
   NullErrorHelper(zone, selector);
 }
 
+DEFINE_RUNTIME_ENTRY(ArgumentNullError, 0) {
+  const String& error = String::Handle(String::New("argument value is null"));
+  Exceptions::ThrowArgumentError(error);
+}
+
 DEFINE_RUNTIME_ENTRY(ArgumentError, 1) {
   const Instance& value = Instance::CheckedHandle(zone, arguments.ArgAt(0));
   Exceptions::ThrowArgumentError(value);
diff --git a/runtime/vm/runtime_entry.h b/runtime/vm/runtime_entry.h
index a5a9f60..85e9d7f2 100644
--- a/runtime/vm/runtime_entry.h
+++ b/runtime/vm/runtime_entry.h
@@ -34,11 +34,16 @@
                intptr_t argument_count,
                bool is_leaf,
                bool is_float)
-      : name_(name),
+      :
+#if !defined(DART_PRECOMPILED_RUNTIME)
+        compiler::RuntimeEntry(this, &CallInternal),
+#endif
+        name_(name),
         function_(function),
         argument_count_(argument_count),
         is_leaf_(is_leaf),
-        is_float_(is_float) {}
+        is_float_(is_float) {
+  }
 
   const char* name() const { return name_; }
   RuntimeFunction function() const { return function_; }
@@ -58,6 +63,11 @@
                                   RawObject** argv,
                                   Thread* thread);
 
+ protected:
+  NOT_IN_PRECOMPILED(static void CallInternal(const RuntimeEntry* runtime_entry,
+                                              compiler::Assembler* assembler,
+                                              intptr_t argument_count));
+
  private:
   const char* const name_;
   const RuntimeFunction function_;
diff --git a/runtime/vm/runtime_entry_arm.cc b/runtime/vm/runtime_entry_arm.cc
index 3ff5758..7f84226 100644
--- a/runtime/vm/runtime_entry_arm.cc
+++ b/runtime/vm/runtime_entry_arm.cc
@@ -42,10 +42,12 @@
 //   SP : points to the arguments and return value array.
 //   R9 : address of the runtime function to call.
 //   R4 : number of arguments to the call.
-void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
-  if (is_leaf()) {
-    ASSERT(argument_count == this->argument_count());
-    __ LoadFromOffset(kWord, TMP, THR, Thread::OffsetFromThread(this));
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                Assembler* assembler,
+                                intptr_t argument_count) {
+  if (runtime_entry->is_leaf()) {
+    ASSERT(argument_count == runtime_entry->argument_count());
+    __ LoadFromOffset(kWord, TMP, THR, Thread::OffsetFromThread(runtime_entry));
     __ str(TMP, Address(THR, Thread::vm_tag_offset()));
     __ blx(TMP);
     __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
@@ -55,7 +57,7 @@
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ LoadFromOffset(kWord, R9, THR, Thread::OffsetFromThread(this));
+    __ LoadFromOffset(kWord, R9, THR, Thread::OffsetFromThread(runtime_entry));
     __ LoadImmediate(R4, argument_count);
     __ BranchLinkToRuntime();
   }
diff --git a/runtime/vm/runtime_entry_arm64.cc b/runtime/vm/runtime_entry_arm64.cc
index a17870c..69f902e 100644
--- a/runtime/vm/runtime_entry_arm64.cc
+++ b/runtime/vm/runtime_entry_arm64.cc
@@ -42,9 +42,11 @@
 //   SP : points to the arguments and return value array.
 //   R5 : address of the runtime function to call.
 //   R4 : number of arguments to the call.
-void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
-  if (is_leaf()) {
-    ASSERT(argument_count == this->argument_count());
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                Assembler* assembler,
+                                intptr_t argument_count) {
+  if (runtime_entry->is_leaf()) {
+    ASSERT(argument_count == runtime_entry->argument_count());
     // Since we are entering C++ code, we must restore the C stack pointer from
     // the stack limit to an aligned value nearer to the top of the stack.
     // We cache the Dart stack pointer and the stack limit in callee-saved
@@ -60,7 +62,7 @@
     __ mov(R25, SP);
     __ ReserveAlignedFrameSpace(0);
     __ mov(CSP, SP);
-    __ ldr(TMP, Address(THR, Thread::OffsetFromThread(this)));
+    __ ldr(TMP, Address(THR, Thread::OffsetFromThread(runtime_entry)));
     __ str(TMP, Address(THR, Thread::vm_tag_offset()));
     __ blr(TMP);
     __ LoadImmediate(TMP, VMTag::kDartCompiledTagId);
@@ -72,7 +74,7 @@
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ ldr(R5, Address(THR, Thread::OffsetFromThread(this)));
+    __ ldr(R5, Address(THR, Thread::OffsetFromThread(runtime_entry)));
     __ LoadImmediate(R4, argument_count);
     __ BranchLinkToRuntime();
   }
diff --git a/runtime/vm/runtime_entry_dbc.cc b/runtime/vm/runtime_entry_dbc.cc
index 2735003..b375e8d 100644
--- a/runtime/vm/runtime_entry_dbc.cc
+++ b/runtime/vm/runtime_entry_dbc.cc
@@ -17,9 +17,13 @@
   return reinterpret_cast<uword>(function());
 }
 
-void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
+#if !defined(DART_PRECOMPILED_RUNTIME)
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                Assembler* assembler,
+                                intptr_t argument_count) {
   UNIMPLEMENTED();
 }
+#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 
 }  // namespace dart
 
diff --git a/runtime/vm/runtime_entry_ia32.cc b/runtime/vm/runtime_entry_ia32.cc
index 26f300e..425529c 100644
--- a/runtime/vm/runtime_entry_ia32.cc
+++ b/runtime/vm/runtime_entry_ia32.cc
@@ -27,17 +27,19 @@
 //   EDX : number of arguments to the call as Smi.
 // For leaf calls the caller is responsible to setup the arguments
 // and look for return values based on the C calling convention.
-void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
-  if (is_leaf()) {
-    ASSERT(argument_count == this->argument_count());
-    __ movl(EAX, Immediate(GetEntryPoint()));
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                Assembler* assembler,
+                                intptr_t argument_count) {
+  if (runtime_entry->is_leaf()) {
+    ASSERT(argument_count == runtime_entry->argument_count());
+    __ movl(EAX, Immediate(runtime_entry->GetEntryPoint()));
     __ movl(Assembler::VMTagAddress(), EAX);
     __ call(EAX);
     __ movl(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ movl(ECX, Immediate(GetEntryPoint()));
+    __ movl(ECX, Immediate(runtime_entry->GetEntryPoint()));
     __ movl(EDX, Immediate(argument_count));
     __ CallToRuntime();
   }
diff --git a/runtime/vm/runtime_entry_list.h b/runtime/vm/runtime_entry_list.h
index fa97c63..4833b04 100644
--- a/runtime/vm/runtime_entry_list.h
+++ b/runtime/vm/runtime_entry_list.h
@@ -41,6 +41,7 @@
   V(RangeError)                                                                \
   V(NullError)                                                                 \
   V(NullErrorWithSelector)                                                     \
+  V(ArgumentNullError)                                                         \
   V(ArgumentError)                                                             \
   V(ArgumentErrorUnboxedInt64)                                                 \
   V(IntegerDivisionByZeroException)                                            \
diff --git a/runtime/vm/runtime_entry_x64.cc b/runtime/vm/runtime_entry_x64.cc
index f84db6b..b21de64 100644
--- a/runtime/vm/runtime_entry_x64.cc
+++ b/runtime/vm/runtime_entry_x64.cc
@@ -24,11 +24,13 @@
 //   RSP : points to the arguments and return value array.
 //   RBX : address of the runtime function to call.
 //   R10 : number of arguments to the call.
-void RuntimeEntry::Call(Assembler* assembler, intptr_t argument_count) const {
-  if (is_leaf()) {
-    ASSERT(argument_count == this->argument_count());
+void RuntimeEntry::CallInternal(const RuntimeEntry* runtime_entry,
+                                Assembler* assembler,
+                                intptr_t argument_count) {
+  if (runtime_entry->is_leaf()) {
+    ASSERT(argument_count == runtime_entry->argument_count());
     COMPILE_ASSERT(CallingConventions::kVolatileCpuRegisters & (1 << RAX));
-    __ movq(RAX, Address(THR, Thread::OffsetFromThread(this)));
+    __ movq(RAX, Address(THR, Thread::OffsetFromThread(runtime_entry)));
     __ movq(Assembler::VMTagAddress(), RAX);
     __ CallCFunction(RAX);
     __ movq(Assembler::VMTagAddress(), Immediate(VMTag::kDartCompiledTagId));
@@ -37,7 +39,7 @@
   } else {
     // Argument count is not checked here, but in the runtime entry for a more
     // informative error message.
-    __ movq(RBX, Address(THR, Thread::OffsetFromThread(this)));
+    __ movq(RBX, Address(THR, Thread::OffsetFromThread(runtime_entry)));
     __ LoadImmediate(R10, Immediate(argument_count));
     __ CallToRuntime();
   }
diff --git a/runtime/vm/service.cc b/runtime/vm/service.cc
index 4de2442..93fa9c6 100644
--- a/runtime/vm/service.cc
+++ b/runtime/vm/service.cc
@@ -701,27 +701,25 @@
             return -1;
           }
           bool valid_enum = false;
+          const char* id_start = cp;
+          while (IsEnumChar(*cp)) {
+            cp++;
+          }
+          if (cp == id_start) {
+            // Empty identifier, something like this [,].
+            return -1;
+          }
+          intptr_t id_len = cp - id_start;
           if (enums_ != NULL) {
             for (intptr_t i = 0; enums_[i] != NULL; i++) {
               intptr_t len = strlen(enums_[i]);
-              if (strncmp(cp, enums_[i], len) == 0) {
+              if (len == id_len && strncmp(id_start, enums_[i], len) == 0) {
                 element_count++;
                 valid_enum = true;
-                cp += len;
                 element_allowed = false;  // we need a comma first.
                 break;
               }
             }
-          } else {
-            // Allow any identifiers
-            const char* id_start = cp;
-            while (IsEnumChar(*cp)) {
-              cp++;
-            }
-            if (cp == id_start) {
-              // Empty identifier, something like this [,].
-              return -1;
-            }
           }
           if (!valid_enum) {
             return -1;
@@ -4110,7 +4108,7 @@
       return false;
     }
     uword obj_begin = RawObject::ToAddr(obj);
-    uword obj_end = obj_begin + obj->Size();
+    uword obj_end = obj_begin + obj->HeapSize();
     return obj_begin <= addr_ && addr_ < obj_end;
   }
 
@@ -4754,6 +4752,13 @@
   }
   CLASS_LIST_TYPED_DATA(DEFINE_ADD_MAP_KEY)
 #undef DEFINE_ADD_MAP_KEY
+#define DEFINE_ADD_MAP_KEY(clazz)                                              \
+  {                                                                            \
+    JSONArray internals(&map, #clazz);                                         \
+    DEFINE_ADD_VALUE_F_CID(Ffi##clazz)                                         \
+  }
+  CLASS_LIST_FFI(DEFINE_ADD_MAP_KEY)
+#undef DEFINE_ADD_MAP_KEY
 #undef DEFINE_ADD_VALUE_F_CID
 #undef DEFINE_ADD_VALUE_F
 
diff --git a/runtime/vm/simulator_dbc.cc b/runtime/vm/simulator_dbc.cc
index 230a519..b059dae 100644
--- a/runtime/vm/simulator_dbc.cc
+++ b/runtime/vm/simulator_dbc.cc
@@ -847,7 +847,7 @@
 
   const intptr_t kCheckedArgs = 1;
   RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+  RawArray* cache = icdata->ptr()->entries_->ptr();
 
   const intptr_t type_args_len =
       SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
@@ -891,7 +891,7 @@
 
   const intptr_t kCheckedArgs = 2;
   RawObject** args = call_base;
-  RawArray* cache = icdata->ptr()->ic_data_->ptr();
+  RawArray* cache = icdata->ptr()->entries_->ptr();
 
   const intptr_t type_args_len =
       SimulatorHelpers::ArgDescTypeArgsLen(icdata->ptr()->args_descriptor_);
@@ -1067,7 +1067,7 @@
     ASSERT(SimulatorBytecode::IsCallOpcode(*pc));                              \
     const uint16_t kidx = SimulatorBytecode::DecodeD(*pc);                     \
     const RawICData* icdata = RAW_CAST(ICData, LOAD_CONSTANT(kidx));           \
-    RawObject** entries = icdata->ptr()->ic_data_->ptr()->data();              \
+    RawObject** entries = icdata->ptr()->entries_->ptr()->data();              \
     SimulatorHelpers::IncrementICUsageCount(entries, 0, 2);                    \
   } while (0);
 
@@ -1080,8 +1080,8 @@
     const intptr_t lhs = reinterpret_cast<intptr_t>(SP[-1]);                   \
     const intptr_t rhs = reinterpret_cast<intptr_t>(SP[-0]);                   \
     ResultT* slot = reinterpret_cast<ResultT*>(SP - 1);                        \
-    if (LIKELY(!thread->isolate()->single_step()) &&                           \
-        LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) {              \
+    if (NOT_IN_PRODUCT(LIKELY(!thread->isolate()->single_step()) &&)           \
+            LIKELY(AreBothSmis(lhs, rhs) && !Func(lhs, rhs, slot))) {          \
       SMI_FASTPATH_ICDATA_INC;                                                 \
       /* Fast path succeeded. Skip the generic call that follows. */           \
       pc++;                                                                    \
@@ -1464,11 +1464,13 @@
 
   {
     BYTECODE(DebugStep, A);
+#ifndef PRODUCT
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
     DISPATCH();
   }
 
@@ -1652,12 +1654,14 @@
   {
     BYTECODE(IndirectStaticCall, A_D);
 
+#ifndef PRODUCT
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     // Invoke target function.
     {
@@ -1665,7 +1669,7 @@
       // Look up the function in the ICData.
       RawObject* ic_data_obj = SP[0];
       RawICData* ic_data = RAW_CAST(ICData, ic_data_obj);
-      RawObject** data = ic_data->ptr()->ic_data_->ptr()->data();
+      RawObject** data = ic_data->ptr()->entries_->ptr()->data();
       SimulatorHelpers::IncrementICUsageCount(data, 0, 0);
       SP[0] = data[ICData::TargetIndexFor(ic_data->ptr()->state_bits_ & 0x3)];
       RawObject** call_base = SP - argc;
@@ -1690,12 +1694,14 @@
   {
     BYTECODE(InstanceCall1, A_D);
 
+#ifndef PRODUCT
     // Check if single stepping.
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     {
       const uint16_t argc = rA;
@@ -1716,11 +1722,14 @@
 
   {
     BYTECODE(InstanceCall2, A_D);
+
+#ifndef PRODUCT
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     {
       const uint16_t argc = rA;
@@ -3330,11 +3339,14 @@
 
   {
     BYTECODE(IfEqStrictNumTOS, 0);
+
+#ifndef PRODUCT
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     SP -= 2;
     if (!SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
@@ -3345,11 +3357,14 @@
 
   {
     BYTECODE(IfNeStrictNumTOS, 0);
+
+#ifndef PRODUCT
     if (thread->isolate()->single_step()) {
       Exit(thread, FP, SP + 1, pc);
       NativeArguments args(thread, 0, NULL, NULL);
       INVOKE_RUNTIME(DRT_SingleStepHandler, args);
     }
+#endif  // !PRODUCT
 
     SP -= 2;
     if (SimulatorHelpers::IsStrictEqualWithNumberCheck(SP[1], SP[2])) {
diff --git a/runtime/vm/snapshot.cc b/runtime/vm/snapshot.cc
index ea839f3..c3d7c8e 100644
--- a/runtime/vm/snapshot.cc
+++ b/runtime/vm/snapshot.cc
@@ -483,6 +483,10 @@
       break;
     }
 #undef SNAPSHOT_READ
+#define SNAPSHOT_READ(clazz) case kFfi##clazz##Cid:
+
+    CLASS_LIST_FFI(SNAPSHOT_READ) { UNREACHABLE(); }
+#undef SNAPSHOT_READ
     default:
       UNREACHABLE();
       break;
@@ -1175,6 +1179,10 @@
       return;
     }
 #undef SNAPSHOT_WRITE
+#define SNAPSHOT_WRITE(clazz) case kFfi##clazz##Cid:
+
+    CLASS_LIST_FFI(SNAPSHOT_WRITE) { UNREACHABLE(); }
+#undef SNAPSHOT_WRITE
     default:
       break;
   }
diff --git a/runtime/vm/snapshot.h b/runtime/vm/snapshot.h
index 1432259..736329c 100644
--- a/runtime/vm/snapshot.h
+++ b/runtime/vm/snapshot.h
@@ -48,6 +48,7 @@
 class RawContextScope;
 class RawDouble;
 class RawExceptionHandlers;
+class RawFfiTrampolineData;
 class RawField;
 class RawFloat32x4;
 class RawFloat64x2;
diff --git a/runtime/vm/stack_frame.cc b/runtime/vm/stack_frame.cc
index 900061b..0e98fc7 100644
--- a/runtime/vm/stack_frame.cc
+++ b/runtime/vm/stack_frame.cc
@@ -33,6 +33,7 @@
     /*.dart_fixed_frame_size = */ -1,
     /*.saved_caller_pp_from_fp = */ -1,
     /*.code_from_fp = */ -1,
+    /*.exit_link_slot_from_entry_fp = */ -1,
 };
 
 const FrameLayout default_frame_layout = {
@@ -43,6 +44,7 @@
     /*.dart_fixed_frame_size = */ kDartFrameFixedSize,
     /*.saved_caller_pp_from_fp = */ kSavedCallerPpSlotFromFp,
     /*.code_from_fp = */ kPcMarkerSlotFromFp,
+    /*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
 };
 const FrameLayout bare_instructions_frame_layout = {
     /*.first_object_from_pc =*/kFirstObjectSlotFromFp,  // No saved PP slot.
@@ -55,6 +57,7 @@
         2,                              // No saved CODE, PP slots.
     /*.saved_caller_pp_from_fp = */ 0,  // No saved PP slot.
     /*.code_from_fp = */ 0,             // No saved CODE
+    /*.exit_link_slot_from_entry_fp = */ kExitLinkSlotFromEntryFp,
 };
 
 namespace compiler {
diff --git a/runtime/vm/static_type_exactness_state.h b/runtime/vm/static_type_exactness_state.h
new file mode 100644
index 0000000..1660eba
--- /dev/null
+++ b/runtime/vm/static_type_exactness_state.h
@@ -0,0 +1,149 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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_STATIC_TYPE_EXACTNESS_STATE_H_
+#define RUNTIME_VM_STATIC_TYPE_EXACTNESS_STATE_H_
+
+#include "platform/allocation.h"
+
+// This header defines the list of VM implementation classes and their ids.
+//
+// Note: we assume that all builds of Dart VM use exactly the same class ids
+// for these classes.
+
+namespace dart {
+
+class Instance;
+class Type;
+
+// Representation of a state of runtime tracking of static type exactness for
+// a particular location in the program (e.g. exactness of type annotation
+// on a field).
+//
+// Given the static type G<T0, ..., Tn> we say that it is exact iff any
+// values that can be observed at this location has runtime type T such that
+// type arguments of T at G are exactly <T0, ..., Tn>.
+//
+// Currently we only support tracking for locations that are also known
+// to be monomorphic with respect to the actual class of the values it contains.
+//
+// Important: locations should never switch from tracked (kIsTriviallyExact,
+// kHasExactSuperType, kHasExactSuperClass, kNotExact) to not tracked
+// (kNotTracking) or the other way around because that would affect unoptimized
+// graphs generated by graph builder and skew deopt ids.
+class StaticTypeExactnessState final {
+ public:
+  // Values stored in the location with static type G<T0, ..., Tn> are all
+  // instances of C<T0, ..., Tn> and C<U0, ..., Un> at G has type parameters
+  // <U0, ..., Un>.
+  //
+  // For trivially exact types we can simply compare type argument
+  // vectors as pointers to check exactness. That's why we represent
+  // trivially exact locations as offset in words to the type arguments of
+  // class C. All other states are represented as non-positive values.
+  //
+  // Note: we are ignoring the type argument vector sharing optimization for
+  // now.
+  static inline StaticTypeExactnessState TriviallyExact(
+      intptr_t type_arguments_offset_in_bytes) {
+    ASSERT((type_arguments_offset_in_bytes > 0) &&
+           Utils::IsInt(8, type_arguments_offset_in_bytes));
+    return StaticTypeExactnessState(type_arguments_offset_in_bytes);
+  }
+
+  static inline bool CanRepresentAsTriviallyExact(
+      intptr_t type_arguments_offset_in_bytes) {
+    return Utils::IsInt(8, type_arguments_offset_in_bytes);
+  }
+
+  // Values stored in the location with static type G<T0, ..., Tn> are all
+  // instances of class C<...> and C<U0, ..., Un> at G has type
+  // parameters <T0, ..., Tn> for any <U0, ..., Un> - that is C<...> has a
+  // supertype G<T0, ..., Tn>.
+  //
+  // For such locations we can simply check if the value stored
+  // is an instance of an expected class and we don't have to look at
+  // type arguments carried by the instance.
+  //
+  // We distinguish situations where we know that G is a superclass of C from
+  // situations where G might be superinterface of C - because in the first
+  // type arguments of G give us constant prefix of type arguments of C.
+  static inline StaticTypeExactnessState HasExactSuperType() {
+    return StaticTypeExactnessState(kHasExactSuperType);
+  }
+
+  static inline StaticTypeExactnessState HasExactSuperClass() {
+    return StaticTypeExactnessState(kHasExactSuperClass);
+  }
+
+  // Values stored in the location don't fall under either kIsTriviallyExact
+  // or kHasExactSuperType categories.
+  //
+  // Note: that does not imply that static type annotation is not exact
+  // according to a broader definition, e.g. location might simply be
+  // polymorphic and store instances of multiple different types.
+  // However for simplicity we don't track such cases yet.
+  static inline StaticTypeExactnessState NotExact() {
+    return StaticTypeExactnessState(kNotExact);
+  }
+
+  // The location does not track exactness of its static type at runtime.
+  static inline StaticTypeExactnessState NotTracking() {
+    return StaticTypeExactnessState(kNotTracking);
+  }
+
+  static inline StaticTypeExactnessState Unitialized() {
+    return StaticTypeExactnessState(kUninitialized);
+  }
+
+  static StaticTypeExactnessState Compute(const Type& static_type,
+                                          const Instance& value,
+                                          bool print_trace = false);
+
+  bool IsTracking() const { return value_ != kNotTracking; }
+  bool IsUninitialized() const { return value_ == kUninitialized; }
+  bool IsHasExactSuperClass() const { return value_ == kHasExactSuperClass; }
+  bool IsHasExactSuperType() const { return value_ == kHasExactSuperType; }
+  bool IsTriviallyExact() const { return value_ > kUninitialized; }
+  bool NeedsFieldGuard() const { return value_ >= kUninitialized; }
+  bool IsExactOrUninitialized() const { return value_ > kNotExact; }
+  bool IsExact() const {
+    return IsTriviallyExact() || IsHasExactSuperType() ||
+           IsHasExactSuperClass();
+  }
+
+  const char* ToCString() const;
+
+  StaticTypeExactnessState CollapseSuperTypeExactness() const {
+    return IsHasExactSuperClass() ? HasExactSuperType() : *this;
+  }
+
+  static inline StaticTypeExactnessState Decode(int8_t value) {
+    return StaticTypeExactnessState(value);
+  }
+
+  int8_t Encode() const { return value_; }
+  int8_t GetTypeArgumentsOffsetInWords() const {
+    ASSERT(IsTriviallyExact());
+    return value_;
+  }
+
+  static constexpr int8_t kUninitialized = 0;
+
+ private:
+  static constexpr int8_t kNotTracking = -4;
+  static constexpr int8_t kNotExact = -3;
+  static constexpr int8_t kHasExactSuperType = -2;
+  static constexpr int8_t kHasExactSuperClass = -1;
+
+  explicit StaticTypeExactnessState(int8_t value) : value_(value) {}
+
+  int8_t value_;
+
+  DISALLOW_ALLOCATION();
+};
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_STATIC_TYPE_EXACTNESS_STATE_H_
diff --git a/runtime/vm/stub_code.cc b/runtime/vm/stub_code.cc
index 6e90207..9171436 100644
--- a/runtime/vm/stub_code.cc
+++ b/runtime/vm/stub_code.cc
@@ -47,8 +47,9 @@
 
 #define STUB_CODE_GENERATE(name)                                               \
   entries_[k##name##Index] = Code::ReadOnlyHandle();                           \
-  *entries_[k##name##Index] = Generate("_stub_" #name, &object_pool_builder,   \
-                                       StubCode::Generate##name##Stub);
+  *entries_[k##name##Index] =                                                  \
+      Generate("_stub_" #name, &object_pool_builder,                           \
+               compiler::StubCodeCompiler::Generate##name##Stub);
 
 #define STUB_CODE_SET_OBJECT_POOL(name)                                        \
   entries_[k##name##Index]->set_object_pool(object_pool.raw());
@@ -181,7 +182,7 @@
 
     Assembler assembler(wrapper);
     const char* name = cls.ToCString();
-    StubCode::GenerateAllocationStubForClass(&assembler, cls);
+    compiler::StubCodeCompiler::GenerateAllocationStubForClass(&assembler, cls);
 
     if (thread->IsMutatorThread()) {
       stub ^= Code::FinalizeCode(name, nullptr, &assembler, pool_attachment,
@@ -243,9 +244,20 @@
 #if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
 RawCode* StubCode::GetBuildMethodExtractorStub(ObjectPoolBuilder* pool) {
 #if !defined(DART_PRECOMPILED_RUNTIME)
+  auto thread = Thread::Current();
+  auto Z = thread->zone();
+  auto object_store = thread->isolate()->object_store();
+
+  const auto& closure_class =
+      Class::ZoneHandle(Z, object_store->closure_class());
+  const auto& closure_allocation_stub =
+      Code::ZoneHandle(Z, StubCode::GetAllocationStubForClass(closure_class));
+  const auto& context_allocation_stub = StubCode::AllocateContext();
+
   ObjectPoolBuilder object_pool_builder;
   Assembler assembler(pool != nullptr ? pool : &object_pool_builder);
-  StubCode::GenerateBuildMethodExtractorStub(&assembler);
+  compiler::StubCodeCompiler::GenerateBuildMethodExtractorStub(
+      &assembler, closure_allocation_stub, context_allocation_stub);
 
   const char* name = "BuildMethodExtractor";
   const Code& stub = Code::Handle(Code::FinalizeCode(
diff --git a/runtime/vm/stub_code.h b/runtime/vm/stub_code.h
index aa148e3..2593ca00 100644
--- a/runtime/vm/stub_code.h
+++ b/runtime/vm/stub_code.h
@@ -7,7 +7,10 @@
 
 #include "vm/allocation.h"
 #include "vm/compiler/assembler/assembler.h"
+#include "vm/compiler/runtime_api.h"
+#include "vm/compiler/stub_code_compiler.h"
 #include "vm/object.h"
+#include "vm/stub_code_list.h"
 
 namespace dart {
 
@@ -19,100 +22,6 @@
 class SnapshotReader;
 class SnapshotWriter;
 
-// List of stubs created in the VM isolate, these stubs are shared by different
-// isolates running in this dart process.
-#if !defined(TARGET_ARCH_DBC)
-#define VM_STUB_CODE_LIST(V)                                                   \
-  V(GetCStackPointer)                                                          \
-  V(JumpToFrame)                                                               \
-  V(RunExceptionHandler)                                                       \
-  V(DeoptForRewind)                                                            \
-  V(WriteBarrier)                                                              \
-  V(WriteBarrierWrappers)                                                      \
-  V(ArrayWriteBarrier)                                                         \
-  V(PrintStopMessage)                                                          \
-  V(AllocateArray)                                                             \
-  V(AllocateContext)                                                           \
-  V(CallToRuntime)                                                             \
-  V(LazyCompile)                                                               \
-  V(InterpretCall)                                                             \
-  V(CallBootstrapNative)                                                       \
-  V(CallNoScopeNative)                                                         \
-  V(CallAutoScopeNative)                                                       \
-  V(FixCallersTarget)                                                          \
-  V(CallStaticFunction)                                                        \
-  V(OptimizeFunction)                                                          \
-  V(InvokeDartCode)                                                            \
-  V(InvokeDartCodeFromBytecode)                                                \
-  V(DebugStepCheck)                                                            \
-  V(UnlinkedCall)                                                              \
-  V(MonomorphicMiss)                                                           \
-  V(SingleTargetCall)                                                          \
-  V(ICCallThroughFunction)                                                     \
-  V(ICCallThroughCode)                                                         \
-  V(MegamorphicCall)                                                           \
-  V(FixAllocationStubTarget)                                                   \
-  V(Deoptimize)                                                                \
-  V(DeoptimizeLazyFromReturn)                                                  \
-  V(DeoptimizeLazyFromThrow)                                                   \
-  V(UnoptimizedIdenticalWithNumberCheck)                                       \
-  V(OptimizedIdenticalWithNumberCheck)                                         \
-  V(ICCallBreakpoint)                                                          \
-  V(RuntimeCallBreakpoint)                                                     \
-  V(OneArgCheckInlineCache)                                                    \
-  V(TwoArgsCheckInlineCache)                                                   \
-  V(SmiAddInlineCache)                                                         \
-  V(SmiSubInlineCache)                                                         \
-  V(SmiEqualInlineCache)                                                       \
-  V(OneArgOptimizedCheckInlineCache)                                           \
-  V(TwoArgsOptimizedCheckInlineCache)                                          \
-  V(ZeroArgsUnoptimizedStaticCall)                                             \
-  V(OneArgUnoptimizedStaticCall)                                               \
-  V(TwoArgsUnoptimizedStaticCall)                                              \
-  V(Subtype1TestCache)                                                         \
-  V(Subtype2TestCache)                                                         \
-  V(Subtype4TestCache)                                                         \
-  V(Subtype6TestCache)                                                         \
-  V(DefaultTypeTest)                                                           \
-  V(TopTypeTypeTest)                                                           \
-  V(TypeRefTypeTest)                                                           \
-  V(UnreachableTypeTest)                                                       \
-  V(SlowTypeTest)                                                              \
-  V(LazySpecializeTypeTest)                                                    \
-  V(CallClosureNoSuchMethod)                                                   \
-  V(FrameAwaitingMaterialization)                                              \
-  V(AsynchronousGapMarker)                                                     \
-  V(NullErrorSharedWithFPURegs)                                                \
-  V(NullErrorSharedWithoutFPURegs)                                             \
-  V(StackOverflowSharedWithFPURegs)                                            \
-  V(StackOverflowSharedWithoutFPURegs)                                         \
-  V(OneArgCheckInlineCacheWithExactnessCheck)                                  \
-  V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)
-
-#else
-#define VM_STUB_CODE_LIST(V)                                                   \
-  V(LazyCompile)                                                               \
-  V(OptimizeFunction)                                                          \
-  V(CallClosureNoSuchMethod)                                                   \
-  V(RunExceptionHandler)                                                       \
-  V(DeoptForRewind)                                                            \
-  V(FixCallersTarget)                                                          \
-  V(Deoptimize)                                                                \
-  V(DeoptimizeLazyFromReturn)                                                  \
-  V(DeoptimizeLazyFromThrow)                                                   \
-  V(DefaultTypeTest)                                                           \
-  V(TopTypeTypeTest)                                                           \
-  V(TypeRefTypeTest)                                                           \
-  V(UnreachableTypeTest)                                                       \
-  V(SlowTypeTest)                                                              \
-  V(LazySpecializeTypeTest)                                                    \
-  V(FrameAwaitingMaterialization)                                              \
-  V(AsynchronousGapMarker)                                                     \
-  V(InvokeDartCodeFromBytecode)                                                \
-  V(InterpretCall)
-
-#endif  // !defined(TARGET_ARCH_DBC)
-
 // Is it permitted for the stubs above to refer to Object::null(), which is
 // allocated in the VM isolate and shared across all isolates.
 // However, in cases where a simple GC-safe placeholder is needed on the stack,
@@ -153,9 +62,15 @@
 
 #if !defined(TARGET_ARCH_DBC) && !defined(TARGET_ARCH_IA32)
   static RawCode* GetBuildMethodExtractorStub(ObjectPoolBuilder* pool);
-  static void GenerateBuildMethodExtractorStub(compiler::Assembler* assembler);
 #endif
 
+  // Generate the stub and finalize the generated code into the stub
+  // code executable area.
+  static RawCode* Generate(
+      const char* name,
+      ObjectPoolBuilder* object_pool_builder,
+      void (*GenerateStub)(compiler::Assembler* assembler));
+
   static const Code& UnoptimizedStaticCallEntry(intptr_t num_args_tested);
 
   static const intptr_t kNoInstantiator = 0;
@@ -172,8 +87,9 @@
 #if !defined(DART_PRECOMPILED_RUNTIME)
 #define GENERATE_STUB(name)                                                    \
   static RawCode* BuildIsolateSpecific##name##Stub(ObjectPoolBuilder* opw) {   \
-    return StubCode::Generate("_iso_stub_" #name, opw,                         \
-                              StubCode::Generate##name##Stub);                 \
+    return StubCode::Generate(                                                 \
+        "_iso_stub_" #name, opw,                                               \
+        compiler::StubCodeCompiler::Generate##name##Stub);                     \
   }
   VM_STUB_CODE_LIST(GENERATE_STUB);
 #undef GENERATE_STUB
@@ -190,68 +106,8 @@
   };
 
   static Code* entries_[kNumStubEntries];
-
-#if !defined(DART_PRECOMPILED_RUNTIME)
-#define STUB_CODE_GENERATE(name)                                               \
-  static void Generate##name##Stub(compiler::Assembler* assembler);
-  VM_STUB_CODE_LIST(STUB_CODE_GENERATE)
-#undef STUB_CODE_GENERATE
-
-  // Generate the stub and finalize the generated code into the stub
-  // code executable area.
-  static RawCode* Generate(
-      const char* name,
-      ObjectPoolBuilder* object_pool_builder,
-      void (*GenerateStub)(compiler::Assembler* assembler));
-
-  static void GenerateSharedStub(compiler::Assembler* assembler,
-                                 bool save_fpu_registers,
-                                 const RuntimeEntry* target,
-                                 intptr_t self_code_stub_offset_from_thread,
-                                 bool allow_return);
-
-  static void GenerateMegamorphicMissStub(compiler::Assembler* assembler);
-  static void GenerateAllocationStubForClass(compiler::Assembler* assembler,
-                                             const Class& cls);
-  static void GenerateNArgsCheckInlineCacheStub(
-      compiler::Assembler* assembler,
-      intptr_t num_args,
-      const RuntimeEntry& handle_ic_miss,
-      Token::Kind kind,
-      bool optimized = false,
-      bool exactness_check = false);
-  static void GenerateUsageCounterIncrement(compiler::Assembler* assembler,
-                                            Register temp_reg);
-  static void GenerateOptimizedUsageCounterIncrement(
-      compiler::Assembler* assembler);
-#endif  // !defined(DART_PRECOMPILED_RUNTIME)
 };
 
-enum DeoptStubKind { kLazyDeoptFromReturn, kLazyDeoptFromThrow, kEagerDeopt };
-
-// Invocation mode for TypeCheck runtime entry that describes
-// where we are calling it from.
-enum TypeCheckMode {
-  // TypeCheck is invoked from LazySpecializeTypeTest stub.
-  // It should replace stub on the type with a specialized version.
-  kTypeCheckFromLazySpecializeStub,
-
-  // TypeCheck is invoked from the SlowTypeTest stub.
-  // This means that cache can be lazily created (if needed)
-  // and dst_name can be fetched from the pool.
-  kTypeCheckFromSlowStub,
-
-  // TypeCheck is invoked from normal inline AssertAssignable.
-  // Both cache and dst_name must be already populated.
-  kTypeCheckFromInline
-};
-
-// Zap value used to indicate unused CODE_REG in deopt.
-static const uword kZapCodeReg = 0xf1f1f1f1;
-
-// Zap value used to indicate unused return address in deopt.
-static const uword kZapReturnAddress = 0xe1e1e1e1;
-
 }  // namespace dart
 
 #endif  // RUNTIME_VM_STUB_CODE_H_
diff --git a/runtime/vm/stub_code_dbc.cc b/runtime/vm/stub_code_dbc.cc
deleted file mode 100644
index fa35e41..0000000
--- a/runtime/vm/stub_code_dbc.cc
+++ /dev/null
@@ -1,133 +0,0 @@
-// Copyright (c) 2016, the Dart project authors.  Please see the AUTHORS file
-// for details. All rights reserved. Use of this source code is governed by a
-// BSD-style license that can be found in the LICENSE file.
-
-#include "vm/globals.h"
-#if defined(TARGET_ARCH_DBC)
-
-#include "vm/compiler/assembler/assembler.h"
-#include "vm/compiler/backend/flow_graph_compiler.h"
-#include "vm/compiler/jit/compiler.h"
-#include "vm/cpu.h"
-#include "vm/dart_entry.h"
-#include "vm/heap/heap.h"
-#include "vm/instructions.h"
-#include "vm/object_store.h"
-#include "vm/runtime_entry.h"
-#include "vm/stack_frame.h"
-#include "vm/stub_code.h"
-#include "vm/tags.h"
-
-#define __ assembler->
-
-namespace dart {
-
-DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects.");
-DEFINE_FLAG(bool,
-            use_slow_path,
-            false,
-            "Set to true for debugging & verifying the slow paths.");
-
-void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
-  __ Compile();
-}
-
-void StubCode::GenerateCallClosureNoSuchMethodStub(Assembler* assembler) {
-  __ NoSuchMethod();
-}
-
-// Not executed, but used as a stack marker when calling
-// DRT_OptimizeInvokedFunction.
-void StubCode::GenerateOptimizeFunctionStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// Not executed, but used as a sentinel in Simulator::JumpToFrame.
-void StubCode::GenerateRunExceptionHandlerStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateDeoptForRewindStub(Assembler* assembler) {
-  __ DeoptRewind();
-}
-
-// TODO(vegorov) Don't generate this stub.
-void StubCode::GenerateFixCallersTargetStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(vegorov) Don't generate these stubs.
-void StubCode::GenerateAllocationStubForClass(Assembler* assembler,
-                                              const Class& cls) {
-  __ Trap();
-}
-
-// TODO(vegorov) Don't generate this stub.
-void StubCode::GenerateMegamorphicMissStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// These deoptimization stubs are only used to populate stack frames
-// with something meaningful to make sure GC can scan the stack during
-// the last phase of deoptimization which materializes objects.
-void StubCode::GenerateDeoptimizeLazyFromReturnStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateDeoptimizeLazyFromThrowStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateDeoptimizeStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateDefaultTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateTopTypeTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateTypeRefTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateUnreachableTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateLazySpecializeTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-// TODO(kustermann): Don't generate this stub.
-void StubCode::GenerateSlowTypeTestStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateInterpretCallStub(Assembler* assembler) {
-  __ Trap();
-}
-
-void StubCode::GenerateInvokeDartCodeFromBytecodeStub(Assembler* assembler) {
-  __ Trap();
-}
-
-}  // namespace dart
-
-#endif  // defined TARGET_ARCH_DBC
diff --git a/runtime/vm/stub_code_list.h b/runtime/vm/stub_code_list.h
new file mode 100644
index 0000000..ce9d729
--- /dev/null
+++ b/runtime/vm/stub_code_list.h
@@ -0,0 +1,106 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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_STUB_CODE_LIST_H_
+#define RUNTIME_VM_STUB_CODE_LIST_H_
+
+namespace dart {
+
+// List of stubs created in the VM isolate, these stubs are shared by different
+// isolates running in this dart process.
+#if !defined(TARGET_ARCH_DBC)
+#define VM_STUB_CODE_LIST(V)                                                   \
+  V(GetCStackPointer)                                                          \
+  V(JumpToFrame)                                                               \
+  V(RunExceptionHandler)                                                       \
+  V(DeoptForRewind)                                                            \
+  V(WriteBarrier)                                                              \
+  V(WriteBarrierWrappers)                                                      \
+  V(ArrayWriteBarrier)                                                         \
+  V(PrintStopMessage)                                                          \
+  V(AllocateArray)                                                             \
+  V(AllocateContext)                                                           \
+  V(CallToRuntime)                                                             \
+  V(LazyCompile)                                                               \
+  V(InterpretCall)                                                             \
+  V(CallBootstrapNative)                                                       \
+  V(CallNoScopeNative)                                                         \
+  V(CallAutoScopeNative)                                                       \
+  V(FixCallersTarget)                                                          \
+  V(CallStaticFunction)                                                        \
+  V(OptimizeFunction)                                                          \
+  V(InvokeDartCode)                                                            \
+  V(InvokeDartCodeFromBytecode)                                                \
+  V(DebugStepCheck)                                                            \
+  V(UnlinkedCall)                                                              \
+  V(MonomorphicMiss)                                                           \
+  V(SingleTargetCall)                                                          \
+  V(ICCallThroughFunction)                                                     \
+  V(ICCallThroughCode)                                                         \
+  V(MegamorphicCall)                                                           \
+  V(FixAllocationStubTarget)                                                   \
+  V(Deoptimize)                                                                \
+  V(DeoptimizeLazyFromReturn)                                                  \
+  V(DeoptimizeLazyFromThrow)                                                   \
+  V(UnoptimizedIdenticalWithNumberCheck)                                       \
+  V(OptimizedIdenticalWithNumberCheck)                                         \
+  V(ICCallBreakpoint)                                                          \
+  V(RuntimeCallBreakpoint)                                                     \
+  V(OneArgCheckInlineCache)                                                    \
+  V(TwoArgsCheckInlineCache)                                                   \
+  V(SmiAddInlineCache)                                                         \
+  V(SmiSubInlineCache)                                                         \
+  V(SmiEqualInlineCache)                                                       \
+  V(OneArgOptimizedCheckInlineCache)                                           \
+  V(TwoArgsOptimizedCheckInlineCache)                                          \
+  V(ZeroArgsUnoptimizedStaticCall)                                             \
+  V(OneArgUnoptimizedStaticCall)                                               \
+  V(TwoArgsUnoptimizedStaticCall)                                              \
+  V(Subtype1TestCache)                                                         \
+  V(Subtype2TestCache)                                                         \
+  V(Subtype4TestCache)                                                         \
+  V(Subtype6TestCache)                                                         \
+  V(DefaultTypeTest)                                                           \
+  V(TopTypeTypeTest)                                                           \
+  V(TypeRefTypeTest)                                                           \
+  V(UnreachableTypeTest)                                                       \
+  V(SlowTypeTest)                                                              \
+  V(LazySpecializeTypeTest)                                                    \
+  V(CallClosureNoSuchMethod)                                                   \
+  V(FrameAwaitingMaterialization)                                              \
+  V(AsynchronousGapMarker)                                                     \
+  V(NullErrorSharedWithFPURegs)                                                \
+  V(NullErrorSharedWithoutFPURegs)                                             \
+  V(StackOverflowSharedWithFPURegs)                                            \
+  V(StackOverflowSharedWithoutFPURegs)                                         \
+  V(OneArgCheckInlineCacheWithExactnessCheck)                                  \
+  V(OneArgOptimizedCheckInlineCacheWithExactnessCheck)
+
+#else
+#define VM_STUB_CODE_LIST(V)                                                   \
+  V(LazyCompile)                                                               \
+  V(OptimizeFunction)                                                          \
+  V(CallClosureNoSuchMethod)                                                   \
+  V(RunExceptionHandler)                                                       \
+  V(DeoptForRewind)                                                            \
+  V(FixCallersTarget)                                                          \
+  V(Deoptimize)                                                                \
+  V(DeoptimizeLazyFromReturn)                                                  \
+  V(DeoptimizeLazyFromThrow)                                                   \
+  V(DefaultTypeTest)                                                           \
+  V(TopTypeTypeTest)                                                           \
+  V(TypeRefTypeTest)                                                           \
+  V(UnreachableTypeTest)                                                       \
+  V(SlowTypeTest)                                                              \
+  V(LazySpecializeTypeTest)                                                    \
+  V(FrameAwaitingMaterialization)                                              \
+  V(AsynchronousGapMarker)                                                     \
+  V(InvokeDartCodeFromBytecode)                                                \
+  V(InterpretCall)
+
+#endif  // !defined(TARGET_ARCH_DBC)
+
+}  // namespace dart
+
+#endif  // RUNTIME_VM_STUB_CODE_LIST_H_
diff --git a/runtime/vm/symbols.cc b/runtime/vm/symbols.cc
index 741239a..b10f4e8 100644
--- a/runtime/vm/symbols.cc
+++ b/runtime/vm/symbols.cc
@@ -12,6 +12,7 @@
 #include "vm/raw_object.h"
 #include "vm/reusable_handles.h"
 #include "vm/snapshot_ids.h"
+#include "vm/type_table.h"
 #include "vm/unicode.h"
 #include "vm/visitor.h"
 
@@ -344,51 +345,104 @@
   return unified_table.Release().raw();
 }
 
-void Symbols::Compact(Isolate* isolate) {
-  ASSERT(isolate != Dart::vm_isolate());
-  Zone* zone = Thread::Current()->zone();
+void Symbols::Compact() {
+  Thread* thread = Thread::Current();
+  ASSERT(thread->isolate() != Dart::vm_isolate());
+  HANDLESCOPE(thread);
+  Zone* zone = thread->zone();
+  ObjectStore* object_store = thread->isolate()->object_store();
 
-  // 1. Drop the symbol table and do a full garbage collection.
-  isolate->object_store()->set_symbol_table(Object::empty_array());
-  isolate->heap()->CollectAllGarbage();
+  // 1. Drop the tables and do a full garbage collection.
+  object_store->set_symbol_table(Object::empty_array());
+  object_store->set_canonical_types(Object::empty_array());
+  object_store->set_canonical_type_arguments(Object::empty_array());
+  thread->heap()->CollectAllGarbage();
 
-  // 2. Walk the heap to find surviving symbols.
+  // 2. Walk the heap to find surviving canonical objects.
   GrowableArray<String*> symbols;
+  GrowableArray<class Type*> types;
+  GrowableArray<class TypeArguments*> type_args;
   class SymbolCollector : public ObjectVisitor {
    public:
-    SymbolCollector(Thread* thread, GrowableArray<String*>* symbols)
-        : symbols_(symbols), zone_(thread->zone()) {}
+    SymbolCollector(Thread* thread,
+                    GrowableArray<String*>* symbols,
+                    GrowableArray<class Type*>* types,
+                    GrowableArray<class TypeArguments*>* type_args)
+        : symbols_(symbols),
+          types_(types),
+          type_args_(type_args),
+          zone_(thread->zone()) {}
 
     void VisitObject(RawObject* obj) {
-      if (obj->IsCanonical() && obj->IsStringInstance()) {
-        symbols_->Add(&String::ZoneHandle(zone_, String::RawCast(obj)));
+      if (obj->IsCanonical()) {
+        if (obj->IsStringInstance()) {
+          symbols_->Add(&String::Handle(zone_, String::RawCast(obj)));
+        } else if (obj->IsType()) {
+          types_->Add(&Type::Handle(zone_, Type::RawCast(obj)));
+        } else if (obj->IsTypeArguments()) {
+          type_args_->Add(
+              &TypeArguments::Handle(zone_, TypeArguments::RawCast(obj)));
+        }
       }
     }
 
    private:
     GrowableArray<String*>* symbols_;
+    GrowableArray<class Type*>* types_;
+    GrowableArray<class TypeArguments*>* type_args_;
     Zone* zone_;
   };
 
   {
-    Thread* thread = Thread::Current();
     HeapIterationScope iteration(thread);
-    SymbolCollector visitor(thread, &symbols);
+    SymbolCollector visitor(thread, &symbols, &types, &type_args);
     iteration.IterateObjects(&visitor);
   }
 
-  // 3. Build a new table from the surviving symbols.
-  Array& array = Array::Handle(
-      zone, HashTables::New<SymbolTable>(symbols.length() * 4 / 3, Heap::kOld));
-  SymbolTable table(zone, array.raw());
-  for (intptr_t i = 0; i < symbols.length(); i++) {
-    String& symbol = *symbols[i];
-    ASSERT(symbol.IsString());
-    ASSERT(symbol.IsCanonical());
-    bool present = table.Insert(symbol);
-    ASSERT(!present);
+  // 3. Build new tables from the surviving canonical objects.
+  {
+    Array& array = Array::Handle(
+        zone,
+        HashTables::New<SymbolTable>(symbols.length() * 4 / 3, Heap::kOld));
+    SymbolTable table(zone, array.raw());
+    for (intptr_t i = 0; i < symbols.length(); i++) {
+      String& symbol = *symbols[i];
+      ASSERT(symbol.IsString());
+      ASSERT(symbol.IsCanonical());
+      bool present = table.Insert(symbol);
+      ASSERT(!present);
+    }
+    object_store->set_symbol_table(table.Release());
   }
-  isolate->object_store()->set_symbol_table(table.Release());
+
+  {
+    Array& array = Array::Handle(zone, HashTables::New<CanonicalTypeSet>(
+                                           types.length() * 4 / 3, Heap::kOld));
+    CanonicalTypeSet table(zone, array.raw());
+    for (intptr_t i = 0; i < types.length(); i++) {
+      class Type& type = *types[i];
+      ASSERT(type.IsType());
+      ASSERT(type.IsCanonical());
+      bool present = table.Insert(type);
+      ASSERT(!present);
+    }
+    object_store->set_canonical_types(table.Release());
+  }
+
+  {
+    Array& array =
+        Array::Handle(zone, HashTables::New<CanonicalTypeArgumentsSet>(
+                                type_args.length() * 4 / 3, Heap::kOld));
+    CanonicalTypeArgumentsSet table(zone, array.raw());
+    for (intptr_t i = 0; i < type_args.length(); i++) {
+      class TypeArguments& type_arg = *type_args[i];
+      ASSERT(type_arg.IsTypeArguments());
+      ASSERT(type_arg.IsCanonical());
+      bool present = table.Insert(type_arg);
+      ASSERT(!present);
+    }
+    object_store->set_canonical_type_arguments(table.Release());
+  }
 }
 
 void Symbols::GetStats(Isolate* isolate, intptr_t* size, intptr_t* capacity) {
diff --git a/runtime/vm/symbols.h b/runtime/vm/symbols.h
index f057703..68c0371 100644
--- a/runtime/vm/symbols.h
+++ b/runtime/vm/symbols.h
@@ -179,6 +179,7 @@
   V(ClosureData, "ClosureData")                                                \
   V(SignatureData, "SignatureData")                                            \
   V(RedirectionData, "RedirectionData")                                        \
+  V(FfiTrampolineData, "FfiTrampolineData")                                    \
   V(Field, "Field")                                                            \
   V(Script, "Script")                                                          \
   V(LibraryClass, "Library")                                                   \
@@ -373,6 +374,8 @@
   V(DartCore, "dart:core")                                                     \
   V(DartCollection, "dart:collection")                                         \
   V(DartDeveloper, "dart:developer")                                           \
+  V(DartFfi, "dart:ffi")                                                       \
+  V(DartFfiLibName, "ffi")                                                     \
   V(DartInternal, "dart:_internal")                                            \
   V(DartIsolate, "dart:isolate")                                               \
   V(DartMirrors, "dart:mirrors")                                               \
@@ -441,6 +444,7 @@
   V(_ensureScheduleImmediate, "_ensureScheduleImmediate")                      \
   V(DartLibrary, "dart.library.")                                              \
   V(DartLibraryMirrors, "dart.library.mirrors")                                \
+  V(DartLibraryFfi, "dart.library.ffi")                                        \
   V(_name, "_name")                                                            \
   V(name, "name")                                                              \
   V(options, "options")                                                        \
@@ -460,7 +464,23 @@
   V(Get, "get")                                                                \
   V(Set, "set")                                                                \
   V(vm_trace_entrypoints, "vm:testing.unsafe.trace-entrypoints-fn")            \
-  V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation")
+  V(BoundsCheckForPartialInstantiation, "_boundsCheckForPartialInstantiation") \
+  V(FfiPointer, "Pointer")                                                     \
+  V(FfiNativeFunction, "NativeFunction")                                       \
+  V(FfiInt8, "Int8")                                                           \
+  V(FfiInt16, "Int16")                                                         \
+  V(FfiInt32, "Int32")                                                         \
+  V(FfiInt64, "Int64")                                                         \
+  V(FfiUint8, "Uint8")                                                         \
+  V(FfiUint16, "Uint16")                                                       \
+  V(FfiUint32, "Uint32")                                                       \
+  V(FfiUint64, "Uint64")                                                       \
+  V(FfiIntPtr, "IntPtr")                                                       \
+  V(FfiFloat, "Float")                                                         \
+  V(FfiDouble, "Double")                                                       \
+  V(FfiVoid, "Void")                                                           \
+  V(FfiNativeType, "NativeType")                                               \
+  V(FfiDynamicLibrary, "DynamicLibrary")
 
 // Contains a list of frequently used strings in a canonicalized form. This
 // list is kept in the vm_isolate in order to share the copy across isolates
@@ -610,7 +630,7 @@
   static RawArray* UnifiedSymbolTable();
 
   // Treat the symbol table as weak and collect garbage.
-  static void Compact(Isolate* isolate);
+  static void Compact();
 
   // Creates a Symbol given a C string that is assumed to contain
   // UTF-8 encoded characters and '\0' is considered a termination character.
diff --git a/runtime/vm/thread_test.cc b/runtime/vm/thread_test.cc
index d71628e..7eeb900 100644
--- a/runtime/vm/thread_test.cc
+++ b/runtime/vm/thread_test.cc
@@ -420,7 +420,7 @@
         for (intptr_t cnt = 0; cnt < 0x1000; cnt++) {
           for (intptr_t i = 0; i < len_; i++) {
             ic_data ^= ic_datas_.AtAcquire(i);
-            arr = ic_data.ic_data();
+            arr = ic_data.entries();
             intptr_t num_checks = arr.Length() / 3;
             if (num_checks < 0 || num_checks > 5) {
               OS::PrintErr("Failure: %" Pd " checks!\n", num_checks);
diff --git a/runtime/vm/timeline.cc b/runtime/vm/timeline.cc
index c19b685..1f96aac 100644
--- a/runtime/vm/timeline.cc
+++ b/runtime/vm/timeline.cc
@@ -209,36 +209,11 @@
   stream_##name##_.Init(#name, HasStream(enabled_streams_, #name));
   TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAG_DEFAULT)
 #undef TIMELINE_STREAM_FLAG_DEFAULT
-
-  if (Timeline::stream_Embedder_.enabled() &&
-      (Timeline::get_start_recording_cb() != NULL)) {
-    Timeline::get_start_recording_cb()();
-  }
-}
-
-void Timeline::StreamStateChange(const char* stream_name,
-                                 bool prev,
-                                 bool curr) {
-  if (prev == curr) {
-    return;
-  }
-  if (strcmp(stream_name, "Embedder") == 0) {
-    if (curr && (Timeline::get_start_recording_cb() != NULL)) {
-      Timeline::get_start_recording_cb()();
-    } else if (!curr && (Timeline::get_stop_recording_cb() != NULL)) {
-      Timeline::get_stop_recording_cb()();
-    }
-  }
 }
 
 void Timeline::Cleanup() {
   ASSERT(recorder_ != NULL);
 
-  if (Timeline::stream_Embedder_.enabled() &&
-      (Timeline::get_stop_recording_cb() != NULL)) {
-    Timeline::get_stop_recording_cb()();
-  }
-
 #ifndef PRODUCT
   if (FLAG_timeline_dir != NULL) {
     recorder_->WriteTo(FLAG_timeline_dir);
@@ -401,8 +376,6 @@
 
 TimelineEventRecorder* Timeline::recorder_ = NULL;
 MallocGrowableArray<char*>* Timeline::enabled_streams_ = NULL;
-Dart_EmbedderTimelineStartRecording Timeline::start_recording_cb_ = NULL;
-Dart_EmbedderTimelineStopRecording Timeline::stop_recording_cb_ = NULL;
 
 #define TIMELINE_STREAM_DEFINE(name, enabled_by_default)                       \
   TimelineStream Timeline::stream_##name##_;
diff --git a/runtime/vm/timeline.h b/runtime/vm/timeline.h
index 7b8baf0..0f50fbd 100644
--- a/runtime/vm/timeline.h
+++ b/runtime/vm/timeline.h
@@ -102,36 +102,14 @@
 
 #define TIMELINE_STREAM_FLAGS(name, not_used)                                  \
   static void SetStream##name##Enabled(bool enabled) {                         \
-    StreamStateChange(#name, stream_##name##_.enabled(), enabled);             \
     stream_##name##_.set_enabled(enabled);                                     \
   }
   TIMELINE_STREAM_LIST(TIMELINE_STREAM_FLAGS)
 #undef TIMELINE_STREAM_FLAGS
 
-  static void set_start_recording_cb(
-      Dart_EmbedderTimelineStartRecording start_recording_cb) {
-    start_recording_cb_ = start_recording_cb;
-  }
-
-  static Dart_EmbedderTimelineStartRecording get_start_recording_cb() {
-    return start_recording_cb_;
-  }
-
-  static void set_stop_recording_cb(
-      Dart_EmbedderTimelineStopRecording stop_recording_cb) {
-    stop_recording_cb_ = stop_recording_cb;
-  }
-
-  static Dart_EmbedderTimelineStopRecording get_stop_recording_cb() {
-    return stop_recording_cb_;
-  }
-
  private:
-  static void StreamStateChange(const char* stream_name, bool prev, bool curr);
   static TimelineEventRecorder* recorder_;
   static MallocGrowableArray<char*>* enabled_streams_;
-  static Dart_EmbedderTimelineStartRecording start_recording_cb_;
-  static Dart_EmbedderTimelineStopRecording stop_recording_cb_;
 
 #define TIMELINE_STREAM_DECLARE(name, not_used)                                \
   static bool stream_##name##_enabled_;                                        \
diff --git a/runtime/vm/timeline_linux.cc b/runtime/vm/timeline_linux.cc
index ed9ff7f..05ddb69 100644
--- a/runtime/vm/timeline_linux.cc
+++ b/runtime/vm/timeline_linux.cc
@@ -10,6 +10,7 @@
 #include <cstdlib>
 
 #include "platform/atomic.h"
+#include "platform/signal_blocker.h"
 #include "vm/isolate.h"
 #include "vm/json_stream.h"
 #include "vm/lockers.h"
@@ -23,16 +24,25 @@
 
 DECLARE_FLAG(bool, trace_timeline);
 
-TimelineEventSystraceRecorder::TimelineEventSystraceRecorder()
-    : TimelineEventPlatformRecorder(), systrace_fd_(-1) {
-  const char* kSystracePath = "/sys/kernel/debug/tracing/trace_marker";
-  systrace_fd_ = open(kSystracePath, O_WRONLY);
-  if ((systrace_fd_ < 0) && FLAG_trace_timeline) {
-    OS::PrintErr("TimelineEventSystraceRecorder: Could not open `%s`\n",
-                 kSystracePath);
+static int OpenTraceFD() {
+  const char* kSystraceDebugPath = "/sys/kernel/debug/tracing/trace_marker";
+  const char* kSystracePath = "/sys/kernel/tracing/trace_marker";
+
+  int fd = TEMP_FAILURE_RETRY(::open(kSystraceDebugPath, O_WRONLY));
+  if (fd < 0) {
+    fd = TEMP_FAILURE_RETRY(::open(kSystracePath, O_WRONLY));
   }
+
+  if (fd < 0 && FLAG_trace_timeline) {
+    OS::PrintErr("TimelineEventSystraceRecorder: Could not open `%s` or `%s`\n",
+                 kSystraceDebugPath, kSystracePath);
+  }
+  return fd;
 }
 
+TimelineEventSystraceRecorder::TimelineEventSystraceRecorder()
+    : TimelineEventPlatformRecorder(), systrace_fd_(OpenTraceFD()) {}
+
 TimelineEventSystraceRecorder::~TimelineEventSystraceRecorder() {
   if (systrace_fd_ >= 0) {
     close(systrace_fd_);
diff --git a/runtime/vm/type_testing_stubs_arm.cc b/runtime/vm/type_testing_stubs_arm.cc
new file mode 100644
index 0000000..30f1de07
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_arm.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+
+#if defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/type_testing_stubs.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const Type& type,
+    const Class& type_class) {
+  const Register kInstanceReg = R0;
+  const Register kClassIdReg = R9;
+
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
+                                      kInstanceReg, kClassIdReg);
+
+  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
+  __ Branch(FieldAddress(CODE_REG, Code::entry_point_offset()));
+}
+
+void TypeTestingStubGenerator::
+    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
+                                                      HierarchyInfo* hi,
+                                                      const Class& type_class,
+                                                      const TypeArguments& tp,
+                                                      const TypeArguments& ta) {
+  const Register kInstanceReg = R0;
+  const Register kInstanceTypeArguments = NOTFP;
+  const Register kClassIdReg = R9;
+
+  BuildOptimizedSubclassRangeCheckWithTypeArguments(
+      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
+      kInstanceTypeArguments);
+}
+
+void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const AbstractType& type_arg,
+    intptr_t type_param_value_offset_i,
+    Label* check_failed) {
+  const Register kInstantiatorTypeArgumentsReg = R2;
+  const Register kFunctionTypeArgumentsReg = R1;
+  const Register kInstanceTypeArguments = NOTFP;
+
+  const Register kClassIdReg = R9;
+  const Register kOwnTypeArgumentValue = TMP;
+
+  BuildOptimizedTypeArgumentValueCheck(
+      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
+      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/type_testing_stubs_arm64.cc b/runtime/vm/type_testing_stubs_arm64.cc
new file mode 100644
index 0000000..0f2981e
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_arm64.cc
@@ -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.
+
+#include "vm/globals.h"
+
+#if defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/type_testing_stubs.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const Type& type,
+    const Class& type_class) {
+  const Register kInstanceReg = R0;
+  const Register kClassIdReg = R9;
+
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
+                                      kInstanceReg, kClassIdReg);
+
+  __ ldr(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
+  __ ldr(R9, FieldAddress(CODE_REG, Code::entry_point_offset()));
+  __ br(R9);
+}
+
+void TypeTestingStubGenerator::
+    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
+                                                      HierarchyInfo* hi,
+                                                      const Class& type_class,
+                                                      const TypeArguments& tp,
+                                                      const TypeArguments& ta) {
+  const Register kInstanceReg = R0;
+  const Register kInstanceTypeArguments = R7;
+  const Register kClassIdReg = R9;
+
+  BuildOptimizedSubclassRangeCheckWithTypeArguments(
+      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
+      kInstanceTypeArguments);
+}
+
+void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const AbstractType& type_arg,
+    intptr_t type_param_value_offset_i,
+    Label* check_failed) {
+  const Register kInstantiatorTypeArgumentsReg = R1;
+  const Register kFunctionTypeArgumentsReg = R2;
+  const Register kInstanceTypeArguments = R7;
+
+  const Register kClassIdReg = R9;
+  const Register kOwnTypeArgumentValue = TMP;
+
+  BuildOptimizedTypeArgumentValueCheck(
+      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
+      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_ARM64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/type_testing_stubs_x64.cc b/runtime/vm/type_testing_stubs_x64.cc
new file mode 100644
index 0000000..69991de
--- /dev/null
+++ b/runtime/vm/type_testing_stubs_x64.cc
@@ -0,0 +1,66 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+#include "vm/globals.h"
+
+#if defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
+
+#include "vm/type_testing_stubs.h"
+
+#define __ assembler->
+
+namespace dart {
+
+void TypeTestingStubGenerator::BuildOptimizedTypeTestStub(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const Type& type,
+    const Class& type_class) {
+  const Register kInstanceReg = RAX;
+  const Register kClassIdReg = TMP;
+
+  BuildOptimizedTypeTestStubFastCases(assembler, hi, type, type_class,
+                                      kInstanceReg, kClassIdReg);
+
+  __ movq(CODE_REG, Address(THR, Thread::slow_type_test_stub_offset()));
+  __ jmp(FieldAddress(CODE_REG, Code::entry_point_offset()));
+}
+
+void TypeTestingStubGenerator::
+    BuildOptimizedSubclassRangeCheckWithTypeArguments(Assembler* assembler,
+                                                      HierarchyInfo* hi,
+                                                      const Class& type_class,
+                                                      const TypeArguments& tp,
+                                                      const TypeArguments& ta) {
+  const Register kInstanceReg = RAX;
+  const Register kInstanceTypeArguments = RSI;
+  const Register kClassIdReg = TMP;
+
+  BuildOptimizedSubclassRangeCheckWithTypeArguments(
+      assembler, hi, type_class, tp, ta, kClassIdReg, kInstanceReg,
+      kInstanceTypeArguments);
+}
+
+void TypeTestingStubGenerator::BuildOptimizedTypeArgumentValueCheck(
+    Assembler* assembler,
+    HierarchyInfo* hi,
+    const AbstractType& type_arg,
+    intptr_t type_param_value_offset_i,
+    Label* check_failed) {
+  const Register kInstanceTypeArguments = RSI;
+  const Register kInstantiatorTypeArgumentsReg = RDX;
+  const Register kFunctionTypeArgumentsReg = RCX;
+
+  const Register kClassIdReg = TMP;
+  const Register kOwnTypeArgumentValue = RDI;
+
+  BuildOptimizedTypeArgumentValueCheck(
+      assembler, hi, type_arg, type_param_value_offset_i, kClassIdReg,
+      kInstanceTypeArguments, kInstantiatorTypeArgumentsReg,
+      kFunctionTypeArgumentsReg, kOwnTypeArgumentValue, check_failed);
+}
+
+}  // namespace dart
+
+#endif  // defined(TARGET_ARCH_X64) && !defined(DART_PRECOMPILED_RUNTIME)
diff --git a/runtime/vm/virtual_memory.cc b/runtime/vm/virtual_memory.cc
index ab89a53..6d73ba0 100644
--- a/runtime/vm/virtual_memory.cc
+++ b/runtime/vm/virtual_memory.cc
@@ -14,14 +14,12 @@
           Utils::RoundDown(address1, PageSize()));
 }
 
-void VirtualMemory::Truncate(intptr_t new_size, bool try_unmap) {
-  ASSERT((new_size & (PageSize() - 1)) == 0);
+void VirtualMemory::Truncate(intptr_t new_size) {
+  ASSERT(Utils::IsAligned(new_size, PageSize()));
   ASSERT(new_size <= size());
-  if (try_unmap &&
-      (reserved_.size() ==
-       region_.size()) && /* Don't create holes in reservation. */
-      FreeSubSegment(reinterpret_cast<void*>(start() + new_size),
-                     size() - new_size)) {
+  if (reserved_.size() == region_.size()) { // Don't create holes in reservation.
+    FreeSubSegment(reinterpret_cast<void*>(start() + new_size),
+                   size() - new_size);
     reserved_.set_size(new_size);
   }
   region_.Subregion(region_, 0, new_size);
diff --git a/runtime/vm/virtual_memory.h b/runtime/vm/virtual_memory.h
index 75ca214..6d74541 100644
--- a/runtime/vm/virtual_memory.h
+++ b/runtime/vm/virtual_memory.h
@@ -57,10 +57,8 @@
 
   static bool InSamePage(uword address0, uword address1);
 
-  // Truncate this virtual memory segment. If try_unmap is false, the
-  // memory beyond the new end is still accessible, but will be returned
-  // upon destruction.
-  void Truncate(intptr_t new_size, bool try_unmap = true);
+  // Truncate this virtual memory segment.
+  void Truncate(intptr_t new_size);
 
   // False for a part of a snapshot added directly to the Dart heap, which
   // belongs to the embedder and must not be deallocated or have its
@@ -72,7 +70,7 @@
  private:
   // Free a sub segment. On operating systems that support it this
   // can give back the virtual memory to the system. Returns true on success.
-  static bool FreeSubSegment(void* address, intptr_t size);
+  static void FreeSubSegment(void* address, intptr_t size);
 
   // This constructor is only used internally when reserving new virtual spaces.
   // It does not reserve any virtual address space on its own.
diff --git a/runtime/vm/virtual_memory_fuchsia.cc b/runtime/vm/virtual_memory_fuchsia.cc
index f11b354..63c47ae 100644
--- a/runtime/vm/virtual_memory_fuchsia.cc
+++ b/runtime/vm/virtual_memory_fuchsia.cc
@@ -126,11 +126,10 @@
   }
 }
 
-bool VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
+void VirtualMemory::FreeSubSegment(void* address, intptr_t size) {
   const uword start = reinterpret_cast<uword>(address);
   unmap(zx_vmar_root_self(), start, start + size);
   LOG_INFO("zx_vmar_unmap(%p, %lx) success\n", address, size);
-  return true;
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
diff --git a/runtime/vm/virtual_memory_posix.cc b/runtime/vm/virtual_memory_posix.cc
index e9d9016..31c7f15 100644
--- a/runtime/vm/virtual_memory_posix.cc
+++ b/runtime/vm/virtual_memory_posix.cc
@@ -76,11 +76,10 @@
   }
 }
 
-bool VirtualMemory::FreeSubSegment(void* address,
+void VirtualMemory::FreeSubSegment(void* address,
                                    intptr_t size) {
   const uword start = reinterpret_cast<uword>(address);
   unmap(start, start + size);
-  return true;
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
diff --git a/runtime/vm/virtual_memory_test.cc b/runtime/vm/virtual_memory_test.cc
index 9454ecf..d54fe28 100644
--- a/runtime/vm/virtual_memory_test.cc
+++ b/runtime/vm/virtual_memory_test.cc
@@ -77,25 +77,13 @@
   for (intptr_t i = 0; i < kIterations; ++i) {
     VirtualMemory* vm =
         VirtualMemory::Allocate(kVirtualMemoryBlockSize, false, NULL);
-    vm->Truncate(kVirtualMemoryBlockSize / 2, true);
+    vm->Truncate(kVirtualMemoryBlockSize / 2);
     delete vm;
   }
   for (intptr_t i = 0; i < kIterations; ++i) {
     VirtualMemory* vm =
         VirtualMemory::Allocate(kVirtualMemoryBlockSize, true, NULL);
-    vm->Truncate(kVirtualMemoryBlockSize / 2, false);
-    delete vm;
-  }
-  for (intptr_t i = 0; i < kIterations; ++i) {
-    VirtualMemory* vm =
-        VirtualMemory::Allocate(kVirtualMemoryBlockSize, true, NULL);
-    vm->Truncate(0, true);
-    delete vm;
-  }
-  for (intptr_t i = 0; i < kIterations; ++i) {
-    VirtualMemory* vm =
-        VirtualMemory::Allocate(kVirtualMemoryBlockSize, false, NULL);
-    vm->Truncate(0, false);
+    vm->Truncate(0);
     delete vm;
   }
 }
diff --git a/runtime/vm/virtual_memory_win.cc b/runtime/vm/virtual_memory_win.cc
index d976676..9c917b3 100644
--- a/runtime/vm/virtual_memory_win.cc
+++ b/runtime/vm/virtual_memory_win.cc
@@ -62,12 +62,11 @@
   }
 }
 
-bool VirtualMemory::FreeSubSegment(void* address,
+void VirtualMemory::FreeSubSegment(void* address,
                                    intptr_t size) {
   if (VirtualFree(address, size, MEM_DECOMMIT) == 0) {
     FATAL1("VirtualFree failed: Error code %d\n", GetLastError());
   }
-  return true;
 }
 
 void VirtualMemory::Protect(void* address, intptr_t size, Protection mode) {
diff --git a/runtime/vm/vm_sources.gni b/runtime/vm/vm_sources.gni
index 9732770..198d04e 100644
--- a/runtime/vm/vm_sources.gni
+++ b/runtime/vm/vm_sources.gni
@@ -47,6 +47,7 @@
   "constants_dbc.h",
   "constants_ia32.h",
   "constants_kbc.h",
+  "constants_x64.cc",
   "constants_x64.h",
   "cpu.h",
   "cpu_arm.cc",
@@ -91,6 +92,7 @@
   "dwarf.h",
   "exceptions.cc",
   "exceptions.h",
+  "ffi_trampoline_stubs_x64.cc",
   "finalizable_data.h",
   "fixed_cache.h",
   "flag_list.h",
@@ -293,13 +295,10 @@
   "stack_frame_x64.h",
   "stack_trace.cc",
   "stack_trace.h",
+  "static_type_exactness_state.h",
   "stub_code.cc",
   "stub_code.h",
-  "stub_code_arm.cc",
-  "stub_code_arm64.cc",
-  "stub_code_dbc.cc",
-  "stub_code_ia32.cc",
-  "stub_code_x64.cc",
+  "stub_code_list.h",
   "symbols.cc",
   "symbols.h",
   "tags.cc",
@@ -337,6 +336,9 @@
   "token_position.h",
   "type_table.h",
   "type_testing_stubs.cc",
+  "type_testing_stubs_arm.cc",
+  "type_testing_stubs_arm64.cc",
+  "type_testing_stubs_x64.cc",
   "type_testing_stubs.h",
   "unibrow-inl.h",
   "unibrow.cc",
diff --git a/samples/ffi/coordinate.dart b/samples/ffi/coordinate.dart
new file mode 100644
index 0000000..f8ac7d48
--- /dev/null
+++ b/samples/ffi/coordinate.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+/// Sample struct for dart:ffi library.
+@ffi.struct
+class Coordinate extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  double x;
+
+  @ffi.Double()
+  double y;
+
+  @ffi.Pointer()
+  Coordinate next;
+
+  // Implementation generated by @ffi.struct annotation.
+  external static int sizeOf();
+
+  Coordinate offsetBy(int offsetInBytes) =>
+      super.offsetBy(offsetInBytes).cast();
+
+  Coordinate elementAt(int index) => offsetBy(sizeOf() * index);
+
+  static Coordinate allocate({int count: 1}) =>
+      ffi.allocate<ffi.Uint8>(count: count * sizeOf()).cast();
+
+  /// Allocate a new [Coordinate] in C memory and populate its fields.
+  factory Coordinate(double x, double y, Coordinate next) {
+    Coordinate result = Coordinate.allocate()
+      ..x = x
+      ..y = y
+      ..next = next;
+    return result;
+  }
+}
diff --git a/samples/ffi/sample_ffi_data.dart b/samples/ffi/sample_ffi_data.dart
new file mode 100644
index 0000000..ba05601
--- /dev/null
+++ b/samples/ffi/sample_ffi_data.dart
@@ -0,0 +1,274 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:ffi' as ffi;
+
+main(List<String> arguments) {
+  print('start main');
+
+  {
+    // basic operation: allocate, get, set, and free
+    ffi.Pointer<ffi.Int64> p = ffi.allocate();
+    p.store(42);
+    int pValue = p.load();
+    print('${p.runtimeType} value: ${pValue}');
+    p.free();
+  }
+
+  {
+    // undefined behavior before set
+    ffi.Pointer<ffi.Int64> p = ffi.allocate();
+    int pValue = p.load();
+    print('If not set, returns garbage: ${pValue}');
+    p.free();
+  }
+
+  {
+    // pointers can be created from an address
+    ffi.Pointer<ffi.Int64> pHelper = ffi.allocate();
+    pHelper.store(1337);
+
+    int address = pHelper.address;
+    print('Address: ${address}');
+
+    ffi.Pointer<ffi.Int64> p = ffi.fromAddress(address);
+    print('${p.runtimeType} value: ${p.load<int>()}');
+
+    pHelper.free();
+  }
+
+  {
+    // address is zeroed out after free
+    ffi.Pointer<ffi.Int64> p = ffi.allocate();
+    p.free();
+    print('After free, address is zero: ${p.address}');
+  }
+
+  {
+    // pointer arithmetic can be done with element offsets or bytes
+    ffi.Pointer<ffi.Int64> p1 = ffi.allocate<ffi.Int64>(count: 2);
+    print('p1 address: ${p1.address}');
+
+    ffi.Pointer<ffi.Int64> p2 = p1.elementAt(1);
+    print('p1.elementAt(1) address: ${p2.address}');
+    p2.store(100);
+
+    ffi.Pointer<ffi.Int64> p3 = p1.offsetBy(8);
+    print('p1.offsetBy(8) address: ${p3.address}');
+    print('p1.offsetBy(8) value: ${p3.load<int>()}');
+    p1.free();
+  }
+
+  {
+    // allocating too much throws an exception
+    try {
+      int maxMint = 9223372036854775807; // 2^63 - 1
+      ffi.allocate<ffi.Int64>(count: maxMint);
+    } on RangeError {
+      print('Expected exception on allocating too much');
+    }
+    try {
+      int maxInt1_8 = 1152921504606846975; // 2^60 -1
+      ffi.allocate<ffi.Int64>(count: maxInt1_8);
+    } on ArgumentError {
+      print('Expected exception on allocating too much');
+    }
+  }
+
+  {
+    // pointers can be cast into another type
+    // resulting in the corresponding bits read
+    ffi.Pointer<ffi.Int64> p1 = ffi.allocate();
+    p1.store(9223372036854775807); // 2^63 - 1
+
+    ffi.Pointer<ffi.Int32> p2 = p1.cast();
+    print('${p2.runtimeType} value: ${p2.load<int>()}'); // -1
+
+    ffi.Pointer<ffi.Int32> p3 = p2.elementAt(1);
+    print('${p3.runtimeType} value: ${p3.load<int>()}'); // 2^31 - 1
+
+    p1.free();
+  }
+
+  {
+    // data can be tightly packed in memory
+    ffi.Pointer<ffi.Int8> p = ffi.allocate(count: 8);
+    for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+      p.elementAt(i).store(i * 3);
+    }
+    for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+      print('p.elementAt($i) value: ${p.elementAt(i).load<int>()}');
+    }
+    p.free();
+  }
+
+  {
+    // exception on storing a value that does not fit
+    ffi.Pointer<ffi.Int32> p11 = ffi.allocate();
+
+    try {
+      p11.store(9223372036854775807);
+    } on ArgumentError {
+      print('Expected exception on calling set with a value that does not fit');
+    }
+
+    p11.free();
+  }
+
+  {
+    // doubles
+    ffi.Pointer<ffi.Double> p = ffi.allocate();
+    p.store(3.14159265359);
+    print('${p.runtimeType} value: ${p.load<double>()}');
+    p.store(3.14);
+    print('${p.runtimeType} value: ${p.load<double>()}');
+    p.free();
+  }
+
+  {
+    // floats
+    ffi.Pointer<ffi.Float> p = ffi.allocate();
+    p.store(3.14159265359);
+    print('${p.runtimeType} value: ${p.load<double>()}');
+    p.store(3.14);
+    print('${p.runtimeType} value: ${p.load<double>()}');
+    p.free();
+  }
+
+  {
+    // ffi.IntPtr varies in size based on whether the platform is 32 or 64 bit
+    // addresses of pointers fit in this size
+    ffi.Pointer<ffi.IntPtr> p = ffi.allocate();
+    int p14addr = p.address;
+    p.store(p14addr);
+    int pValue = p.load();
+    print('${p.runtimeType} value: ${pValue}');
+    p.free();
+  }
+
+  {
+    // void pointers are unsized
+    // the size of the element it is pointing to is undefined
+    // this means they cannot be ffi.allocated, read, or written
+    // this would would fail to compile:
+    // ffi.allocate<ffi.Void>();
+
+    ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
+    ffi.Pointer<ffi.Void> p2 = p1.cast();
+    print('${p2.runtimeType} address: ${p2.address}');
+
+    // this fails to compile, we cannot read something unsized
+    // p2.load<int>();
+
+    // this fails to compile, we cannot write something unsized
+    // p2.store(1234);
+
+    p1.free();
+  }
+
+  {
+    // pointer to a pointer to something
+    ffi.Pointer<ffi.Int16> pHelper = ffi.allocate();
+    pHelper.store(17);
+
+    ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
+
+    // storing into a pointer pointer automatically unboxes
+    p.store(pHelper);
+
+    // reading from a pointer pointer automatically boxes
+    ffi.Pointer<ffi.Int16> pHelper2 = p.load();
+    print('${pHelper2.runtimeType} value: ${pHelper2.load<int>()}');
+
+    int pValue = p.load<ffi.Pointer<ffi.Int16>>().load();
+    print('${p.runtimeType} value\'s value: ${pValue}');
+
+    p.free();
+    pHelper.free();
+  }
+
+  {
+    // the pointer to pointer types must match up
+    ffi.Pointer<ffi.Int8> pHelper = ffi.allocate();
+    pHelper.store(123);
+
+    ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
+
+    // this fails to compile due to type mismatch
+    // p.store(pHelper);
+
+    pHelper.free();
+    p.free();
+  }
+
+  {
+    // null pointer in Dart points to address 0 in c++
+    ffi.Pointer<ffi.Pointer<ffi.Int8>> pointerToPointer = ffi.allocate();
+    ffi.Pointer<ffi.Int8> value = null;
+    pointerToPointer.store(value);
+    value = pointerToPointer.load();
+    print("Loading a pointer to the 0 address is null: ${value}");
+    pointerToPointer.free();
+  }
+
+  {
+    // sizeof returns element size in bytes
+    print('sizeOf<ffi.Double>(): ${ffi.sizeOf<ffi.Double>()}');
+    print('sizeOf<ffi.Int16>(): ${ffi.sizeOf<ffi.Int16>()}');
+    print('sizeOf<ffi.IntPtr>(): ${ffi.sizeOf<ffi.IntPtr>()}');
+  }
+
+  {
+    // only concrete sub types of NativeType can be ffi.allocated
+    // this would fail to compile:
+    // ffi.allocate();
+  }
+
+  {
+    // only concrete sub types of NativeType can be asked for size
+    // this would fail to compile:
+    // ffi.sizeOf();
+  }
+
+  {
+    // with ffi.IntPtr pointers, one can manually setup aribtrary data
+    // structres in C memory.
+
+    void createChain(ffi.Pointer<ffi.IntPtr> head, int length, int value) {
+      if (length == 0) {
+        head.store(value);
+        return;
+      }
+      ffi.Pointer<ffi.IntPtr> next = ffi.allocate<ffi.IntPtr>();
+      head.store(next.address);
+      createChain(next, length - 1, value);
+    }
+
+    int getChainValue(ffi.Pointer<ffi.IntPtr> head, int length) {
+      if (length == 0) {
+        return head.load();
+      }
+      ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
+      return getChainValue(next, length - 1);
+    }
+
+    void freeChain(ffi.Pointer<ffi.IntPtr> head, int length) {
+      ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
+      head.free();
+      if (length == 0) {
+        return;
+      }
+      freeChain(next, length - 1);
+    }
+
+    int length = 10;
+    ffi.Pointer<ffi.IntPtr> head = ffi.allocate();
+    createChain(head, length, 512);
+    int tailValue = getChainValue(head, length);
+    print('tailValue: ${tailValue}');
+    freeChain(head, length);
+  }
+
+  print("end main");
+}
diff --git a/samples/ffi/sample_ffi_dynamic_library.dart b/samples/ffi/sample_ffi_dynamic_library.dart
new file mode 100644
index 0000000..cf83400
--- /dev/null
+++ b/samples/ffi/sample_ffi_dynamic_library.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:ffi' as ffi;
+
+typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
+
+typedef DoubleUnOp = double Function(double);
+
+main(List<String> arguments) {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  print(l);
+  print(l.runtimeType);
+
+  var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
+  print(timesFour);
+  print(timesFour.runtimeType);
+
+  print(timesFour(3.0));
+}
diff --git a/samples/ffi/sample_ffi_functions.dart b/samples/ffi/sample_ffi_functions.dart
new file mode 100644
index 0000000..62b5718
--- /dev/null
+++ b/samples/ffi/sample_ffi_functions.dart
@@ -0,0 +1,267 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:ffi' as ffi;
+
+typedef NativeUnaryOp = ffi.Int32 Function(ffi.Int32);
+typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
+typedef UnaryOp = int Function(int);
+typedef BinaryOp = int Function(int, int);
+typedef GenericBinaryOp<T> = int Function(int, T);
+typedef NativeQuadOpSigned = ffi.Int64 Function(
+    ffi.Int64, ffi.Int32, ffi.Int16, ffi.Int8);
+typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
+    ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8);
+typedef NativeFunc4 = ffi.IntPtr Function(ffi.IntPtr);
+typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
+typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
+typedef NativeOctenaryOp = ffi.IntPtr Function(
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr);
+typedef NativeDoubleOctenaryOp = ffi.Double Function(
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double);
+typedef NativeVigesimalOp = ffi.Double Function(
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double);
+typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
+    ffi.Pointer<ffi.Int64>);
+typedef QuadOp = int Function(int, int, int, int);
+typedef DoubleUnaryOp = double Function(double);
+typedef OctenaryOp = int Function(
+    int, int, int, int, int, int, int, int, int, int);
+typedef DoubleOctenaryOp = double Function(double, double, double, double,
+    double, double, double, double, double, double);
+typedef VigesimalOp = double Function(
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double);
+
+main(List<String> arguments) {
+  print('start main');
+
+  ffi.DynamicLibrary ffiTestFunctions =
+      ffi.DynamicLibrary.open("ffi_test_functions");
+
+  {
+    // int32 bin op
+    BinaryOp sumPlus42 =
+        ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+
+    var result = sumPlus42(3, 17);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // various size arguments
+    QuadOp intComputation = ffiTestFunctions
+        .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
+    var result = intComputation(125, 250, 500, 1000);
+    print(result);
+    print(result.runtimeType);
+
+    var mint = 0x7FFFFFFFFFFFFFFF; // 2 ^ 63 - 1
+    result = intComputation(1, 1, 0, mint);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // unsigned int parameters
+    QuadOp uintComputation = ffiTestFunctions
+        .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+    var result = uintComputation(0xFF, 0xFFFF, 0xFFFFFFFF, -1);
+    result = uintComputation(1, 1, 0, -1);
+    print(result);
+    print(result.runtimeType);
+    print(-0xFF + 0xFFFF - 0xFFFFFFFF);
+  }
+
+  {
+    // architecture size argument
+    ffi.Pointer<ffi.NativeFunction<NativeFunc4>> p =
+        ffiTestFunctions.lookup("Times3");
+    UnaryOp f6 = p.asFunction();
+    var result = f6(1337);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // function with double
+    DoubleUnaryOp times1_337Double = ffiTestFunctions
+        .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+    var result = times1_337Double(2.0);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // function with float
+    DoubleUnaryOp times1_337Float = ffiTestFunctions
+        .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
+    var result = times1_337Float(1000.0);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // function with many arguments: arguments get passed in registers and stack
+    OctenaryOp sumManyInts = ffiTestFunctions
+        .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
+    var result = sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // function with many double arguments
+    DoubleOctenaryOp sumManyDoubles = ffiTestFunctions.lookupFunction<
+        NativeDoubleOctenaryOp, DoubleOctenaryOp>("SumManyDoubles");
+    var result =
+        sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // function with many arguments, ints and doubles mixed
+    VigesimalOp sumManyNumbers = ffiTestFunctions
+        .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+    var result = sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11,
+        12.0, 13, 14.0, 15, 16.0, 17, 18.0, 19, 20.0);
+    print(result);
+    print(result.runtimeType);
+  }
+
+  {
+    // pass an array / pointer as argument
+    Int64PointerUnOp assign1337Index1 = ffiTestFunctions
+        .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
+    ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
+    p2.store(42);
+    p2.elementAt(1).store(1000);
+    print(p2.elementAt(1).address.toRadixString(16));
+    print(p2.elementAt(1).load<int>());
+    ffi.Pointer<ffi.Int64> result = assign1337Index1(p2);
+    print(p2.elementAt(1).load<int>());
+    print(assign1337Index1);
+    print(assign1337Index1.runtimeType);
+    print(result);
+    print(result.runtimeType);
+    print(result.address.toRadixString(16));
+    print(result.load<int>());
+  }
+
+  {
+    // passing in null for an int argument throws a null pointer exception
+    BinaryOp sumPlus42 =
+        ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+
+    int x = null;
+    try {
+      sumPlus42(43, x);
+    } on ArgumentError {
+      print('Expected exception on passing null for int');
+    }
+  }
+
+  {
+    // passing in null for a double argument throws a null pointer exception
+    DoubleUnaryOp times1_337Double = ffiTestFunctions
+        .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+
+    double x = null;
+    try {
+      times1_337Double(x);
+    } on ArgumentError {
+      print('Expected exception on passing null for double');
+    }
+  }
+
+  {
+    // passing in null for an int argument throws a null pointer exception
+    VigesimalOp sumManyNumbers = ffiTestFunctions
+        .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+
+    int x = null;
+    try {
+      sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
+          14.0, 15, 16.0, 17, 18.0, x, 20.0);
+    } on ArgumentError {
+      print('Expected exception on passing null for int');
+    }
+  }
+
+  {
+    // passing in null for a pointer argument results in a nullptr in c
+    Int64PointerUnOp nullableInt64ElemAt1 =
+        ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
+            "NullableInt64ElemAt1");
+
+    ffi.Pointer<ffi.Int64> result = nullableInt64ElemAt1(null);
+    print(result);
+    print(result.runtimeType);
+
+    ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
+    result = nullableInt64ElemAt1(p2);
+    print(result);
+    print(result.runtimeType);
+    p2.free();
+  }
+
+  print("end main");
+}
diff --git a/samples/ffi/sample_ffi_functions_callbacks.dart b/samples/ffi/sample_ffi_functions_callbacks.dart
new file mode 100644
index 0000000..ddd6840
--- /dev/null
+++ b/samples/ffi/sample_ffi_functions_callbacks.dart
@@ -0,0 +1,80 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:ffi' as ffi;
+
+import 'coordinate.dart';
+
+typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+
+typedef CoordinateTrice = Coordinate Function(
+    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+
+typedef BinaryOp = int Function(int, int);
+typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
+typedef NativeIntptrBinOpLookup
+    = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
+
+typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+
+typedef ApplyTo42And74Type = int Function(
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+
+int myPlus(int a, int b) {
+  print("myPlus");
+  print(a);
+  print(b);
+  return a + b;
+}
+
+main(List<String> arguments) {
+  print('start main');
+
+  ffi.DynamicLibrary ffiTestFunctions =
+      ffi.DynamicLibrary.open("ffi_test_functions");
+
+  {
+    // pass a c pointer to a c function as an argument to a c function
+    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
+        transposeCoordinatePointer =
+        ffiTestFunctions.lookup("TransposeCoordinate");
+    ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
+        ffiTestFunctions.lookup("CoordinateUnOpTrice");
+    CoordinateTrice coordinateUnOpTrice = p2.asFunction();
+    Coordinate c1 = Coordinate(10.0, 20.0, null);
+    c1.next = c1;
+    Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+    print(result.runtimeType);
+    print(result.x);
+    print(result.y);
+  }
+
+  {
+    // return a c pointer to a c function from a c function
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p14 =
+        ffiTestFunctions.lookup("IntptrAdditionClosure");
+    NativeIntptrBinOpLookup intptrAdditionClosure = p14.asFunction();
+
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
+        intptrAdditionClosure();
+    BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
+    print(intptrAddition(10, 27));
+  }
+
+  {
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> pointer =
+        ffi.fromFunction(myPlus);
+    print(pointer);
+
+    ffi.Pointer<ffi.NativeFunction<NativeApplyTo42And74Type>> p17 =
+        ffiTestFunctions.lookup("ApplyTo42And74");
+    ApplyTo42And74Type applyTo42And74 = p17.asFunction();
+
+    // int result = applyTo42And74(pointer);
+    // print(result);
+  }
+
+  print("end main");
+}
diff --git a/samples/ffi/sample_ffi_functions_structs.dart b/samples/ffi/sample_ffi_functions_structs.dart
new file mode 100644
index 0000000..ba076e0
--- /dev/null
+++ b/samples/ffi/sample_ffi_functions_structs.dart
@@ -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 file.
+
+import 'dart:ffi' as ffi;
+
+import 'coordinate.dart';
+
+typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+
+main(List<String> arguments) {
+  print('start main');
+
+  ffi.DynamicLibrary ffiTestFunctions =
+      ffi.DynamicLibrary.open("ffi_test_functions");
+
+  {
+    // pass a struct to a c function and get a struct as return value
+    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+        ffiTestFunctions.lookup("TransposeCoordinate");
+    NativeCoordinateOp f1 = p1.asFunction();
+
+    Coordinate c1 = Coordinate(10.0, 20.0, null);
+    Coordinate c2 = Coordinate(42.0, 84.0, c1);
+    c1.next = c2;
+
+    Coordinate result = f1(c1);
+
+    print(c1.x);
+    print(c1.y);
+
+    print(result.runtimeType);
+
+    print(result.x);
+    print(result.y);
+  }
+
+  {
+    // pass an array of structs to a c funtion
+    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+        ffiTestFunctions.lookup("CoordinateElemAt1");
+    NativeCoordinateOp f1 = p1.asFunction();
+
+    Coordinate c1 = Coordinate.allocate(count: 3);
+    Coordinate c2 = c1.elementAt(1);
+    Coordinate c3 = c1.elementAt(2);
+    c1.x = 10.0;
+    c1.y = 10.0;
+    c1.next = c3;
+    c2.x = 20.0;
+    c2.y = 20.0;
+    c2.next = c1;
+    c3.x = 30.0;
+    c3.y = 30.0;
+    c3.next = c2;
+
+    Coordinate result = f1(c1);
+
+    print(result.x);
+    print(result.y);
+  }
+
+  print("end main");
+}
diff --git a/samples/ffi/sample_ffi_structs.dart b/samples/ffi/sample_ffi_structs.dart
new file mode 100644
index 0000000..fd757e5
--- /dev/null
+++ b/samples/ffi/sample_ffi_structs.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. 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:ffi' as ffi;
+
+import 'coordinate.dart';
+
+main(List<String> arguments) {
+  print('start main');
+
+  {
+    // allocates each coordinate separately in c memory
+    Coordinate c1 = Coordinate(10.0, 10.0, null);
+    Coordinate c2 = Coordinate(20.0, 20.0, c1);
+    Coordinate c3 = Coordinate(30.0, 30.0, c2);
+    c1.next = c3;
+
+    Coordinate currentCoordinate = c1;
+    for (var i in [0, 1, 2, 3, 4]) {
+      currentCoordinate = currentCoordinate.next;
+      print("${currentCoordinate.x}; ${currentCoordinate.y}");
+    }
+
+    c1.free();
+    c2.free();
+    c3.free();
+  }
+
+  {
+    // allocates coordinates consecutively in c memory
+    Coordinate c1 = Coordinate.allocate(count: 3);
+    Coordinate c2 = c1.elementAt(1);
+    Coordinate c3 = c1.elementAt(2);
+    c1.x = 10.0;
+    c1.y = 10.0;
+    c1.next = c3;
+    c2.x = 20.0;
+    c2.y = 20.0;
+    c2.next = c1;
+    c3.x = 30.0;
+    c3.y = 30.0;
+    c3.next = c2;
+
+    Coordinate currentCoordinate = c1;
+    for (var i in [0, 1, 2, 3, 4]) {
+      currentCoordinate = currentCoordinate.next;
+      print("${currentCoordinate.x}; ${currentCoordinate.y}");
+    }
+
+    c1.free();
+  }
+
+  {
+    Coordinate c = Coordinate(10, 10, null);
+    print(c is Coordinate);
+    print(c is ffi.Pointer<ffi.Void>);
+    print(c is ffi.Pointer);
+    c.free();
+  }
+
+  print("end main");
+}
diff --git a/sdk/BUILD.gn b/sdk/BUILD.gn
index ec27270..3f48b0a 100644
--- a/sdk/BUILD.gn
+++ b/sdk/BUILD.gn
@@ -183,6 +183,7 @@
   "convert",
   "core",
   "developer",
+  "ffi",
   "html",
   "_http",
   "indexed_db",
@@ -856,14 +857,20 @@
   ]
 }
 
-# This rule copies the dartdoc_options.yaml file.
-copy("copy_dartdoc_options") {
+# This rule generates a custom dartdoc_options.yaml file.
+action("write_dartdoc_options") {
   visibility = [ ":create_common_sdk" ]
-  sources = [
-    "../dartdoc_options.yaml",
+  inputs = [
+    "../.git/logs/HEAD",
   ]
+  output = "$root_out_dir/dart-sdk/dartdoc_options.yaml"
   outputs = [
-    "$root_out_dir/dart-sdk/dartdoc_options.yaml",
+    output,
+  ]
+  script = "../tools/write_dartdoc_options_file.py"
+  args = [
+    "--output",
+    rebase_path(output),
   ]
 }
 
@@ -886,13 +893,13 @@
     ":copy_api_readme",
     ":copy_dart",
     ":copy_dartdoc_files",
-    ":copy_dartdoc_options",
     ":copy_headers",
     ":copy_libraries_dart",
     ":copy_license",
     ":copy_libraries_specification",
     ":copy_readme",
     ":copy_vm_dill_files",
+    ":write_dartdoc_options",
     ":write_revision_file",
     ":write_version_file",
   ]
diff --git a/sdk/lib/_internal/js_runtime/lib/js_helper.dart b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
index f36ace5..0befba60 100644
--- a/sdk/lib/_internal/js_runtime/lib/js_helper.dart
+++ b/sdk/lib/_internal/js_runtime/lib/js_helper.dart
@@ -377,167 +377,6 @@
   }
 }
 
-class ReflectionInfo {
-  static const int REQUIRED_PARAMETERS_INFO = 0;
-  static const int OPTIONAL_PARAMETERS_INFO = 1;
-  static const int FUNCTION_TYPE_INDEX = 2;
-  static const int FIRST_DEFAULT_ARGUMENT = 3;
-
-  /// A JavaScript function object.
-  final jsFunction;
-
-  /// Raw reflection information.
-  final List data;
-
-  /// Is this a getter or a setter.
-  final bool isAccessor;
-
-  /// Number of required parameters.
-  final int requiredParameterCount;
-
-  /// Number of optional parameters.
-  final int optionalParameterCount;
-
-  /// Are optional parameters named.
-  final bool areOptionalParametersNamed;
-
-  /// Either an index to the function type in the embedded `metadata` global or
-  /// a JavaScript function object which can compute such a type (presumably
-  /// due to free type variables).
-  final functionType;
-
-  List cachedSortedIndices;
-
-  ReflectionInfo.internal(
-      this.jsFunction,
-      this.data,
-      this.isAccessor,
-      this.requiredParameterCount,
-      this.optionalParameterCount,
-      this.areOptionalParametersNamed,
-      this.functionType);
-
-  factory ReflectionInfo(jsFunction) {
-    List data = JS('JSExtendableArray|Null', r'#.$reflectionInfo', jsFunction);
-    if (data == null) return null;
-    data = JSArray.markFixedList(data);
-
-    int requiredParametersInfo =
-        JS('int', '#[#]', data, REQUIRED_PARAMETERS_INFO);
-    int requiredParameterCount = JS('int', '# >> 2', requiredParametersInfo);
-    bool isAccessor = (requiredParametersInfo & 2) == 2;
-
-    int optionalParametersInfo =
-        JS('int', '#[#]', data, OPTIONAL_PARAMETERS_INFO);
-    int optionalParameterCount = JS('int', '# >> 1', optionalParametersInfo);
-    bool areOptionalParametersNamed = (optionalParametersInfo & 1) == 1;
-
-    var functionType = JS('', '#[#]', data, FUNCTION_TYPE_INDEX);
-    return new ReflectionInfo.internal(
-        jsFunction,
-        data,
-        isAccessor,
-        requiredParameterCount,
-        optionalParameterCount,
-        areOptionalParametersNamed,
-        functionType);
-  }
-
-  String parameterName(int parameter) {
-    int metadataIndex;
-    if (JS_GET_FLAG('MUST_RETAIN_METADATA')) {
-      metadataIndex = JS('int', '#[2 * # + # + #]', data, parameter,
-          optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
-    } else {
-      metadataIndex = JS('int', '#[# + # + #]', data, parameter,
-          optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
-    }
-    var name = getMetadata(metadataIndex);
-    return JS('String', '#', name);
-  }
-
-  List<int> parameterMetadataAnnotations(int parameter) {
-    if (!JS_GET_FLAG('MUST_RETAIN_METADATA')) {
-      throw new StateError('metadata has not been preserved');
-    } else {
-      return JS('', '#[2 * # + # + # + 1]', data, parameter,
-          optionalParameterCount, FIRST_DEFAULT_ARGUMENT);
-    }
-  }
-
-  int defaultValue(int parameter) {
-    if (parameter < requiredParameterCount) return null;
-    return JS('int', '#[# + # - #]', data, FIRST_DEFAULT_ARGUMENT, parameter,
-        requiredParameterCount);
-  }
-
-  /// Returns the default value of the [parameter]th entry of the list of
-  /// parameters sorted by name.
-  int defaultValueInOrder(int parameter) {
-    if (parameter < requiredParameterCount) return null;
-
-    if (!areOptionalParametersNamed || optionalParameterCount == 1) {
-      return defaultValue(parameter);
-    }
-
-    int index = sortedIndex(parameter - requiredParameterCount);
-    return defaultValue(index);
-  }
-
-  /// Returns the default value of the [parameter]th entry of the list of
-  /// parameters sorted by name.
-  String parameterNameInOrder(int parameter) {
-    if (parameter < requiredParameterCount) return null;
-
-    if (!areOptionalParametersNamed || optionalParameterCount == 1) {
-      return parameterName(parameter);
-    }
-
-    int index = sortedIndex(parameter - requiredParameterCount);
-    return parameterName(index);
-  }
-
-  /// Computes the index of the parameter in the list of named parameters sorted
-  /// by their name.
-  int sortedIndex(int unsortedIndex) {
-    if (cachedSortedIndices == null) {
-      // TODO(karlklose): cache this between [ReflectionInfo] instances or cache
-      // [ReflectionInfo] instances by [jsFunction].
-      cachedSortedIndices = new List(optionalParameterCount);
-      Map<String, int> positions = <String, int>{};
-      for (int i = 0; i < optionalParameterCount; i++) {
-        int index = requiredParameterCount + i;
-        positions[parameterName(index)] = index;
-      }
-      int index = 0;
-      (positions.keys.toList()..sort()).forEach((String name) {
-        cachedSortedIndices[index++] = positions[name];
-      });
-    }
-    return cachedSortedIndices[unsortedIndex];
-  }
-
-  @NoInline()
-  computeFunctionRti(jsConstructor) {
-    if (JS('bool', 'typeof # == "number"', functionType)) {
-      return getType(functionType);
-    } else if (JS('bool', 'typeof # == "function"', functionType)) {
-      if (jsConstructor != null) {
-        var fakeInstance = JS('', 'new #()', jsConstructor);
-        setRuntimeTypeInfo(
-            fakeInstance, JS('JSExtendableArray', '#["<>"]', fakeInstance));
-        return JS('=Object|Null', r'#.apply({$receiver:#})', functionType,
-            fakeInstance);
-      }
-      return functionType;
-    } else {
-      throw new RuntimeError('Unexpected function type');
-    }
-  }
-
-  String get reflectionName => JS('String', r'#.$reflectionName', jsFunction);
-}
-
 class Primitives {
   static int objectHashCode(object) {
     int hash = JS('int|Null', r'#.$identityHash', object);
@@ -2196,14 +2035,7 @@
     // This variable holds either an index into the types-table, or a function
     // that can compute a function-rti. (The latter is necessary if the type
     // is dependent on generic arguments).
-    var functionType;
-    if (reflectionInfo is List) {
-      JS('', '#.\$reflectionInfo = #', function, reflectionInfo);
-      ReflectionInfo info = new ReflectionInfo(function);
-      functionType = info.functionType;
-    } else {
-      functionType = reflectionInfo;
-    }
+    var functionType = reflectionInfo;
 
     // function tmp() {};
     // tmp.prototype = BC.prototype;
@@ -3353,7 +3185,10 @@
 String _computeCspNonce() {
   var currentScript = JS_EMBEDDED_GLOBAL('', CURRENT_SCRIPT);
   if (currentScript == null) return null;
-  return JS('String', 'String(#.nonce)', currentScript);
+  String nonce = JS('String|Null', '#.nonce', currentScript);
+  return (nonce != null && nonce != '')
+      ? nonce
+      : JS('String|Null', '#.getAttribute("nonce")', currentScript);
 }
 
 /// The 'crossOrigin' value on the current script used for CORS, if any.
@@ -3509,6 +3344,7 @@
     JS('', '#.src = #', script, uri);
     if (_cspNonce != null && _cspNonce != '') {
       JS('', '#.nonce = #', script, _cspNonce);
+      JS('', '#.setAttribute("nonce", #)', script, _cspNonce);
     }
     if (_crossOrigin != null && _crossOrigin != '') {
       JS('', '#.crossOrigin = #', script, _crossOrigin);
diff --git a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
index 5e1c046..58a9e90 100644
--- a/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
+++ b/sdk/lib/_internal/sdk_library_metadata/lib/libraries.dart
@@ -63,6 +63,11 @@
       categories: "Client,Server,Embedded",
       maturity: Maturity.UNSTABLE,
       dart2jsPatchPath: "_internal/js_runtime/lib/developer_patch.dart"),
+  "ffi": const LibraryInfo("ffi/ffi.dart",
+      categories: "Server",
+      // TODO(dacoharkes): Update maturity when we release dart:ffi.
+      // https://github.com/dart-lang/sdk/issues/34452
+      maturity: Maturity.EXPERIMENTAL),
   "html": const LibraryInfo("html/dart2js/html_dart2js.dart",
       categories: "Client",
       maturity: Maturity.WEB_STABLE,
diff --git a/sdk/lib/core/map.dart b/sdk/lib/core/map.dart
index 42b606a..0c2f586 100644
--- a/sdk/lib/core/map.dart
+++ b/sdk/lib/core/map.dart
@@ -358,7 +358,7 @@
    *
    * The values are iterated in the order of their corresponding keys.
    * This means that iterating [keys] and [values] in parallel will
-   * provided matching pairs of keys and values.
+   * provide matching pairs of keys and values.
    *
    * The returned iterable has an efficient `length` method based on the
    * [length] of the map. Its [Iterable.contains] method is based on
diff --git a/sdk/lib/developer/timeline.dart b/sdk/lib/developer/timeline.dart
index 4853f4a..b3075bf 100644
--- a/sdk/lib/developer/timeline.dart
+++ b/sdk/lib/developer/timeline.dart
@@ -8,7 +8,7 @@
     const bool.fromEnvironment("dart.developer.timeline", defaultValue: true);
 
 /// A typedef for the function argument to [Timeline.timeSync].
-typedef dynamic TimelineSyncFunction();
+typedef TimelineSyncFunction<T> = T Function();
 
 // TODO: This typedef is not used.
 typedef Future TimelineAsyncFunction();
@@ -154,7 +154,7 @@
 
   /// A utility method to time a synchronous [function]. Internally calls
   /// [function] bracketed by calls to [startSync] and [finishSync].
-  static dynamic timeSync(String name, TimelineSyncFunction function,
+  static T timeSync<T>(String name, TimelineSyncFunction<T> function,
       {Map arguments, Flow flow}) {
     startSync(name, arguments: arguments, flow: flow);
     try {
diff --git a/sdk/lib/ffi/annotations.dart b/sdk/lib/ffi/annotations.dart
new file mode 100644
index 0000000..24401e6
--- /dev/null
+++ b/sdk/lib/ffi/annotations.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.
+
+part of dart.ffi;
+
+class Struct {
+  const Struct();
+}
+
+/// This Dart class represents a C struct.
+///
+/// Fields in this struct, annotated with a subtype of [NativeType], are
+/// automatically transformed into wrappers to access the fields of the struct
+/// in C memory.
+///
+/// Fields without a [NativeType] annotation are not supported.
+const struct = const Struct();
+
+class DartRepresentationOf {
+  /// Represents the Dart type corresponding to a [NativeType].
+  ///
+  /// [Int8]                               -> [int]
+  /// [Int16]                              -> [int]
+  /// [Int32]                              -> [int]
+  /// [Int64]                              -> [int]
+  /// [Uint8]                              -> [int]
+  /// [Uint16]                             -> [int]
+  /// [Uint32]                             -> [int]
+  /// [Uint64]                             -> [int]
+  /// [IntPtr]                             -> [int]
+  /// [Double]                             -> [double]
+  /// [Float]                              -> [double]
+  /// [Pointer]<T>                         -> [Pointer]<T>
+  /// T extends [Pointer]                  -> T
+  /// [NativeFunction]<T1 Function(T2, T3) -> S1 Function(S2, S3)
+  ///    where DartRepresentationOf(Tn) -> Sn
+  const DartRepresentationOf(String nativeType);
+}
+
+class Unsized {
+  const Unsized();
+}
+
+/// This [NativeType] does not have predefined size.
+///
+/// Unsized NativeTypes do not support [sizeOf] because their size is unknown.
+/// Consequently, [allocate], [Pointer.load], [Pointer.store], and
+/// [Pointer.elementAt] are not available.
+const unsized = const Unsized();
diff --git a/sdk/lib/ffi/dynamic_library.dart b/sdk/lib/ffi/dynamic_library.dart
new file mode 100644
index 0000000..98aa64a
--- /dev/null
+++ b/sdk/lib/ffi/dynamic_library.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.ffi;
+
+/// Represents a dynamically loaded C library.
+class DynamicLibrary {
+  /// Loads a dynamic library file. This is the equivalent of dlopen.
+  ///
+  /// Throws an [ArgumentError] if loading the dynamic library fails.
+  ///
+  /// Note that it loads the functions in the library lazily (RTLD_LAZY).
+  external factory DynamicLibrary.open(String name);
+
+  /// Looks up a symbol in the [DynamicLibrary] and returns its address in
+  /// memory. Equivalent of dlsym.
+  ///
+  /// Throws an [ArgumentError] if it fails to lookup the symbol.
+  external Pointer<T> lookup<T extends NativeType>(String symbolName);
+
+  /// Helper that combines lookup and cast to a Dart function.
+  F lookupFunction<T extends Function, F extends Function>(String symbolName) {
+    return lookup<NativeFunction<T>>(symbolName)?.asFunction<F>();
+  }
+
+  /// Dynamic libraries are equal if they load the same library.
+  external bool operator ==(other);
+
+  /// The hash code for a DynamicLibrary only depends on the loaded library
+  external int get hashCode;
+}
diff --git a/sdk/lib/ffi/ffi.dart b/sdk/lib/ffi/ffi.dart
new file mode 100644
index 0000000..407cc12
--- /dev/null
+++ b/sdk/lib/ffi/ffi.dart
@@ -0,0 +1,102 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file
+
+library dart.ffi;
+
+part "native_type.dart";
+part "annotations.dart";
+part "dynamic_library.dart";
+
+/// Allocate [count] elements of type [T] on the C heap with malloc() and return
+/// a pointer to the newly allocated memory.
+///
+/// Note that the memory are uninitialized.
+///
+/// TODO(dacoharkes): change signature to T allocate<T extends Pointer>() ?
+/// This would enable us to allocate structs. However how do we know the size of
+/// structs? https://github.com/dart-lang/sdk/issues/35782
+external Pointer<T> allocate<T extends NativeType>({int count: 1});
+
+/// Construction from raw value
+external T fromAddress<T extends Pointer>(int ptr);
+
+/// number of bytes used by native type T
+external int sizeOf<T extends NativeType>();
+
+/// Convert Dart function to a C function pointer, automatically marshalling
+/// the arguments and return value
+///
+/// Note: this is not implemented, always returns Pointer with address 0.
+///
+/// TODO(dacoharkes): Implement this feature.
+/// https://github.com/dart-lang/sdk/issues/35761
+external Pointer<NativeFunction<T>> fromFunction<T extends Function>(
+    @DartRepresentationOf("T") Function f);
+
+/*
+/// TODO(dacoharkes): Implement this feature.
+/// https://github.com/dart-lang/sdk/issues/35770
+/// Return a pointer object that has a finalizer attached to it. When this
+/// pointer object is collected by GC the given finalizer is invoked.
+///
+/// Note: the pointer object passed to the finalizer is not the same as
+/// the pointer object that is returned from [finalizable] - it points
+/// to the same memory region but has different identity.
+external Pointer<T> finalizable<T extends NativeType>(
+    Pointer<T> p, void finalizer(Pointer<T> ptr));
+*/
+
+/// Represents a pointer into the native C memory.
+class Pointer<T extends NativeType> extends NativeType {
+  const Pointer();
+
+  /// Store a Dart value into this location.
+  ///
+  /// The [value] is automatically marshalled into its C representation.
+  /// Note that ints which do not fit in [T] are truncated and sign extended,
+  /// and doubles stored into Pointer<[Float]> lose precision.
+  external void store(@DartRepresentationOf("T") Object value);
+
+  /// Load a Dart value from this location.
+  ///
+  /// The value is automatically unmarshalled from its C representation.
+  external R load<@DartRepresentationOf("T") R>();
+
+  /// Access to the raw pointer value.
+  external int get address;
+
+  /// Pointer arithmetic (takes element size into account).
+  external Pointer<T> elementAt(int index);
+
+  /// Pointer arithmetic (byte offset).
+  ///
+  /// TODO(dacoharkes): remove this?
+  /// https://github.com/dart-lang/sdk/issues/35883
+  external Pointer<T> offsetBy(int offsetInBytes);
+
+  /// Cast Pointer<T> to a (subtype of) Pointer<V>.
+  external U cast<U extends Pointer>();
+
+  /// Convert to Dart function, automatically marshalling the arguments
+  /// and return value.
+  ///
+  /// Can only be called on [Pointer]<[NativeFunction]>.
+  external R asFunction<@DartRepresentationOf("T") R extends Function>();
+
+  /// Free memory on the C heap pointed to by this pointer with free().
+  ///
+  /// Note that this zeros out the address.
+  external void free();
+
+  /// Equality for Pointers only depends on their address.
+  bool operator ==(other) {
+    if (other == null) return false;
+    return address == other.address;
+  }
+
+  /// The hash code for a Pointer only depends on its address.
+  int get hashCode {
+    return address.hashCode;
+  }
+}
diff --git a/sdk/lib/ffi/ffi_sources.gni b/sdk/lib/ffi/ffi_sources.gni
new file mode 100644
index 0000000..d67b267
--- /dev/null
+++ b/sdk/lib/ffi/ffi_sources.gni
@@ -0,0 +1,12 @@
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+ffi_sdk_sources = [
+  "ffi.dart",
+
+  # The above file needs to be first as it lists the parts below.
+  "annotations.dart",
+  "dynamic_library.dart",
+  "native_type.dart"
+]
diff --git a/sdk/lib/ffi/native_type.dart b/sdk/lib/ffi/native_type.dart
new file mode 100644
index 0000000..61f9cde
--- /dev/null
+++ b/sdk/lib/ffi/native_type.dart
@@ -0,0 +1,133 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+part of dart.ffi;
+
+/// [NativeType]'s subtypes represent a native type in C.
+///
+/// [NativeType]'s subtypes are not constructible in the Dart code and serve
+/// purely as markers in type signatures.
+class NativeType {
+  const NativeType();
+}
+
+/// [_NativeInteger]'s subtypes represent a native integer in C.
+///
+/// [_NativeInteger]'s subtypes are not constructible in the Dart code and serve
+/// purely as markers in type signatures.
+class _NativeInteger extends NativeType {
+  const _NativeInteger();
+}
+
+/// [_NativeDouble]'s subtypes represent a native float or double in C.
+///
+/// [_NativeDouble]'s subtypes are not constructible in the Dart code and serve
+/// purely as markers in type signatures.
+class _NativeDouble extends NativeType {
+  const _NativeDouble();
+}
+
+/// Represents a native signed 8 bit integer in C.
+///
+/// [Int8] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+class Int8 extends _NativeInteger {
+  const Int8();
+}
+
+/// Represents a native signed 16 bit integer in C.
+///
+/// [Int16] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+class Int16 extends _NativeInteger {
+  const Int16();
+}
+
+/// Represents a native signed 32 bit integer in C.
+///
+/// [Int32] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+class Int32 extends _NativeInteger {
+  const Int32();
+}
+
+/// Represents a native signed 64 bit integer in C.
+///
+/// [Int64] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+class Int64 extends _NativeInteger {
+  const Int64();
+}
+
+/// Represents a native unsigned 8 bit integer in C.
+///
+/// [Uint8] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+class Uint8 extends _NativeInteger {
+  const Uint8();
+}
+
+/// Represents a native unsigned 16 bit integer in C.
+///
+/// [Uint16] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Uint16 extends _NativeInteger {
+  const Uint16();
+}
+
+/// Represents a native unsigned 32 bit integer in C.
+///
+/// [Uint32] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Uint32 extends _NativeInteger {
+  const Uint32();
+}
+
+/// Represents a native unsigned 64 bit integer in C.
+///
+/// [Uint64] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Uint64 extends _NativeInteger {
+  const Uint64();
+}
+
+/// Represents a native pointer-sized integer in C.
+///
+/// [IntPtr] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class IntPtr extends _NativeInteger {
+  const IntPtr();
+}
+
+/// Represents a native 32 bit float in C.
+///
+/// [Float] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Float extends _NativeDouble {
+  const Float();
+}
+
+/// Represents a native 64 bit double in C.
+///
+/// [Double] is not constructible in the Dart code and serves purely as marker
+/// in type signatures.
+class Double extends _NativeDouble {
+  const Double();
+}
+
+/// Represents a void type in C.
+///
+/// [Void] is not constructible in the Dart code and serves purely as marker in
+/// type signatures.
+@unsized
+class Void extends NativeType {
+  const Void();
+}
+
+/// Represents a function type in C.
+///
+/// [NativeFunction] is not constructible in the Dart code and serves purely as
+/// marker in type signatures.
+@unsized
+class NativeFunction<T extends Function> extends NativeType {}
diff --git a/sdk/lib/libraries.json b/sdk/lib/libraries.json
index db0bf0c..9b239ff 100644
--- a/sdk/lib/libraries.json
+++ b/sdk/lib/libraries.json
@@ -63,6 +63,14 @@
         ],
         "uri": "collection/collection.dart"
       },
+      "ffi": {
+        "patches": [
+          "../../runtime/lib/ffi_dynamic_library_patch.dart",
+          "../../runtime/lib/ffi_native_type_patch.dart",
+          "../../runtime/lib/ffi_patch.dart"
+        ],
+        "uri": "ffi/ffi.dart"
+      },
       "typed_data": {
         "patches": "../../runtime/lib/typed_data_patch.dart",
         "uri": "typed_data/typed_data.dart"
diff --git a/sdk/lib/libraries.yaml b/sdk/lib/libraries.yaml
index e2d0f7c..a53b69a 100644
--- a/sdk/lib/libraries.yaml
+++ b/sdk/lib/libraries.yaml
@@ -87,6 +87,13 @@
         - "../../runtime/lib/profiler.dart"
         - "../../runtime/lib/timeline.dart"
 
+    ffi:
+      uri: "ffi/ffi.dart"
+      patches:
+        - "../../runtime/lib/ffi_dynamic_library_patch.dart"
+        - "../../runtime/lib/ffi_native_type_patch.dart"
+        - "../../runtime/lib/ffi_patch.dart"
+
     _http:
       uri: "_http/http.dart"
 
diff --git a/tests/co19_2/co19_2-analyzer.status b/tests/co19_2/co19_2-analyzer.status
index 9de243e..108c0ed 100644
--- a/tests/co19_2/co19_2-analyzer.status
+++ b/tests/co19_2/co19_2-analyzer.status
@@ -3,15 +3,15 @@
 # BSD-style license that can be found in the LICENSE file.
 
 [ $compiler == dart2analyzer ]
-Language/Classes/Abstract_Instance_Members/override_default_value_t01: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/override_default_value_t02: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/override_default_value_t03: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/override_default_value_t04: MissingCompileTimeError # Issue 33995
-Language/Classes/Abstract_Instance_Members/override_default_value_t05: MissingCompileTimeError # Issue 33995
+Language/Classes/Abstract_Instance_Members/override_default_value_t01: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
+Language/Classes/Abstract_Instance_Members/override_default_value_t02: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
+Language/Classes/Abstract_Instance_Members/override_default_value_t03: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
+Language/Classes/Abstract_Instance_Members/override_default_value_t04: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
+Language/Classes/Abstract_Instance_Members/override_default_value_t05: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
 Language/Classes/Getters/type_object_t01: CompileTimeError # Issue 33995
 Language/Classes/Getters/type_object_t02: CompileTimeError # Issue 33995
-Language/Classes/Instance_Methods/override_different_default_values_t01: MissingCompileTimeError # Issue 33995
-Language/Classes/Instance_Methods/override_different_default_values_t02: MissingCompileTimeError # Issue 33995
+Language/Classes/Instance_Methods/override_different_default_values_t01: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
+Language/Classes/Instance_Methods/override_different_default_values_t02: MissingCompileTimeError # https://github.com/dart-lang/co19/issues/234
 Language/Classes/Static_Methods/same_name_method_and_setter_t01: CompileTimeError # Invalid test, see #33237
 Language/Classes/method_definition_t06: MissingCompileTimeError # Please triage this failure
 Language/Enums/syntax_t08: CompileTimeError # Issue 33995
diff --git a/tests/co19_2/co19_2-dart2js.status b/tests/co19_2/co19_2-dart2js.status
index a5c9730..a4d8adc 100644
--- a/tests/co19_2/co19_2-dart2js.status
+++ b/tests/co19_2/co19_2-dart2js.status
@@ -14,3 +14,322 @@
 LayoutTests/*: SkipByDesign # d8 is not a browser
 LibTest/html/*: SkipByDesign # d8 is not a browser
 WebPlatformTest/*: SkipByDesign # d8 is not a browser
+
+[ $compiler == dartdevc || $compiler == dartdevk ]
+Language/Classes/Constructors/Generative_Constructors/formal_parameter_t07: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/fresh_instance_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/implicit_superinitializer_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/implicit_superinitializer_t02: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/initializers_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/initializers_t15: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/initializing_formals_execution_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/initializing_this_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/redirection_t01: Skip # Times out
+Language/Classes/Constructors/Generative_Constructors/syntax_t01: Skip # Times out
+Language/Classes/Constructors/implicit_constructor_t01: Skip # Times out
+Language/Classes/Constructors/implicit_constructor_t02: Skip # Times out
+Language/Classes/Constructors/name_t01: Skip # Times out
+Language/Classes/Constructors/name_t02: Skip # Times out
+Language/Classes/Constructors/name_t03: Skip # Times out
+Language/Classes/Getters/instance_getter_t01: Skip # Times out
+Language/Classes/Getters/instance_getter_t02: Skip # Times out
+Language/Classes/Getters/instance_getter_t03: Skip # Times out
+Language/Classes/Getters/instance_getter_t04: Skip # Times out
+Language/Classes/Getters/instance_getter_t05: Skip # Times out
+Language/Classes/Getters/instance_getter_t06: Skip # Times out
+Language/Classes/Getters/override_t04: Skip # Times out
+Language/Classes/Getters/return_type_t01: Skip # Times out
+Language/Classes/Getters/static_t01/none: Skip # Times out
+Language/Classes/Getters/static_t02: Skip # Times out
+Language/Classes/Getters/syntax_t01: Skip # Times out
+Language/Classes/Getters/void_return_type_t01: Skip # Times out
+Language/Classes/Instance_Methods/Operators/allowed_names_t01: Skip # Times out
+Language/Classes/Instance_Methods/Operators/arity_0_or_1_t01: Skip # Times out
+Language/Classes/Instance_Methods/Operators/arity_0_t01: Skip # Times out
+Language/Classes/Instance_Methods/Operators/syntax_t01: Skip # Times out
+Language/Classes/Instance_Methods/Operators/syntax_t03: Skip # Times out
+Language/Classes/Instance_Methods/override_named_parameters_t03: Skip # Times out
+Language/Classes/Instance_Methods/override_named_parameters_t04: Skip # Times out
+Language/Classes/Instance_Methods/override_named_parameters_t06: Skip # Times out
+Language/Classes/Instance_Methods/override_subtype_t05: Skip # Times out
+Language/Classes/Instance_Methods/override_subtype_t06: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t01: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t02: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t04: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t05: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t06: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t07: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t08: Skip # Times out
+Language/Classes/Instance_Methods/same_name_static_member_in_superclass_t09: Skip # Times out
+Language/Classes/Instance_Variables/definition_t01: Skip # Times out
+Language/Classes/Instance_Variables/definition_t02: Skip # Times out
+Language/Classes/Instance_Variables/definition_t04: Skip # Times out
+Language/Classes/Setters/instance_setter_t01: Skip # Times out
+Language/Expressions/Function_Invocation/async_generator_invokation_t08: Skip # Times out
+Language/Expressions/Function_Invocation/async_generator_invokation_t10: Skip # Times out
+Language/Types/Interface_Types/subtype_t27: Skip # Times out
+Language/Types/Interface_Types/subtype_t28: Skip # Times out
+LayoutTests/fast/backgrounds/001_t01: Skip # Times out
+LayoutTests/fast/backgrounds/animated-gif-as-background_t01: Skip # Times out
+LayoutTests/fast/backgrounds/multiple-backgrounds-assert_t01: Skip # Times out
+LayoutTests/fast/canvas/2d.text.draw.fill.maxWidth.gradient_t01: Skip # Times out
+LayoutTests/fast/canvas/DrawImageSinglePixelStretch_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-before-css_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-composite-alpha_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-composite-canvas_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-composite-image_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-composite-stroke-alpha_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-composite-text-alpha_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-css-crazy_t01: Skip # Times out
+LayoutTests/fast/canvas/canvas-imageSmoothingEnabled-repaint_t01: Skip # Times out
+LayoutTests/fast/canvas/drawImage-with-valid-image_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/canvas-resize-crash_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/gl-teximage_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgb565_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba4444_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image-rgba5551_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-image_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgb565_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba4444_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video-rgba5551_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/tex-image-and-sub-image-2d-with-video_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/texture-color-profile_t01: Skip # Times out
+LayoutTests/fast/canvas/webgl/texture-transparent-pixels-initialized_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/bug91547_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/inline-splitting-with-after-float-crash_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/pseudo-animation-before-onload_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/pseudo-animation-display_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/pseudo-animation_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/pseudo-element-events_t01: Skip # Times out
+LayoutTests/fast/css-generated-content/pseudo-transition-event_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/auto-content-resolution-rows_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/breadth-size-resolution-grid_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/calc-resolution-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/display-grid-set-get_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/flex-and-minmax-content-resolution-rows_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/flex-content-resolution-columns_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/flex-content-resolution-rows_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-auto-columns-rows-get-set_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-auto-flow-get-set_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-auto-flow-update_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-container-change-explicit-grid-recompute-child_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-bad-cast-addchild_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-border-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-border-padding-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-empty-row-column_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-min-max-height_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-padding-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-padding-margin_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-remove-svg-child_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-element-shrink-to-fit_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-area-get-set_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-bad-named-area-auto-placement_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-bad-resolution-double-span_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-change-order-auto-flow_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-display_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-horiz-bt_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-vert-lr_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows-vert-rl_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-margin-auto-columns-rows_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-margin-resolution_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-item-order-auto-flow-resolution_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-strict-ordering-crash_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/grid-template-areas-get-set_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/implicit-rows-auto-resolution_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/justify-self-cell_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/minmax-fixed-logical-height-only_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/minmax-fixed-logical-width-only_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-in-percent-grid_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track-update_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-grid-item-in-percent-grid-track_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item-update_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-padding-margin-resolution-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/percent-resolution-grid-item_t01: Skip # Times out
+LayoutTests/fast/css-grid-layout/place-cell-by-index_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/css-tables_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-absolutes_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-blocks_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-column-flex-items_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-flex-items_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/intrinsic-sized-replaced-absolutes_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/tables_t01: Skip # Times out
+LayoutTests/fast/css-intrinsic-dimensions/width-shrinks-avoid-floats_t01: Skip # Times out
+LayoutTests/fast/css/cached-sheet-restore-crash_t01: Skip # Times out
+LayoutTests/fast/css/comment-before-charset-external_t01: Skip # Times out
+LayoutTests/fast/css/comment-before-charset_t01: Skip # Times out
+LayoutTests/fast/css/counters/asterisk-counter-update-after-layout-crash_t01: Skip # Times out
+LayoutTests/fast/css/counters/complex-before_t01: Skip # Times out
+LayoutTests/fast/css/counters/counter-before-selector-crash_t01: Skip # Times out
+LayoutTests/fast/css/counters/counter-reparent-table-children-crash_t01: Skip # Times out
+LayoutTests/fast/css/counters/counter-reset-subtree-insert-crash_t01: Skip # Times out
+LayoutTests/fast/css/counters/counter-ruby-text-cleared_t01: Skip # Times out
+LayoutTests/fast/css/counters/counter-traverse-object-crash_t01: Skip # Times out
+LayoutTests/fast/css/font-face-svg-decoding-error_t01: Skip # Times out
+LayoutTests/fast/css/font-face-unicode-range-overlap-load_t01: Skip # Times out
+LayoutTests/fast/css/implicit-attach-marking_t01: Skip # Times out
+LayoutTests/fast/css/link-alternate-stylesheet-1_t01: Skip # Times out
+LayoutTests/fast/css/link-alternate-stylesheet-2_t01: Skip # Times out
+LayoutTests/fast/css/link-alternate-stylesheet-3_t01: Skip # Times out
+LayoutTests/fast/css/link-alternate-stylesheet-4_t01: Skip # Times out
+LayoutTests/fast/css/link-alternate-stylesheet-5_t01: Skip # Times out
+LayoutTests/fast/css/link-disabled-attr-parser_t01: Skip # Times out
+LayoutTests/fast/css/nested-at-rules_t01: Skip # Times out
+LayoutTests/fast/css/percent-min-width-img-src-change_t01: Skip # Times out
+LayoutTests/fast/css/percent-width-img-src-change_t01: Skip # Times out
+LayoutTests/fast/css/pseudo-target-indirect-sibling-001_t01: Skip # Times out
+LayoutTests/fast/css/pseudo-target-indirect-sibling-002_t01: Skip # Times out
+LayoutTests/fast/css/remove-fixed-resizer-crash_t01: Skip # Times out
+LayoutTests/fast/css/sheet-collection-link_t01: Skip # Times out
+LayoutTests/fast/css/sheet-title_t01: Skip # Times out
+LayoutTests/fast/css/space-before-charset-external_t01: Skip # Times out
+LayoutTests/fast/css/space-before-charset_t01: Skip # Times out
+LayoutTests/fast/css/sticky/remove-inline-sticky-crash_t01: Skip # Times out
+LayoutTests/fast/css/sticky/remove-sticky-crash_t01: Skip # Times out
+LayoutTests/fast/css/sticky/sticky-table-col-crash_t01: Skip # Times out
+LayoutTests/fast/css/style-element-process-crash_t01: Skip # Times out
+LayoutTests/fast/css/stylesheet-enable-first-alternate-link_t01: Skip # Times out
+LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-link_t01: Skip # Times out
+LayoutTests/fast/css/stylesheet-enable-first-alternate-on-load-sheet_t01: Skip # Times out
+LayoutTests/fast/css/stylesheet-enable-second-alternate-link_t01: Skip # Times out
+LayoutTests/fast/css/stylesheet-parentStyleSheet_t01: Skip # Times out
+LayoutTests/fast/css/webkit-keyframes-crash_t01: Skip # Times out
+LayoutTests/fast/css/webkit-marquee-speed-unit-in-quirksmode_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLDocument/active-element-gets-unforcusable_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLDocument/set-focus-on-valid-element_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLImageElement/image-loading-gc_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLImageElement/image-natural-width-height_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/link-and-subresource-test_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/link-beforeload-recursive_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/link-onload-before-page-load_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/link-onload2_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/onload-completion-test_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/prefetch-onload_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLLinkElement/prefetch_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLObjectElement/beforeload-set-text-crash_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLObjectElement/set-type-to-null-crash_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/async-false-inside-async-false-load_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/async-onbeforeload_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/defer-onbeforeload_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/defer-script-invalid-url_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/dont-load-unknown-type_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/remove-in-beforeload_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/remove-source_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/script-for-attribute-unexpected-execution_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/script-load-events_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/script-reexecution_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLScriptElement/script-set-src_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLStyleElement/style-onload-before-page-load_t01: Skip # Times out
+LayoutTests/fast/dom/HTMLTemplateElement/innerHTML-inert_t01: Skip # Times out
+LayoutTests/fast/dom/SelectorAPI/bug-17313_t01: Skip # Times out
+LayoutTests/fast/dom/StyleSheet/detached-style-2_t01: Skip # Times out
+LayoutTests/fast/dom/StyleSheet/detached-style_t01: Skip # Times out
+LayoutTests/fast/dom/StyleSheet/discarded-sheet-owner-null_t01: Skip # Times out
+LayoutTests/fast/dom/css-cached-import-rule_t01: Skip # Times out
+LayoutTests/fast/dom/css-insert-import-rule-twice_t01: Skip # Times out
+LayoutTests/fast/dom/css-insert-import-rule_t01: Skip # Times out
+LayoutTests/fast/dom/css-mediarule-deleteRule-update_t01: Skip # Times out
+LayoutTests/fast/dom/css-mediarule-insertRule-update_t01: Skip # Times out
+LayoutTests/fast/dom/domtimestamp-is-number_t01: Skip # Times out
+LayoutTests/fast/dom/empty-hash-and-search_t01: Skip # Times out
+LayoutTests/fast/dom/gc-image-element-2_t01: Skip # Times out
+LayoutTests/fast/dom/gc-image-element_t01: Skip # Times out
+LayoutTests/fast/dom/horizontal-scrollbar-in-rtl_t01: Skip # Times out
+LayoutTests/fast/dom/horizontal-scrollbar-when-dir-change_t01: Skip # Times out
+LayoutTests/fast/dom/icon-url-change_t01: Skip # Times out
+LayoutTests/fast/dom/icon-url-list_t01: Skip # Times out
+LayoutTests/fast/dom/id-attribute-with-namespace-crash_t01: Skip # Times out
+LayoutTests/fast/dom/image-object_t01: Skip # Times out
+LayoutTests/fast/dom/inner-text_t01: Skip # Times out
+LayoutTests/fast/dom/shadow/insertion-point-list-menu-crash_t01: Skip # Times out
+LayoutTests/fast/dom/shadow/insertion-point-video-crash_t01: Skip # Times out
+LayoutTests/fast/dom/shadow/link-in-shadow-tree_t01: Skip # Times out
+LayoutTests/fast/dom/shadow/no-renderers-for-light-children_t01: Skip # Times out
+LayoutTests/fast/dom/text-node-attach-crash_t01: Skip # Times out
+LayoutTests/fast/dom/vertical-scrollbar-when-dir-change_t01: Skip # Times out
+LayoutTests/fast/dynamic/continuation-detach-crash_t01: Skip # Times out
+LayoutTests/fast/events/change-overflow-on-overflow-change_t01: Skip # Times out
+LayoutTests/fast/events/clipboard-clearData_t01: Skip # Times out
+LayoutTests/fast/events/clipboard-dataTransferItemList_t01: Skip # Times out
+LayoutTests/fast/events/dispatch-event-being-dispatched_t01: Skip # Times out
+LayoutTests/fast/events/document-elementFromPoint_t01: Skip # Times out
+LayoutTests/fast/events/nested-event-remove-node-crash_t01: Skip # Times out
+LayoutTests/fast/events/no-window-load_t01: Skip # Times out
+LayoutTests/fast/events/overflowchanged-event-raf-timing_t01: Skip # Times out
+LayoutTests/fast/events/tabindex-removal-from-focused-element_t01: Skip # Times out
+LayoutTests/fast/events/window-load-capture_t01: Skip # Times out
+LayoutTests/fast/flexbox/crash-flexbox-no-layout-child_t01: Skip # Times out
+LayoutTests/fast/flexbox/layoutHorizontalBox-crash_t01: Skip # Times out
+LayoutTests/fast/flexbox/overhanging-floats-not-removed-crash_t01: Skip # Times out
+LayoutTests/fast/forms/HTMLOptionElement_selected_t01: Skip # Times out
+LayoutTests/fast/forms/activate-and-disabled-elements_t01: Skip # Times out
+LayoutTests/fast/forms/autofocus-focus-only-once_t01: Skip # Times out
+LayoutTests/fast/forms/autofocus-input-css-style-change_t01: Skip # Times out
+LayoutTests/fast/forms/autofocus-opera-007_t01: Skip # Times out
+LayoutTests/fast/forms/autofocus-readonly-attribute_t01: Skip # Times out
+LayoutTests/fast/forms/button/button-disabled-blur_t01: Skip # Times out
+LayoutTests/fast/forms/focus-style-pending_t01: Skip # Times out
+LayoutTests/fast/forms/form-added-to-table_t01: Skip # Times out
+LayoutTests/fast/forms/input-type-change_t01: Skip # Times out
+LayoutTests/fast/forms/input-width-height-attributes-without-renderer-loaded-image_t01: Skip # Times out
+LayoutTests/fast/forms/input-width-height-attributes-without-renderer_t01: Skip # Times out
+LayoutTests/fast/forms/search-popup-crasher_t01: Skip # Times out
+LayoutTests/fast/forms/select-change-popup-to-listbox-in-event-handler_t01: Skip # Times out
+LayoutTests/fast/forms/select-generated-content_t01: Skip # Times out
+LayoutTests/fast/forms/textarea-placeholder-relayout-assertion_t01: Skip # Times out
+LayoutTests/fast/forms/textarea-scrollbar-height_t01: Skip # Times out
+LayoutTests/fast/forms/textfield-focus-out_t01: Skip # Times out
+LayoutTests/fast/html/imports/import-element-removed-flag_t01: Skip # Times out
+LayoutTests/fast/loader/about-blank-hash-change_t01: Skip # Times out
+LayoutTests/fast/loader/about-blank-hash-kept_t01: Skip # Times out
+LayoutTests/fast/loader/hashchange-event-async_t01: Skip # Times out
+LayoutTests/fast/loader/hashchange-event-properties_t01: Skip # Times out
+LayoutTests/fast/loader/local-css-allowed-in-strict-mode_t01: Skip # Times out
+LayoutTests/fast/loader/onhashchange-attribute-listeners_t01: Skip # Times out
+LayoutTests/fast/loader/onload-policy-ignore-for-frame_t01: Skip # Times out
+LayoutTests/fast/loader/scroll-position-restored-on-back_t01: Skip # Times out
+LayoutTests/fast/loader/scroll-position-restored-on-reload-at-load-event_t01: Skip # Times out
+LayoutTests/fast/overflow/scroll-vertical-not-horizontal_t01: Skip # Times out
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-anonymous-table-cell_t01: Skip # Times out
+LayoutTests/fast/replaced/iframe-with-percentage-height-within-table-with-table-cell-ignore-height_t01: Skip # Times out
+LayoutTests/fast/replaced/table-percent-height-text-controls_t01: Skip # Times out
+LayoutTests/fast/replaced/table-percent-height_t01: Skip # Times out
+LayoutTests/fast/replaced/table-percent-width_t01: Skip # Times out
+LayoutTests/fast/replaced/table-replaced-element_t01: Skip # Times out
+LayoutTests/fast/speechsynthesis/speech-synthesis-boundary-events_t01: Skip # Times out
+LayoutTests/fast/speechsynthesis/speech-synthesis-speak_t01: Skip # Times out
+LayoutTests/fast/sub-pixel/float-list-inside_t01: Skip # Times out
+LibTest/html/CanvasRenderingContext2D/addEventListener_A01_t03: Skip # Times out
+LibTest/html/Element/blur_A01_t01: Skip # Times out
+LibTest/html/Element/focus_A01_t01: Skip # Times out
+LibTest/html/Element/loadEvent_A01_t01: Skip # Times out
+LibTest/html/Element/mouseWheelEvent_A01_t01: Skip # Times out
+LibTest/html/Element/onLoad_A01_t01: Skip # Times out
+LibTest/html/Element/onMouseWheel_A01_t01: Skip # Times out
+LibTest/html/Element/onTransitionEnd_A01_t01: Skip # Times out
+LibTest/html/Element/transitionEndEvent_A01_t01: Skip # Times out
+LibTest/html/HttpRequest/onError_A01_t02: Skip # Times out
+LibTest/html/HttpRequest/responseText_A01_t02: Skip # Times out
+LibTest/html/HttpRequestUpload/onError_A01_t02: Skip # Times out
+LibTest/html/HttpRequestUpload/onLoadEnd_A01_t01: Skip # Times out
+LibTest/html/HttpRequestUpload/onLoadStart_A01_t01: Skip # Times out
+LibTest/html/HttpRequestUpload/onLoad_A01_t01: Skip # Times out
+LibTest/html/IFrameElement/blur_A01_t01: Skip # Times out
+LibTest/html/IFrameElement/enteredView_A01_t01: Skip # Times out
+LibTest/html/IFrameElement/focus_A01_t01: Skip # Times out
+LibTest/html/IFrameElement/onMouseWheel_A01_t01: Skip # Times out
+LibTest/html/IFrameElement/onTransitionEnd_A01_t01: Skip # Times out
+WebPlatformTest/DOMEvents/approved/ProcessingInstruction.DOMCharacterDataModified_t01: Skip # Times out
+WebPlatformTest/Utils/test/asyncTestTimeout_t01: Skip # Times out
+WebPlatformTest/dom/nodes/Node-isEqualNode_t01: Skip # Times out
+WebPlatformTest/html/semantics/embedded-content/media-elements/error-codes/error_t01: Skip # Times out
+WebPlatformTest/html/semantics/embedded-content/media-elements/interfaces/TextTrack/cues_t01: Skip # Times out
+WebPlatformTest/webstorage/event_local_key_t01: Skip # Times out
+WebPlatformTest/webstorage/event_local_newvalue_t01: Skip # Times out
+WebPlatformTest/webstorage/event_local_oldvalue_t01: Skip # Times out
+WebPlatformTest/webstorage/event_local_storagearea_t01: Skip # Times out
+WebPlatformTest/webstorage/event_local_url_t01: Skip # Times out
+WebPlatformTest/webstorage/event_session_key_t01: Skip # Times out
+WebPlatformTest/webstorage/event_session_newvalue_t01: Skip # Times out
+WebPlatformTest/webstorage/event_session_oldvalue_t01: Skip # Times out
+WebPlatformTest/webstorage/event_session_storagearea_t01: Skip # Times out
+WebPlatformTest/webstorage/event_session_url_t01: Skip # Times out
diff --git a/tests/co19_2/co19_2-kernel.status b/tests/co19_2/co19_2-kernel.status
index 39ea365..717b34e4 100644
--- a/tests/co19_2/co19_2-kernel.status
+++ b/tests/co19_2/co19_2-kernel.status
@@ -2,6 +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.
 
+[ $compiler == dartk ]
+LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
+LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
+
 [ $compiler == dartkp ]
 Language/Expressions/Instance_Creation/New/evaluation_t20: RuntimeError
 Language/Functions/Formal_Parameters/Optional_Formals/default_value_t02: DartkCrash
@@ -26,6 +30,8 @@
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t04: RuntimeError
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t05/none: RuntimeError
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t06/none: RuntimeError
+LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError
+LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
 LanguageFeatures/Subtyping/static/generated/left_bottom_global_variable_A02_t01: DartkCrash
 LanguageFeatures/Subtyping/static/generated/left_promoted_variable_global_variable_A02_t01: DartkCrash
 LibTest/collection/DoubleLinkedQueue/removeWhere_A02_t02: RuntimeError
@@ -68,50 +74,6 @@
 Language/Statements/For/syntax_t20: Crash # Assertion error: kernel_shadow_ast.dart: 'receiver == null': is not true.
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: Crash
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t04: Crash
-LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/03: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t02/04: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A02_t03/03: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A03_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/03: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/04: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/05: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/06: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/07: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/08: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/constant_set_literals_A05_t01/09: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/04: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/05: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/06: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/08: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/semantics_A04_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/semantics_A05_t01: Pass
-LanguageFeatures/Set-literals/semantics_A05_t05/01: MissingCompileTimeError # Exact types
-LanguageFeatures/Set-literals/semantics_A05_t05/02: MissingCompileTimeError # Exact types
-LanguageFeatures/Set-literals/semantics_A05_t05/03: MissingCompileTimeError # Exact types
-LanguageFeatures/Set-literals/set_literals_A01_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/set_literals_A02_t01: Pass # CompileTimeError on $fasta
-LanguageFeatures/Set-literals/set_literals_A04_t02/01: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/02: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/03: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/04: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/05: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/11: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/12: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/set_literals_A04_t02/13: MissingCompileTimeError # Issue 35608
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: Pass # CompileTimeError on $fasta
 
 [ $runtime == vm ]
 LibTest/collection/ListBase/ListBase_class_A01_t02: Pass, Slow # Does many calls
@@ -547,24 +509,16 @@
 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_t01: CompileTimeError # This feature is not implemented yet
-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_A03_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/semantics_A04_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/semantics_A05_t02: RuntimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/set_literals_A01_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/set_literals_A02_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: CompileTimeError # This feature is not implemented yet
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: RuntimeError
+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/exact_types_of_literals_A01_t03: CompileTimeError
+LanguageFeatures/Set-literals/semantics_A05_t01: CompileTimeError
+LanguageFeatures/Set-literals/set_literals_A04_t01: CompileTimeError
 LanguageFeatures/Simple-bounds/dynamic/class_FutureOr_l1_t02: CompileTimeError
 LanguageFeatures/Simple-bounds/static/class_FutureOr_l1_t02/none: CompileTimeError
 LanguageFeatures/Simple-bounds/static/typedef_FutureOr_l1_t02/none: CompileTimeError
@@ -608,15 +562,6 @@
 
 [ $arch == simdbc64 && ($compiler == dartk || $compiler == dartkb) ]
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: CompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/01: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/02: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/03: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/04: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/05: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A02_t04/06: Pass
-LanguageFeatures/Set-literals/constant_set_literals_A04_t01: Pass
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: CompileTimeError
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t02: CompileTimeError
 LibTest/collection/ListBase/ListBase_class_A01_t02: Timeout, Pass # https://github.com/dart-lang/sdk/issues/35316 as well?
 LibTest/collection/ListMixin/ListMixin_class_A01_t02: Timeout, Pass # https://github.com/dart-lang/sdk/issues/35316 as well?
 LibTest/io/Link/renameSync_A02_t01: RuntimeError, Pass
@@ -683,51 +628,6 @@
 
 [ $arch != simdbc64 && $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
 LanguageFeatures/Constant_update2018/ShortCircuitOperators_A03_t03: CompileTimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass
-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/constant_set_literals_A03_t01: Pass
-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
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/06: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/08: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: RuntimeError
-LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: Pass
-LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: RuntimeError
-LanguageFeatures/Set-literals/semantics_A04_t01: Pass
-LanguageFeatures/Set-literals/semantics_A05_t01: RuntimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A01_t01: Pass
-LanguageFeatures/Set-literals/set_literals_A02_t01: Pass
-LanguageFeatures/Set-literals/set_literals_A04_t02/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/11: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/12: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/13: MissingCompileTimeError
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: Pass
 
 [ $compiler != dart2js && $runtime != vm && $fasta ]
 Language/Classes/Constructors/Constant_Constructors/initializer_not_a_constant_t01: MissingCompileTimeError # Issue 34191
@@ -747,6 +647,23 @@
 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
@@ -919,11 +836,9 @@
 LibTest/io/RawDatagramSocket/receive_A02_t02: RuntimeError
 
 [ $runtime == vm && ($compiler == dartk || $compiler == dartkb) ]
-Language/Classes/definition_t23: CompileTimeError
 Language/Expressions/Constants/exception_t02/01: MissingRuntimeError
 Language/Expressions/Function_Invocation/async_invokation_t02: RuntimeError
 Language/Expressions/Logical_Boolean_Expressions/syntax_t01: RuntimeError
-Language/Mixins/Mixin_Application/syntax_t16: CompileTimeError
 Language/Statements/Assert/execution_t08: RuntimeError
 Language/Types/Function_Types/call_t01: RuntimeError
 LanguageFeatures/Constant_update2018/CastOperator_A01_t01: DartkCrash
@@ -999,51 +914,6 @@
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t15: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t16: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_typedef_l1_t02: RuntimeError
-LanguageFeatures/Set-literals/constant_set_literals_A02_t01: Pass
-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/constant_set_literals_A03_t01: Pass
-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
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t01/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/06: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t02/08: MissingCompileTimeError
-LanguageFeatures/Set-literals/exact_types_of_literals_A01_t03: RuntimeError
-LanguageFeatures/Set-literals/non_constant_set_literals_A01_t01: Pass
-LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: RuntimeError
-LanguageFeatures/Set-literals/semantics_A04_t01: Pass
-LanguageFeatures/Set-literals/semantics_A05_t01: RuntimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/semantics_A05_t05/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A01_t01: Pass
-LanguageFeatures/Set-literals/set_literals_A02_t01: Pass
-LanguageFeatures/Set-literals/set_literals_A04_t02/01: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/02: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/03: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/04: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/05: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/11: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/12: MissingCompileTimeError
-LanguageFeatures/Set-literals/set_literals_A04_t02/13: MissingCompileTimeError
-LanguageFeatures/Set-literals/syntax_compatibility_A01_t01: Pass
 LanguageFeatures/Simple-bounds/dynamic/typedef_FutureOr_l1_t02: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t07: RuntimeError
 LanguageFeatures/Simple-bounds/dynamic/typedef_l1_t12: RuntimeError
@@ -1331,7 +1201,6 @@
 LanguageFeatures/Instantiate-to-bound/class/dynamic/class_typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l1_t02: RuntimeError
 LanguageFeatures/Instantiate-to-bound/typedef/dynamic/typedef_l2_t01: RuntimeError
-LanguageFeatures/Set-literals/non_constant_set_literals_A02_t01: Pass # CompileTimeError on $fasta
 LibTest/async/Future/asStream_A01_t02: RuntimeError
 LibTest/async/Stream/Stream.fromFutures_A04_t03: RuntimeError
 LibTest/async/Stream/Stream.fromIterable_A03_t02: RuntimeError
diff --git a/tests/compiler/dart2js/allocator_analysis/kallocator_analysis_test.dart b/tests/compiler/dart2js/allocator_analysis/kallocator_analysis_test.dart
new file mode 100644
index 0000000..a4b8e88
--- /dev/null
+++ b/tests/compiler/dart2js/allocator_analysis/kallocator_analysis_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 'dart:io';
+import 'package:async_helper/async_helper.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/ir/util.dart';
+import 'package:compiler/src/js_backend/allocator_analysis.dart';
+import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:compiler/src/util/features.dart';
+import 'package:kernel/ast.dart' as ir;
+import '../equivalence/id_equivalence.dart';
+import '../equivalence/id_equivalence_helper.dart';
+
+main(List<String> args) {
+  asyncTest(() async {
+    Directory dataDir = new Directory.fromUri(Platform.script.resolve('kdata'));
+    await checkTests(dataDir, const KAllocatorAnalysisDataComputer(),
+        args: args, testOmit: false, testFrontend: true);
+  });
+}
+
+class Tags {
+  static const String initialValue = 'initial';
+}
+
+class KAllocatorAnalysisDataComputer extends DataComputer<Features> {
+  const KAllocatorAnalysisDataComputer();
+
+  @override
+  void computeMemberData(Compiler compiler, MemberEntity member,
+      Map<Id, ActualData<Features>> actualMap,
+      {bool verbose: false}) {
+    if (member.isField) {
+      KernelFrontEndStrategy frontendStrategy = compiler.frontendStrategy;
+      KAllocatorAnalysis allocatorAnalysis =
+          compiler.backend.allocatorResolutionAnalysisForTesting;
+      ir.Member node = frontendStrategy.elementMap.getMemberNode(member);
+      ConstantValue initialValue =
+          allocatorAnalysis.getFixedInitializerForTesting(member);
+      Features features = new Features();
+      if (initialValue != null) {
+        features[Tags.initialValue] = initialValue.toStructuredText();
+      }
+      Id id = computeEntityId(node);
+      actualMap[id] = new ActualData<Features>(
+          id, features, computeSourceSpanFromTreeNode(node), member);
+    }
+  }
+
+  @override
+  DataInterpreter<Features> get dataValidator =>
+      const FeaturesDataInterpreter();
+}
diff --git a/tests/compiler/dart2js/allocator_analysis/kdata/simple_initializers.dart b/tests/compiler/dart2js/allocator_analysis/kdata/simple_initializers.dart
new file mode 100644
index 0000000..be12d6c
--- /dev/null
+++ b/tests/compiler/dart2js/allocator_analysis/kdata/simple_initializers.dart
@@ -0,0 +1,110 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+main() {
+  new Class1();
+  new Class2();
+}
+
+const bool const1 = true;
+
+class Class1 {
+  /*element: Class1.field0:initial=NullConstant*/
+  var field0;
+
+  /*element: Class1.field1:initial=NullConstant*/
+  var field1 = null;
+
+  /*element: Class1.field2:initial=BoolConstant(true)*/
+  var field2 = true;
+
+  /*element: Class1.field3:initial=BoolConstant(false)*/
+  var field3 = false;
+
+  /*element: Class1.field4:initial=IntConstant(0)*/
+  var field4 = 0;
+
+  /*element: Class1.field5:initial=IntConstant(1)*/
+  var field5 = 1;
+
+  /*element: Class1.field6:initial=StringConstant("")*/
+  var field6 = '';
+
+  /*element: Class1.field7:initial=StringConstant("foo")*/
+  var field7 = 'foo';
+
+  /*element: Class1.field8:*/
+  var field8 = 0.5;
+
+  /*element: Class1.field9:*/
+  var field9 = const [];
+
+  /*element: Class1.field10:*/
+  var field10 = const {};
+
+  /*element: Class1.field11:*/
+  var field11 = #foo;
+
+  /*element: Class1.field12:*/
+  var field12 = 2 + 3;
+
+  /*element: Class1.field13:*/
+  var field13 = const1;
+}
+
+class Class2 {
+  /*element: Class2.field1:*/
+  var field1;
+
+  /*element: Class2.field2:*/
+  var field2;
+
+  /*element: Class2.field3:*/
+  var field3;
+
+  /*element: Class2.field4:*/
+  var field4;
+
+  /*element: Class2.field5:*/
+  var field5;
+
+  /*element: Class2.field6:*/
+  var field6;
+
+  /*element: Class2.field7:*/
+  var field7;
+
+  /*element: Class2.field8:*/
+  var field8;
+
+  /*element: Class2.field9:*/
+  var field9;
+
+  /*element: Class2.field10:*/
+  var field10;
+
+  /*element: Class2.field11:*/
+  var field11;
+
+  /*element: Class2.field12:*/
+  var field12;
+
+  /*element: Class2.field13:*/
+  var field13;
+
+  Class2()
+      : field1 = null,
+        field2 = true,
+        field3 = false,
+        field4 = 0,
+        field5 = 1,
+        field6 = '',
+        field7 = 'foo',
+        field8 = 0.5,
+        field9 = const [],
+        field10 = const {},
+        field11 = #foo,
+        field12 = 2 + 3,
+        field13 = const1;
+}
diff --git a/tests/compiler/dart2js/closure/closure_test.dart b/tests/compiler/dart2js/closure/closure_test.dart
index 705638c..26d0d92 100644
--- a/tests/compiler/dart2js/closure/closure_test.dart
+++ b/tests/compiler/dart2js/closure/closure_test.dart
@@ -273,7 +273,8 @@
         addLocals('fields', (f(Local local, _)) {
           codegenWorldBuilder.forEachInstanceField(
               closureRepresentationInfo.closureClassEntity,
-              (_, FieldEntity field) {
+              (_, FieldEntity field, {bool isElided}) {
+            if (isElided) return;
             f(closureRepresentationInfo.getLocalForField(field), field);
           });
         });
diff --git a/tests/compiler/dart2js/codegen/class_codegen_test.dart b/tests/compiler/dart2js/codegen/class_codegen_test.dart
index bb22e20..a38938e 100644
--- a/tests/compiler/dart2js/codegen/class_codegen_test.dart
+++ b/tests/compiler/dart2js/codegen/class_codegen_test.dart
@@ -40,11 +40,14 @@
 const String TEST_FOUR = r"""
 var g = 0;
 class A {
+  @pragma('dart2js:noElision')
   var x = g++;
 }
 
 class B extends A {
+  @pragma('dart2js:noElision')
   var y = g++;
+  @pragma('dart2js:noElision')
   var z = g++;
 }
 
@@ -55,6 +58,7 @@
 
 const String TEST_FIVE = r"""
 class A {
+  @pragma('dart2js:noElision')
   var a;
   A(a) : this.a = a {}
 }
@@ -90,8 +94,8 @@
 
 constructor1() async {
   String generated = await compileAll(TEST_FIVE);
-  print('--------------------\n$generated\n');
-  Expect.isTrue(generated.contains(new RegExp(r"new [$A-Z]+\.A\(a\);")));
+  Expect.isTrue(generated.contains(new RegExp(r"new [$A-Z]+\.A\(a\);")),
+      '--------------------\n$generated\n');
 }
 
 main() {
diff --git a/tests/compiler/dart2js/codegen/constant_namer_test.dart b/tests/compiler/dart2js/codegen/constant_namer_test.dart
index 076f377..8893422 100644
--- a/tests/compiler/dart2js/codegen/constant_namer_test.dart
+++ b/tests/compiler/dart2js/codegen/constant_namer_test.dart
@@ -8,7 +8,9 @@
 
 const String TEST_ONE = r"""
   class Token {
+    @pragma('dart2js:noElision')
     final name;
+    @pragma('dart2js:noElision')
     final value;
     const Token(this.name, [this.value]);
     use() { print(this); }
diff --git a/tests/compiler/dart2js/codegen/expect_annotations_test.dart b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
index bcff3bd..f4e5903 100644
--- a/tests/compiler/dart2js/codegen/expect_annotations_test.dart
+++ b/tests/compiler/dart2js/codegen/expect_annotations_test.dart
@@ -75,11 +75,11 @@
     Expect.isNotNull(method);
     Expect.equals(
         expectNoInline,
-        closedWorld.annotationsData.nonInlinableFunctions.contains(method),
+        closedWorld.annotationsData.hasNoInline(method),
         "Unexpected annotation of @NoInline() on '$method'.");
     Expect.equals(
         expectAssumeDynamic,
-        closedWorld.annotationsData.assumeDynamicMembers.contains(method),
+        closedWorld.annotationsData.hasAssumeDynamic(method),
         "Unexpected annotation of @AssumeDynamic() on '$method'.");
     GlobalTypeInferenceResults results =
         compiler.globalInference.resultsForTesting;
diff --git a/tests/compiler/dart2js/codegen/model_data/capture.dart b/tests/compiler/dart2js/codegen/model_data/capture.dart
new file mode 100644
index 0000000..ca9279e
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/capture.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.
+
+/*element: method1:params=0*/
+@pragma('dart2js:noInline')
+method1([a]) => /*params=0*/ () => a;
+
+class Class {
+  /*element: Class.f:emitted*/
+  @pragma('dart2js:noElision')
+  var f;
+
+  /*element: Class.capture:params=0*/
+  @pragma('dart2js:noInline')
+  Class.capture([a]) : f = (/*params=0*/ () => a);
+
+  // TODO(johnniwinther): Remove the redundant assignment of elided boxed
+  // parameters.
+  /*element: Class.box:assign=[a,a],params=0*/
+  @pragma('dart2js:noInline')
+  Class.box([a])
+      : f = (/*assign=[a],params=0*/ () {
+          a = 42;
+        });
+
+  Class.internal(this.f);
+}
+
+class Subclass extends Class {
+  /*element: Subclass.capture:params=0*/
+  @pragma('dart2js:noInline')
+  Subclass.capture([a]) : super.internal(/*params=0*/ () => a);
+
+  /*element: Subclass.box:assign=[a,a],params=0*/
+  @pragma('dart2js:noInline')
+  Subclass.box([a])
+      : super.internal(/*assign=[a],params=0*/ () {
+          a = 42;
+        });
+}
+
+/*element: main:calls=*,params=0*/
+main() {
+  method1();
+  new Class.capture();
+  new Class.box();
+  new Subclass.capture();
+  new Subclass.box();
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/constructors.dart b/tests/compiler/dart2js/codegen/model_data/constructors.dart
new file mode 100644
index 0000000..69be657
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/constructors.dart
@@ -0,0 +1,140 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+class Class {
+  /*element: Class.constructor1:params=0*/
+  @pragma('dart2js:noInline')
+  Class.constructor1() {}
+
+  /*element: Class.constructor2a:params=0*/
+  @pragma('dart2js:noInline')
+  Class.constructor2a([a]) {}
+
+  /*element: Class.constructor2b:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor2b([a]) {}
+
+  /*element: Class.constructor2c:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor2c([a]) {}
+
+  /*element: Class.constructor3a:params=0*/
+  @pragma('dart2js:noInline')
+  Class.constructor3a([a, b]) {}
+
+  /*element: Class.constructor3b:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor3b([a, b]) {}
+
+  /*element: Class.constructor3c:params=2*/
+  @pragma('dart2js:noInline')
+  Class.constructor3c([a, b]) {}
+
+  /*element: Class.constructor4a:params=0*/
+  @pragma('dart2js:noInline')
+  Class.constructor4a({a}) {}
+
+  /*element: Class.constructor4b:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor4b({a}) {}
+
+  /*element: Class.constructor4c:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor4c({a}) {}
+
+  /*element: Class.constructor5a:params=0*/
+  @pragma('dart2js:noInline')
+  Class.constructor5a({a, b}) {}
+
+  /*element: Class.constructor5b:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor5b({a, b}) {}
+
+  /*element: Class.constructor5c:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor5c({a, b}) {}
+
+  /*element: Class.constructor6a:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor6a(a, [b, c]) {}
+
+  /*element: Class.constructor6b:params=2*/
+  @pragma('dart2js:noInline')
+  Class.constructor6b(a, [b, c]) {}
+
+  /*element: Class.constructor6c:params=3*/
+  @pragma('dart2js:noInline')
+  Class.constructor6c(a, [b, c]) {}
+
+  /*element: Class.constructor7a:params=1*/
+  @pragma('dart2js:noInline')
+  Class.constructor7a(a, {b, c}) {}
+
+  /*element: Class.constructor7b:params=2*/
+  @pragma('dart2js:noInline')
+  Class.constructor7b(a, {b, c}) {}
+
+  /*element: Class.constructor7c:params=2*/
+  @pragma('dart2js:noInline')
+  Class.constructor7c(a, {b, c}) {}
+}
+
+/*element: main:
+ calls=[
+  Class$constructor1(0),
+  Class$constructor2a(0),
+  Class$constructor2b(1),
+  Class$constructor2c(1),
+  Class$constructor2c(1),
+  Class$constructor3a(0),
+  Class$constructor3b(1),
+  Class$constructor3b(1),
+  Class$constructor3c(2),
+  Class$constructor4a(0),
+  Class$constructor4b(1),
+  Class$constructor4c(1),
+  Class$constructor4c(1),
+  Class$constructor5a(0),
+  Class$constructor5b(1),
+  Class$constructor5c(1),
+  Class$constructor6a(1),
+  Class$constructor6b(2),
+  Class$constructor6b(2),
+  Class$constructor6c(3),
+  Class$constructor7a(1),
+  Class$constructor7b(2),
+  Class$constructor7c(2)],
+ params=0
+*/
+main() {
+  new Class.constructor1();
+
+  new Class.constructor2a();
+  new Class.constructor2b(null);
+  new Class.constructor2c();
+  new Class.constructor2c(null);
+
+  new Class.constructor3a();
+  new Class.constructor3b();
+  new Class.constructor3b(null);
+  new Class.constructor3c(null, null);
+
+  new Class.constructor4a();
+  new Class.constructor4b(a: null);
+  new Class.constructor4c();
+  new Class.constructor4c(a: null);
+
+  new Class.constructor5a();
+  new Class.constructor5b(a: null);
+  new Class.constructor5c(b: null);
+
+  new Class.constructor6a(null);
+  new Class.constructor6b(null);
+  new Class.constructor6b(null, null);
+  new Class.constructor6c(null, null, null);
+
+  new Class.constructor7a(null);
+  new Class.constructor7b(null, b: null);
+  new Class.constructor7c(null, c: null);
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart b/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart
index c014519..f519f30 100644
--- a/tests/compiler/dart2js/codegen/model_data/dynamic_get.dart
+++ b/tests/compiler/dart2js/codegen/model_data/dynamic_get.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.
 
+/*element: main:calls=*,params=0*/
 main() {
   method1(new Class1a());
   method2(new Class2a<int>());
@@ -12,50 +13,54 @@
 }
 
 class Class1a {
-  /*element: Class1a.field1:*/
+  /*element: Class1a.field1:emitted*/
   int field1;
 }
 
+/*element: method1:params=1*/
 @pragma('dart2js:noInline')
 method1(dynamic c) {
   return c.field1;
 }
 
 class Class2a<T> {
-  /*element: Class2a.field2:*/
+  /*element: Class2a.field2:emitted*/
   T field2;
 }
 
+/*element: method2:params=1*/
 @pragma('dart2js:noInline')
 method2(dynamic c) {
   return c.field2;
 }
 
 class Class3a {
-  /*element: Class3a.field3:get=simple*/
+  /*element: Class3a.field3:emitted,get=simple*/
   int field3;
 }
 
 class Class3b {
-  /*element: Class3b.field3:get=simple*/
+  /*element: Class3b.field3:emitted,get=simple*/
   int field3;
 }
 
+/*element: method3:calls=[get$field3(0)],params=1*/
 @pragma('dart2js:noInline')
 method3(dynamic c) {
   return c.field3;
 }
 
 class Class4a {
-  /*element: Class4a.field4:get=simple*/
+  /*element: Class4a.field4:emitted,get=simple*/
   int field4;
 }
 
 class Class4b implements Class4a {
-  /*element: Class4b.field4:get=simple*/
+  /*element: Class4b.field4:emitted,get=simple*/
   int field4;
 }
 
+/*element: method4:calls=[get$field4(0)],params=1*/
 @pragma('dart2js:noInline')
 method4(Class4a c) {
   return c.field4;
diff --git a/tests/compiler/dart2js/codegen/model_data/dynamic_set.dart b/tests/compiler/dart2js/codegen/model_data/dynamic_set.dart
index ac96348..8df2ee2 100644
--- a/tests/compiler/dart2js/codegen/model_data/dynamic_set.dart
+++ b/tests/compiler/dart2js/codegen/model_data/dynamic_set.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.
 
+/*element: main:calls=*,params=0*/
 main() {
   method1(new Class1a());
   method2(new Class2a<int>());
@@ -12,55 +13,60 @@
 }
 
 class Class1a {
-  /*element: Class1a.field1:*/
+  /*element: Class1a.field1:elided*/
   int field1;
 }
 
+/*element: method1:params=1*/
 @pragma('dart2js:noInline')
 method1(dynamic c) {
   c.field1 = 42;
 }
 
 class Class2a<T> {
-  /*strong.element: Class2a.field2:checked*/
-  /*omit.element: Class2a.field2:*/
+  /*strong.element: Class2a.field2:checked,elided*/
+  /*omit.element: Class2a.field2:elided*/
   T field2;
 }
 
+/*strong.element: method2:calls=[set$field2(1)],params=1*/
+/*omit.element: method2:params=1*/
 @pragma('dart2js:noInline')
 method2(dynamic c) {
   c.field2 = 42;
 }
 
 class Class3a {
-  /*strong.element: Class3a.field3:checked*/
-  /*omit.element: Class3a.field3:set=simple*/
+  /*strong.element: Class3a.field3:checked,elided*/
+  /*omit.element: Class3a.field3:elided,set=simple*/
   int field3;
 }
 
 class Class3b {
-  /*strong.element: Class3b.field3:checked*/
-  /*omit.element: Class3b.field3:set=simple*/
+  /*strong.element: Class3b.field3:checked,elided*/
+  /*omit.element: Class3b.field3:elided,set=simple*/
   int field3;
 }
 
+/*element: method3:calls=[set$field3(1)],params=1*/
 @pragma('dart2js:noInline')
 method3(dynamic c) {
   c.field3 = 42;
 }
 
 class Class4a {
-  /*strong.element: Class4a.field4:checked*/
-  /*omit.element: Class4a.field4:set=simple*/
+  /*strong.element: Class4a.field4:checked,elided*/
+  /*omit.element: Class4a.field4:elided,set=simple*/
   int field4;
 }
 
 class Class4b implements Class4a {
-  /*strong.element: Class4b.field4:checked*/
-  /*omit.element: Class4b.field4:set=simple*/
+  /*strong.element: Class4b.field4:checked,elided*/
+  /*omit.element: Class4b.field4:elided,set=simple*/
   int field4;
 }
 
+/*element: method4:calls=[set$field4(1)],params=1*/
 @pragma('dart2js:noInline')
 method4(Class4a c) {
   c.field4 = 42;
diff --git a/tests/compiler/dart2js/codegen/model_data/field_set.dart b/tests/compiler/dart2js/codegen/model_data/field_set.dart
new file mode 100644
index 0000000..6c23abe
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/field_set.dart
@@ -0,0 +1,123 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: main:calls=*,params=0*/
+main() {
+  method1(new Class1a());
+  method2(new Class2a());
+  method2(new Class2b());
+
+  method3(new Class3a());
+  Class3b b = new Class3b();
+  method3(b);
+  print(b.field3);
+
+  method5(new Class5a());
+  method6(new Class6a());
+  method6(new Class6b());
+  method7();
+  method8();
+  method9();
+  method10();
+}
+
+class Class1a {
+  /*element: Class1a.field1:emitted*/
+  @pragma('dart2js:noElision')
+  int field1;
+}
+
+/*element: method1:assign=[field1],params=1*/
+@pragma('dart2js:noInline')
+method1(Class1a c) {
+  c.field1 = 42;
+}
+
+class Class2a {
+  /*element: Class2a.field2:emitted*/
+  @pragma('dart2js:noElision')
+  int field2 = 42;
+}
+
+class Class2b extends Class2a {}
+
+/*element: method2:assign=[field2],params=1*/
+@pragma('dart2js:noInline')
+method2(Class2a c) {
+  c.field2 = 42;
+}
+
+class Class3a {
+  /*element: Class3a.field3:elided,set=simple*/
+  var field3;
+}
+
+class Class3b implements Class3a {
+  /*element: Class3b.field3:emitted,set=simple*/
+  var field3;
+}
+
+/*element: method3:calls=[set$field3(1)],params=1*/
+@pragma('dart2js:noInline')
+method3(Class3a a) => a.field3 = 42;
+
+class Class5a {
+  /*element: Class5a.field5:elided*/
+  int field5;
+}
+
+/*element: method5:params=1*/
+@pragma('dart2js:noInline')
+method5(Class5a c) {
+  c.field5 = 42;
+}
+
+class Class6a {
+  /*element: Class6a.field6:elided*/
+  int field6 = 42;
+}
+
+class Class6b extends Class6a {}
+
+@pragma('dart2js:noInline')
+method6(Class6a c) {
+  /*element: method6:params=1*/
+  c.field6 = 42;
+}
+
+/*element: field7:emitted*/
+@pragma('dart2js:noElision')
+int field7;
+
+/*element: method7:assign=[field7],params=0*/
+@pragma('dart2js:noInline')
+method7() {
+  field7 = 42;
+}
+
+int field8;
+
+/*element: method8:params=0*/
+@pragma('dart2js:noInline')
+method8() {
+  field8 = 42;
+}
+
+/*element: field9:emitted,lazy*/
+@pragma('dart2js:noElision')
+int field9 = throw 'field9';
+
+/*element: method9:assign=[field9],params=0*/
+@pragma('dart2js:noInline')
+method9() {
+  field9 = 42;
+}
+
+int field10 = throw 'field9';
+
+/*element: method10:params=0*/
+@pragma('dart2js:noInline')
+method10() {
+  field10 = 42;
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/fields.dart b/tests/compiler/dart2js/codegen/model_data/fields.dart
new file mode 100644
index 0000000..62c3b52
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/fields.dart
@@ -0,0 +1,97 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+var field1a;
+
+var field1b;
+
+var field1c;
+
+/*element: field2a:params=0*/
+@pragma('dart2js:noInline')
+get field2a => 42;
+
+@pragma('dart2js:noInline')
+set field2a(_) {}
+
+@pragma('dart2js:noInline')
+get field2b => 42;
+
+/*element: field2b=:params=1*/
+@pragma('dart2js:noInline')
+set field2b(_) {}
+
+/*element: field2c:params=0*/
+@pragma('dart2js:noInline')
+get field2c => 42;
+
+/*element: field2c=:params=1*/
+@pragma('dart2js:noInline')
+set field2c(_) {}
+
+class Class {
+  /*element: Class.field1a:emitted*/
+  var field1a;
+
+  /*element: Class.field1b:elided*/
+  var field1b;
+
+  /*element: Class.field1c:emitted*/
+  var field1c;
+
+  /*element: Class.field2a:params=0*/
+  @pragma('dart2js:noInline')
+  get field2a => 42;
+
+  @pragma('dart2js:noInline')
+  set field2a(_) {}
+
+  @pragma('dart2js:noInline')
+  get field2b => 42;
+
+  /*element: Class.field2b=:params=1*/
+  @pragma('dart2js:noInline')
+  set field2b(_) {}
+
+  /*element: Class.field2c:params=0*/
+  @pragma('dart2js:noInline')
+  get field2c => 42;
+
+  set field2c(_) {}
+
+  /*element: Class.field3a:elided*/
+  var field3a = 0;
+
+  /*element: Class.field3b:elided*/
+  var field3b;
+
+  /*element: Class.:params=0*/
+  @pragma('dart2js:noInline')
+  Class([this.field3b]);
+
+  /*element: Class.test:calls=[get$field2a(0),get$field2c(0),set$field2b(1)],params=0*/
+  @pragma('dart2js:noInline')
+  test() {
+    field1a;
+    field1b = 42;
+    field1c = field1c;
+
+    field2a;
+    field2b = 42;
+    field2c = field2c;
+  }
+}
+
+/*element: main:calls=[Class$(0),field2a(0),field2b(1),field2c(0),field2c0(1),test$0(0)],params=0*/
+main() {
+  field1a;
+  field1b = 42;
+  field1c = field1c;
+
+  field2a;
+  field2b = 42;
+  field2c = field2c;
+
+  new Class().test();
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/instance_method_parameters.dart b/tests/compiler/dart2js/codegen/model_data/instance_method_parameters.dart
new file mode 100644
index 0000000..a861c04
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/instance_method_parameters.dart
@@ -0,0 +1,126 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 Class {
+  /*element: Class.method1:params=0*/
+  @pragma('dart2js:noInline')
+  method1() {}
+
+  /*element: Class.method2a:params=0*/
+  @pragma('dart2js:noInline')
+  method2a([a]) {}
+
+  /*element: Class.method2b:params=1*/
+  @pragma('dart2js:noInline')
+  method2b([a]) {}
+
+  /*element: Class.method2c:params=1,stubs=[method2c$0:method2c$1(1)]*/
+  @pragma('dart2js:noInline')
+  method2c([a]) {}
+
+  /*element: Class.method3a:params=0*/
+  @pragma('dart2js:noInline')
+  method3a([a, b]) {}
+
+  /*element: Class.method3b:params=1,stubs=[method3b$0:method3b$1(1)]*/
+  @pragma('dart2js:noInline')
+  method3b([a, b]) {}
+
+  /*element: Class.method3c:params=2*/
+  @pragma('dart2js:noInline')
+  method3c([a, b]) {}
+
+  /*element: Class.method4a:params=0*/
+  @pragma('dart2js:noInline')
+  method4a({a}) {}
+
+  /*element: Class.method4b:params=1*/
+  @pragma('dart2js:noInline')
+  method4b({a}) {}
+
+  /*element: Class.method4c:params=1,stubs=[method4c$0:method4c$1$a(1)]*/
+  @pragma('dart2js:noInline')
+  method4c({a}) {}
+
+  /*element: Class.method5a:params=0*/
+  @pragma('dart2js:noInline')
+  method5a({a, b}) {}
+
+  /*element: Class.method5b:params=1*/
+  @pragma('dart2js:noInline')
+  method5b({a, b}) {}
+
+  /*element: Class.method5c:params=1*/
+  @pragma('dart2js:noInline')
+  method5c({a, b}) {}
+
+  /*element: Class.method6a:params=0,stubs=[method6a$0:method6a$1$0(1)]*/
+  @pragma('dart2js:noInline')
+  method6a<T>() {}
+
+  /*element: Class.method7a:params=1*/
+  @pragma('dart2js:noInline')
+  method7a(a, [b, c]) {}
+
+  /*element: Class.method7b:params=2,stubs=[method7b$1:method7b$2(2)]*/
+  @pragma('dart2js:noInline')
+  method7b(a, [b, c]) {}
+
+  /*element: Class.method7c:params=3*/
+  @pragma('dart2js:noInline')
+  method7c(a, [b, c]) {}
+
+  /*element: Class.method8a:params=1*/
+  @pragma('dart2js:noInline')
+  method8a(a, {b, c}) {}
+
+  /*element: Class.method8b:params=2*/
+  @pragma('dart2js:noInline')
+  method8b(a, {b, c}) {}
+
+  /*element: Class.method8c:params=2*/
+  @pragma('dart2js:noInline')
+  method8c(a, {b, c}) {}
+
+  /*element: Class.test:calls=*,params=0*/
+  @pragma('dart2js:noInline')
+  test() {
+    method1();
+
+    method2a();
+    method2b(null);
+    method2c();
+    method2c(null);
+
+    method3a();
+    method3b();
+    method3b(null);
+    method3c(null, null);
+
+    method4a();
+    method4b(a: null);
+    method4c();
+    method4c(a: null);
+
+    method5a();
+    method5b(a: null);
+    method5c(b: null);
+
+    method6a();
+
+    method7a(null);
+    method7b(null);
+    method7b(null, null);
+    method7c(null, null, null);
+
+    method8a(null);
+    method8b(null, b: null);
+    method8c(null, c: null);
+  }
+}
+
+/*element: main:calls=[test$0(0)],params=0*/
+main() {
+  new Class().test();
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/native.dart b/tests/compiler/dart2js/codegen/model_data/native.dart
new file mode 100644
index 0000000..23dcd6e
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/native.dart
@@ -0,0 +1,134 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+@Native('Class')
+class Class {
+  factory Class() {
+    throw new UnsupportedError("Not supported");
+  }
+
+  @pragma('dart2js:noElision')
+  int field1;
+
+  int field2;
+
+  /*element: Class.method1:
+   calls=[method1(a,b,c)],
+   params=4,
+   stubs=[
+    method1$1:method1(a),
+    method1$2:method1(a,b)]
+  */
+  @pragma('dart2js:noInline')
+  method1(a, [b, c])
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  /*element: Class.method2:
+   calls=[method2(a,b,c)],
+   params=4,
+   stubs=[
+    method2$1:method2(a),
+    method2$2$b:method2(a,b),
+    method2$2$c:method2(a,null,c)]
+  */
+  @pragma('dart2js:noInline')
+  method2(a, {b, c})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  // TODO(johnniwinther): Control the order of the named arguments. Currently
+  // we sort them lexicographically but that doesn't match the target
+  // expectations.
+  /*element: Class.method3:
+   calls=[method3(a,c,b)],
+   params=4,
+   stubs=[
+    method3$1:method3(a),
+    method3$2$b:method3(a,null,b),
+    method3$2$c:method3(a,c)]
+  */
+  @pragma('dart2js:noInline')
+  method3(a, {c, b})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  // TODO(johnniwinther): Control the order of the named arguments. Currently
+  // we sort them lexicographically but that doesn't match the target
+  // expectations.
+  /*element: Class.method4:
+   calls=[method4(a,c,d,b)],
+   params=5,
+   stubs=[
+    method4$1:method4(a),
+    method4$2$b:method4(a,null,null,b),
+    method4$2$c:method4(a,c),
+    method4$3$b$c:method4(a,c,null,b),
+    method4$3$b$d:method4(a,null,d,b),
+    method4$3$c$d:method4(a,c,d)]
+  */
+  @pragma('dart2js:noInline')
+  method4(a, {c, d, b})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+}
+
+/*element: makeClass:params=0*/
+@Creates('Class')
+makeClass()
+    // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+    native;
+
+/*element: main:calls=[test(1),*],params=0*/
+main() {
+  test(makeClass());
+}
+
+/*element: test:
+ assign=[field1,field2],
+ calls=[
+  method1$1(2),
+  method1$2(3),
+  method1$3(4),
+  method2$1(2),
+  method2$2$b(3),
+  method2$2$c(3),
+  method2$3$b$c(4),
+  method3$1(2),
+  method3$2$b(3),
+  method3$2$c(3),
+  method3$3$b$c(4),
+  method4$1(2),
+  method4$2$b(3),
+  method4$2$c(3),
+  method4$3$b$c(4),
+  method4$3$b$d(4),
+  method4$3$c$d(4)],
+ params=1
+*/
+@pragma('dart2js:noInline')
+test(Class o) {
+  o.field1 = 42;
+  o.field2 = 42;
+  o.method1(0);
+  o.method1(0, 1);
+  o.method1(0, 1, 2);
+  o.method2(0);
+  o.method2(0, b: 1);
+  o.method2(0, b: 1, c: 2);
+  o.method2(0, c: 2);
+  o.method3(0);
+  o.method3(0, b: 1);
+  o.method3(0, b: 1, c: 2);
+  o.method3(0, c: 2);
+  o.method4(0);
+  o.method4(0, b: 1);
+  o.method4(0, b: 1, c: 2);
+  o.method4(0, c: 2);
+  o.method4(0, c: 2, d: 3);
+  o.method4(0, b: 1, d: 3);
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/native_inlined.dart b/tests/compiler/dart2js/codegen/model_data/native_inlined.dart
new file mode 100644
index 0000000..7e99271
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/native_inlined.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+@Native('Class')
+class Class {
+  factory Class() {
+    throw new UnsupportedError("Not supported");
+  }
+
+  method1(a, [b, c])
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  /*element: Class.method2:
+   calls=[method2(a,b,c)],
+   params=4,
+   stubs=[
+    method2$1:method2(a),
+    method2$2$b:method2(a,b),
+    method2$2$c:method2(a,null,c)]
+  */
+  method2(a, {b, c})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  // TODO(johnniwinther): Control the order of the named arguments. Currently
+  // we sort them lexicographically but that doesn't match the target
+  // expectations.
+  /*element: Class.method3:
+   calls=[method3(a,c,b)],
+   params=4,
+   stubs=[
+    method3$1:method3(a),
+    method3$2$b:method3(a,null,b),
+    method3$2$c:method3(a,c)]
+  */
+  method3(a, {c, b})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+
+  // TODO(johnniwinther): Control the order of the named arguments. Currently
+  // we sort them lexicographically but that doesn't match the target
+  // expectations.
+  /*element: Class.method4:
+   calls=[method4(a,c,d,b)],
+   params=5,
+   stubs=[
+    method4$1:method4(a),
+    method4$2$b:method4(a,null,null,b),
+    method4$2$c:method4(a,c),
+    method4$3$b$c:method4(a,c,null,b),
+    method4$3$b$d:method4(a,null,d,b),
+    method4$3$c$d:method4(a,c,d)]
+  */
+  method4(a, {c, d, b})
+      // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+      native;
+}
+
+/*element: makeClass:params=0*/
+@Creates('Class')
+makeClass()
+    // ignore: NATIVE_FUNCTION_BODY_IN_NON_SDK_CODE
+    native;
+
+/*element: main:calls=[test(1),*],params=0*/
+main() {
+  test(makeClass());
+}
+
+/*element: test:
+ calls=[
+  method1(0),
+  method1(0,1),
+  method1(0,1,2),
+  method2$1(2),
+  method2$2$b(3),
+  method2$2$c(3),
+  method2$3$b$c(4),
+  method3$1(2),
+  method3$2$b(3),
+  method3$2$c(3),
+  method3$3$b$c(4),
+  method4$1(2),
+  method4$2$b(3),
+  method4$2$c(3),
+  method4$3$b$c(4),
+  method4$3$b$d(4),
+  method4$3$c$d(4)],
+ params=1
+*/
+@pragma('dart2js:noInline')
+test(Class o) {
+  if (o == null) return;
+  o.method1(0);
+  o.method1(0, 1);
+  o.method1(0, 1, 2);
+  o.method2(0);
+  o.method2(0, b: 1);
+  o.method2(0, b: 1, c: 2);
+  o.method2(0, c: 2);
+  o.method3(0);
+  o.method3(0, b: 1);
+  o.method3(0, b: 1, c: 2);
+  o.method3(0, c: 2);
+  o.method4(0);
+  o.method4(0, b: 1);
+  o.method4(0, b: 1, c: 2);
+  o.method4(0, c: 2);
+  o.method4(0, c: 2, d: 3);
+  o.method4(0, b: 1, d: 3);
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/native_unused_parameters.dart b/tests/compiler/dart2js/codegen/model_data/native_unused_parameters.dart
new file mode 100644
index 0000000..36197db
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/native_unused_parameters.dart
@@ -0,0 +1,119 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+/*element: Class.:params=1*/
+@Native('Class')
+class Class {
+  /*element: Class.method1:calls=[method1()],params=1*/
+  @pragma('dart2js:noInline')
+  method1([a, b])
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method2:calls=[method2(a)],params=2*/
+  @pragma('dart2js:noInline')
+  method2([a, b])
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method3:calls=[method3(a,b)],params=3*/
+  @pragma('dart2js:noInline')
+  method3([a, b])
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method4:
+   calls=[method4(a,b)],
+   params=3,
+   stubs=[method4$0:method4()]
+  */
+  @pragma('dart2js:noInline')
+  method4([a, b])
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method5:
+   calls=[method5(a,b)],
+   params=3,
+   stubs=[method5$1:method5(a)]
+  */
+  @pragma('dart2js:noInline')
+  method5([a, b])
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method6:
+   calls=[method6(a,b,c)],
+   params=4,
+   stubs=[method6$1:method6(a)]
+  */
+  @pragma('dart2js:noInline')
+  method6(a, {b, c})
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method7:
+   calls=[method7(a,b,c)],
+   params=4,
+   stubs=[method7$2$b:method7(a,b)]
+  */
+  @pragma('dart2js:noInline')
+  method7(a, {b, c})
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+
+  /*element: Class.method8:
+   calls=[method8(a,b,c)],
+   params=4,
+   stubs=[
+    method8$2$b:method8(a,b),
+    method8$2$c:method8(a,null,c)]
+  */
+  @pragma('dart2js:noInline')
+  method8(a, {b, c})
+      // ignore: native_function_body_in_non_sdk_code
+      native;
+}
+
+/*element: test:
+ calls=[
+  method1$0(1),
+  method2$1(2),
+  method3$2(3),
+  method4$0(1),
+  method4$2(3),
+  method5$1(2),
+  method5$2(3),
+  method6$1(2),
+  method6$3$b$c(4),
+  method7$2$b(3),
+  method7$3$b$c(4),
+  method8$2$b(3),
+  method8$2$c(3)],
+ params=1
+*/
+@pragma('dart2js:noInline')
+test(Class c) {
+  c.method1();
+  c.method2(null);
+  c.method3(null, null);
+  c.method4();
+  c.method4(null, null);
+  c.method5(null);
+  c.method5(null, null);
+  c.method6(null);
+  c.method6(null, b: null, c: null);
+  c.method7(null, b: null);
+  c.method7(null, b: null, c: null);
+  c.method8(null, b: null);
+  c.method8(null, c: null);
+}
+
+/*element: main:calls=*,params=0*/
+main() {
+  test(new Class());
+}
diff --git a/tests/compiler/dart2js/codegen/model_data/static_method_parameters.dart b/tests/compiler/dart2js/codegen/model_data/static_method_parameters.dart
new file mode 100644
index 0000000..5fb0bfd
--- /dev/null
+++ b/tests/compiler/dart2js/codegen/model_data/static_method_parameters.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.
+
+/*element: method1:params=0*/
+@pragma('dart2js:noInline')
+method1() {}
+
+/*element: method2a:params=0*/
+@pragma('dart2js:noInline')
+method2a([a]) {}
+
+/*element: method2b:params=1*/
+@pragma('dart2js:noInline')
+method2b([a]) {}
+
+/*element: method2c:params=1*/
+@pragma('dart2js:noInline')
+method2c([a]) {}
+
+/*element: method3a:params=0*/
+@pragma('dart2js:noInline')
+method3a([a, b]) {}
+
+/*element: method3b:params=1*/
+@pragma('dart2js:noInline')
+method3b([a, b]) {}
+
+/*element: method3c:params=2*/
+@pragma('dart2js:noInline')
+method3c([a, b]) {}
+
+/*element: method4a:params=0*/
+@pragma('dart2js:noInline')
+method4a({a}) {}
+
+/*element: method4b:params=1*/
+@pragma('dart2js:noInline')
+method4b({a}) {}
+
+/*element: method4c:params=1*/
+@pragma('dart2js:noInline')
+method4c({a}) {}
+
+/*element: method5a:params=0*/
+@pragma('dart2js:noInline')
+method5a({a, b}) {}
+
+/*element: method5b:params=1*/
+@pragma('dart2js:noInline')
+method5b({a, b}) {}
+
+/*element: method5c:params=1*/
+@pragma('dart2js:noInline')
+method5c({a, b}) {}
+
+/*element: method6a:params=0*/
+@pragma('dart2js:noInline')
+method6a<T>() {}
+
+/*element: method7a:params=1*/
+@pragma('dart2js:noInline')
+method7a(a, [b, c]) {}
+
+/*element: method7b:params=2*/
+@pragma('dart2js:noInline')
+method7b(a, [b, c]) {}
+
+/*element: method7c:params=3*/
+@pragma('dart2js:noInline')
+method7c(a, [b, c]) {}
+
+/*element: method8a:params=1*/
+@pragma('dart2js:noInline')
+method8a(a, {b, c}) {}
+
+/*element: method8b:params=2*/
+@pragma('dart2js:noInline')
+method8b(a, {b, c}) {}
+
+/*element: method8c:params=2*/
+@pragma('dart2js:noInline')
+method8c(a, {b, c}) {}
+
+/*element: main:
+ calls=[
+  method1(0),
+  method2a(0),
+  method2b(1),
+  method2c(1),
+  method2c(1),
+  method3a(0),
+  method3b(1),
+  method3b(1),
+  method3c(2),
+  method4a(0),
+  method4b(1),
+  method4c(1),
+  method4c(1),
+  method5a(0),
+  method5b(1),
+  method5c(1),
+  method6a(0),
+  method7a(1),
+  method7b(2),
+  method7b(2),
+  method7c(3),
+  method8a(1),
+  method8b(2),
+  method8c(2)],
+ params=0
+*/
+main() {
+  method1();
+
+  method2a();
+  method2b(null);
+  method2c();
+  method2c(null);
+
+  method3a();
+  method3b();
+  method3b(null);
+  method3c(null, null);
+
+  method4a();
+  method4b(a: null);
+  method4c();
+  method4c(a: null);
+
+  method5a();
+  method5b(a: null);
+  method5c(b: null);
+
+  method6a();
+
+  method7a(null);
+  method7b(null);
+  method7b(null, null);
+  method7c(null, null, null);
+
+  method8a(null);
+  method8b(null, b: null);
+  method8c(null, c: null);
+}
diff --git a/tests/compiler/dart2js/codegen/model_test.dart b/tests/compiler/dart2js/codegen/model_test.dart
index fffbce8..e00c78d 100644
--- a/tests/compiler/dart2js/codegen/model_test.dart
+++ b/tests/compiler/dart2js/codegen/model_test.dart
@@ -9,10 +9,13 @@
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
 import 'package:compiler/src/elements/entities.dart';
+import 'package:compiler/src/js/js.dart' as js;
+import 'package:compiler/src/js_backend/namer.dart';
 import 'package:compiler/src/js_emitter/model.dart';
 import 'package:compiler/src/js_model/element_map.dart';
 import 'package:compiler/src/js_model/js_world.dart';
 import 'package:compiler/src/util/features.dart';
+import 'package:js_ast/js_ast.dart' as js;
 import 'package:kernel/ast.dart' as ir;
 import '../equivalence/id_equivalence.dart';
 import '../equivalence/id_equivalence_helper.dart';
@@ -26,7 +29,7 @@
   });
 }
 
-class ModelDataComputer extends DataComputer<String> {
+class ModelDataComputer extends DataComputer<Features> {
   const ModelDataComputer();
 
   /// Compute type inference data for [member] from kernel based inference.
@@ -34,7 +37,7 @@
   /// Fills [actualMap] with the data.
   @override
   void computeMemberData(Compiler compiler, MemberEntity member,
-      Map<Id, ActualData<String>> actualMap,
+      Map<Id, ActualData<Features>> actualMap,
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     JsToElementMap elementMap = closedWorld.elementMap;
@@ -45,24 +48,32 @@
   }
 
   @override
-  DataInterpreter<String> get dataValidator => const StringDataInterpreter();
+  DataInterpreter<Features> get dataValidator =>
+      const FeaturesDataInterpreter();
 }
 
 class Tags {
   static const String needsCheckedSetter = 'checked';
   static const String getterFlags = 'get';
   static const String setterFlags = 'set';
+  static const String parameterCount = 'params';
+  static const String call = 'calls';
+  static const String parameterStub = 'stubs';
+  static const String isEmitted = 'emitted';
+  static const String isElided = 'elided';
+  static const String assignment = 'assign';
+  static const String isLazy = 'lazy';
 }
 
 /// AST visitor for computing inference data for a member.
-class ModelIrComputer extends IrDataExtractor<String> {
+class ModelIrComputer extends IrDataExtractor<Features> {
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
   final ProgramLookup _programLookup;
 
   ModelIrComputer(
       DiagnosticReporter reporter,
-      Map<Id, ActualData<String>> actualMap,
+      Map<Id, ActualData<Features>> actualMap,
       this._elementMap,
       MemberEntity member,
       Compiler compiler,
@@ -70,7 +81,7 @@
       : _programLookup = new ProgramLookup(compiler),
         super(reporter, actualMap);
 
-  String getMemberValue(MemberEntity member) {
+  Features getMemberValue(MemberEntity member) {
     if (member is FieldEntity) {
       Field field = _programLookup.getField(member);
       if (field != null) {
@@ -78,6 +89,11 @@
         if (field.needsCheckedSetter) {
           features.add(Tags.needsCheckedSetter);
         }
+        if (field.isElided) {
+          features.add(Tags.isElided);
+        } else {
+          features.add(Tags.isEmitted);
+        }
         void registerFlags(String tag, int flags) {
           switch (flags) {
             case 0:
@@ -97,19 +113,91 @@
         registerFlags(Tags.getterFlags, field.getterFlags);
         registerFlags(Tags.setterFlags, field.setterFlags);
 
-        return features.getText();
+        return features;
+      }
+      StaticField staticField = _programLookup.getStaticField(member);
+      if (staticField != null) {
+        Features features = new Features();
+        features.add(Tags.isEmitted);
+        if (staticField.isLazy) {
+          features.add(Tags.isLazy);
+        }
+        return features;
+      }
+    } else if (member is FunctionEntity) {
+      Method method = _programLookup.getMethod(member);
+      if (method != null) {
+        Features features = new Features();
+        js.Expression code = method.code;
+        if (code is js.Fun) {
+          features[Tags.parameterCount] = '${code.params.length}';
+        }
+
+        void registerCalls(String tag, js.Node node, [String prefix = '']) {
+          forEachNode(node, onCall: (js.Call node) {
+            js.Node target = node.target;
+            if (target is js.PropertyAccess) {
+              js.Node selector = target.selector;
+              bool fixedNameCall = false;
+              String name;
+              if (selector is js.Name) {
+                name = selector.key;
+                fixedNameCall = selector is StringBackedName;
+              } else if (selector is js.LiteralString) {
+                /// Call to fixed backend name, so we include the argument
+                /// values to test encoding of optional parameters in native
+                /// methods.
+                name = selector.value.substring(1, selector.value.length - 1);
+                fixedNameCall = true;
+              }
+              if (name != null) {
+                if (fixedNameCall) {
+                  String arguments =
+                      node.arguments.map(js.nodeToString).join(',');
+                  features.addElement(tag, '${prefix}${name}(${arguments})');
+                } else {
+                  features.addElement(
+                      tag, '${prefix}${name}(${node.arguments.length})');
+                }
+              }
+            }
+          });
+        }
+
+        registerCalls(Tags.call, code);
+        if (method is DartMethod) {
+          for (ParameterStubMethod stub in method.parameterStubs) {
+            registerCalls(Tags.parameterStub, stub.code, '${stub.name.key}:');
+          }
+        }
+        forEachNode(code, onAssignment: (js.Assignment node) {
+          js.Expression leftHandSide = node.leftHandSide;
+          if (leftHandSide is js.PropertyAccess) {
+            js.Node selector = leftHandSide.selector;
+            String name;
+            if (selector is js.Name) {
+              name = selector.key;
+            } else if (selector is js.LiteralString) {
+              name = selector.value.substring(1, selector.value.length - 1);
+            }
+            if (name != null) {
+              features.addElement(Tags.assignment, '${name}');
+            }
+          }
+        });
+        return features;
       }
     }
     return null;
   }
 
   @override
-  String computeMemberValue(Id id, ir.Member node) {
+  Features computeMemberValue(Id id, ir.Member node) {
     return getMemberValue(_elementMap.getMember(node));
   }
 
   @override
-  String computeNodeValue(Id id, ir.TreeNode node) {
+  Features computeNodeValue(Id id, ir.TreeNode node) {
     if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
       ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
       return getMemberValue(info.callMethod);
diff --git a/tests/compiler/dart2js/codegen/pragma_annotations_test.dart b/tests/compiler/dart2js/codegen/pragma_annotations_test.dart
index d2ae5aa..a4487ec 100644
--- a/tests/compiler/dart2js/codegen/pragma_annotations_test.dart
+++ b/tests/compiler/dart2js/codegen/pragma_annotations_test.dart
@@ -53,11 +53,11 @@
     Expect.isNotNull(method, "Cannot find method '$name'");
     Expect.equals(
         expectNoInline,
-        closedWorld.annotationsData.nonInlinableFunctions.contains(method),
+        closedWorld.annotationsData.hasNoInline(method),
         "Unexpected annotation of 'noInline' on '$method'.");
     Expect.equals(
         expectTryInline,
-        closedWorld.annotationsData.tryInlineFunctions.contains(method),
+        closedWorld.annotationsData.hasTryInline(method),
         "Unexpected annotation of 'tryInline' on '$method'.");
   }
 
diff --git a/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart b/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
index 50487ca..5c72752 100644
--- a/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
+++ b/tests/compiler/dart2js/deferred/dont_inline_deferred_constants_test.dart
@@ -91,7 +91,7 @@
 
 // Make sure that deferred constants are not inlined into the main hunk.
 const Map<String, String> MEMORY_SOURCE_FILES = const {
-  "main.dart": """
+  "main.dart": r"""
 import "dart:async";
 
 import 'lib1.dart' deferred as lib1;
@@ -102,6 +102,8 @@
 class C {
   final p;
   const C(this.p);
+
+  String toString() => 'C($p)';
 }
 
 foo() => print("main");
diff --git a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
index 487af98..b386ea1 100644
--- a/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
+++ b/tests/compiler/dart2js/end_to_end/bad_output_io_test.dart
@@ -44,7 +44,7 @@
 
   final messages = [];
 
-  void info(var message, [kind]) {
+  void info(var message, [kind = Diagnostic.VERBOSE_INFO]) {
     messages.add([message, kind]);
   }
 
diff --git a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
index cfd8f5c..5369eb2 100644
--- a/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
+++ b/tests/compiler/dart2js/equivalence/id_equivalence_helper.dart
@@ -7,6 +7,7 @@
 
 import 'package:compiler/src/colors.dart' as colors;
 import 'package:compiler/src/common.dart';
+import 'package:compiler/compiler_new.dart';
 import 'package:compiler/src/common_elements.dart';
 import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/compiler.dart';
@@ -147,13 +148,16 @@
     {List<String> options: const <String>[],
     bool verbose: false,
     bool testFrontend: false,
+    bool printCode: false,
     bool forUserLibrariesOnly: true,
     bool skipUnprocessedMembers: false,
     bool skipFailedCompilations: false,
     Iterable<Id> globalIds: const <Id>[]}) async {
+  OutputCollector outputCollector = new OutputCollector();
   CompilationResult result = await runCompiler(
       entryPoint: entryPoint,
       memorySourceFiles: memorySourceFiles,
+      outputProvider: outputCollector,
       options: options,
       beforeRun: (compiler) {
         compiler.stopAfterTypeInference =
@@ -163,6 +167,11 @@
     if (skipFailedCompilations) return null;
     Expect.isTrue(result.isSuccess, "Unexpected compilation error.");
   }
+  if (printCode) {
+    print('--code------------------------------------------------------------');
+    print(outputCollector.getOutput('', OutputType.js));
+    print('------------------------------------------------------------------');
+  }
   Compiler compiler = result.compiler;
   dataComputer.onCompilation(compiler);
   dynamic closedWorld = testFrontend
@@ -527,6 +536,7 @@
   bool verbose = args.remove('-v');
   bool shouldContinue = args.remove('-c');
   bool testAfterFailures = args.remove('-a');
+  bool printCode = args.remove('-p');
   bool continued = false;
   bool hasFailures = false;
 
@@ -606,6 +616,7 @@
           entryPoint, memorySourceFiles, dataComputer,
           options: options,
           verbose: verbose,
+          printCode: printCode,
           testFrontend: testFrontend,
           forUserLibrariesOnly: forUserLibrariesOnly,
           globalIds: annotations.globalData.keys);
@@ -699,9 +710,13 @@
     } else {
       List<String> errorsFound = [];
       Features expectedFeatures = Features.fromText(expectedData);
+      Set<String> validatedFeatures = new Set<String>();
       expectedFeatures.forEach((String key, Object expectedValue) {
-        Object actualValue = actualFeatures[key] ?? '';
-        if (expectedValue == '') {
+        validatedFeatures.add(key);
+        Object actualValue = actualFeatures[key];
+        if (!actualFeatures.containsKey(key)) {
+          errorsFound.add('No data found for $key');
+        } else if (expectedValue == '') {
           if (actualValue != '') {
             errorsFound.add('Non-empty data found for $key');
           }
@@ -753,6 +768,15 @@
               "Mismatch for $key: expected '$expectedValue', found '${actualValue}'");
         }
       });
+      actualFeatures.forEach((String key, Object value) {
+        if (!validatedFeatures.contains(key)) {
+          if (value == '') {
+            errorsFound.add("Extra data found '$key'");
+          } else {
+            errorsFound.add("Extra data found $key=$value");
+          }
+        }
+      });
       return errorsFound.isNotEmpty ? errorsFound.join('\n ') : null;
     }
   }
diff --git a/tests/compiler/dart2js/helpers/compiler_helper.dart b/tests/compiler/dart2js/helpers/compiler_helper.dart
index 1bbca1b..9fab31d 100644
--- a/tests/compiler/dart2js/helpers/compiler_helper.dart
+++ b/tests/compiler/dart2js/helpers/compiler_helper.dart
@@ -60,15 +60,21 @@
     options.add(Flags.disableInlining);
   }
 
+  // Pretend this is a dart2js_native test to allow use of 'native' keyword
+  // and import of private libraries.
+  String commonTestPath = 'sdk/tests/compiler';
+  Uri entryPoint = Uri.parse('memory:$commonTestPath/dart2js_native/main.dart');
+
   Map<String, String> source;
   methodName ??= entry;
   if (entry != 'main') {
-    source = {'main.dart': "$code\n\nmain() => $entry;"};
+    source = {entryPoint.path: "$code\n\nmain() => $entry;"};
   } else {
-    source = {'main.dart': code};
+    source = {entryPoint.path: code};
   }
 
   CompilationResult result = await runCompiler(
+      entryPoint: entryPoint,
       memorySourceFiles: source,
       options: options,
       outputProvider: outputCollector);
@@ -101,8 +107,15 @@
   if (minify) {
     options.add(Flags.minify);
   }
+
+  // Pretend this is a dart2js_native test to allow use of 'native' keyword
+  // and import of private libraries.
+  String commonTestPath = 'sdk/tests/compiler';
+  Uri entryPoint = Uri.parse('memory:$commonTestPath/dart2js_native/main.dart');
+
   CompilationResult result = await runCompiler(
-      memorySourceFiles: {'main.dart': code},
+      entryPoint: entryPoint,
+      memorySourceFiles: {entryPoint.path: code},
       options: options,
       outputProvider: outputCollector,
       diagnosticHandler: diagnosticCollector);
diff --git a/tests/compiler/dart2js/helpers/program_lookup.dart b/tests/compiler/dart2js/helpers/program_lookup.dart
index e01108d..cac728c 100644
--- a/tests/compiler/dart2js/helpers/program_lookup.dart
+++ b/tests/compiler/dart2js/helpers/program_lookup.dart
@@ -53,7 +53,7 @@
       for (Fragment fragment in program.fragments) {
         for (Library library in fragment.libraries) {
           assert(!libraryMap.containsKey(library.element));
-          libraryMap[library.element] = new LibraryData(library);
+          libraryMap[library.element] = new LibraryData(library, fragment);
         }
       }
     }
@@ -74,17 +74,25 @@
 
   Method getMethod(FunctionEntity function) {
     if (function.enclosingClass != null) {
-      return getClassData(function.enclosingClass).getMethod(function);
+      return getClassData(function.enclosingClass)?.getMethod(function);
     } else {
-      return getLibraryData(function.library).getMethod(function);
+      return getLibraryData(function.library)?.getMethod(function);
     }
   }
 
   Field getField(FieldEntity field) {
     if (field.enclosingClass != null) {
-      return getClassData(field.enclosingClass).getField(field);
+      return getClassData(field.enclosingClass)?.getField(field);
     } else {
-      return getLibraryData(field.library).getField(field);
+      return getLibraryData(field.library)?.getField(field);
+    }
+  }
+
+  StaticField getStaticField(FieldEntity field) {
+    if (field.enclosingClass != null) {
+      return getClassData(field.enclosingClass)?.getStaticField(field);
+    } else {
+      return getLibraryData(field.library)?.getStaticField(field);
     }
   }
 }
@@ -94,8 +102,9 @@
   Map<ClassEntity, ClassData> _classMap = {};
   Map<FunctionEntity, StaticMethod> _methodMap = {};
   Map<FieldEntity, Field> _fieldMap = {};
+  Map<FieldEntity, StaticField> _staticFieldMap = {};
 
-  LibraryData(this.library) {
+  LibraryData(this.library, Fragment fragment) {
     for (Class cls in library.classes) {
       assert(!_classMap.containsKey(cls.element));
       _classMap[cls.element] = new ClassData(cls);
@@ -112,7 +121,8 @@
         _methodMap[method.element] = method;
       }
     }
-    for (Field field in library.staticFieldsForReflection) {
+
+    void addField(Field field) {
       ClassEntity enclosingClass = field.element?.enclosingClass;
       if (enclosingClass != null) {
         ClassData data =
@@ -124,6 +134,30 @@
         _fieldMap[field.element] = field;
       }
     }
+
+    for (Field field in library.staticFieldsForReflection) {
+      addField(field);
+    }
+
+    void addStaticField(StaticField field) {
+      ClassEntity enclosingClass = field.element?.enclosingClass;
+      if (enclosingClass != null) {
+        ClassData data =
+            _classMap.putIfAbsent(enclosingClass, () => new ClassData(null));
+        assert(!data._fieldMap.containsKey(field.element));
+        data._staticFieldMap[field.element] = field;
+      } else if (field.element != null) {
+        assert(!_fieldMap.containsKey(field.element));
+        _staticFieldMap[field.element] = field;
+      }
+    }
+
+    for (StaticField field in fragment.staticNonFinalFields) {
+      addStaticField(field);
+    }
+    for (StaticField field in fragment.staticLazilyInitializedFields) {
+      addStaticField(field);
+    }
   }
 
   ClassData getClassData(ClassEntity element) {
@@ -137,12 +171,20 @@
   Field getField(FieldEntity field) {
     return _fieldMap[field];
   }
+
+  StaticField getStaticField(FieldEntity field) {
+    return _staticFieldMap[field];
+  }
+
+  String toString() => 'LibraryData(library=$library,_classMap=$_classMap,'
+      '_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
 }
 
 class ClassData {
   final Class cls;
   Map<FunctionEntity, Method> _methodMap = {};
   Map<FieldEntity, Field> _fieldMap = {};
+  Map<FieldEntity, StaticField> _staticFieldMap = {};
   Map<FieldEntity, StubMethod> _checkedSetterMap = {};
 
   ClassData(this.cls) {
@@ -170,24 +212,35 @@
     return _fieldMap[field];
   }
 
+  StaticField getStaticField(FieldEntity field) {
+    return _staticFieldMap[field];
+  }
+
   StubMethod getCheckedSetter(FieldEntity field) {
     return _checkedSetterMap[field];
   }
+
+  String toString() => 'ClassData(cls=$cls,'
+      '_methodMap=$_methodMap,_fieldMap=$_fieldMap)';
 }
 
 void forEachNode(js.Node root,
     {void Function(js.Call) onCall,
-    void Function(js.PropertyAccess) onPropertyAccess}) {
-  CallbackVisitor visitor =
-      new CallbackVisitor(onCall: onCall, onPropertyAccess: onPropertyAccess);
+    void Function(js.PropertyAccess) onPropertyAccess,
+    void Function(js.Assignment) onAssignment}) {
+  CallbackVisitor visitor = new CallbackVisitor(
+      onCall: onCall,
+      onPropertyAccess: onPropertyAccess,
+      onAssignment: onAssignment);
   root.accept(visitor);
 }
 
 class CallbackVisitor extends js.BaseVisitor {
   final void Function(js.Call) onCall;
   final void Function(js.PropertyAccess) onPropertyAccess;
+  final void Function(js.Assignment) onAssignment;
 
-  CallbackVisitor({this.onCall, this.onPropertyAccess});
+  CallbackVisitor({this.onCall, this.onPropertyAccess, this.onAssignment});
 
   @override
   visitCall(js.Call node) {
@@ -200,4 +253,10 @@
     if (onPropertyAccess != null) onPropertyAccess(node);
     super.visitAccess(node);
   }
+
+  @override
+  visitAssignment(js.Assignment node) {
+    if (onAssignment != null) onAssignment(node);
+    return super.visitAssignment(node);
+  }
 }
diff --git a/tests/compiler/dart2js/impact/impact_test.dart b/tests/compiler/dart2js/impact/impact_test.dart
index e59b077..2dc7d40 100644
--- a/tests/compiler/dart2js/impact/impact_test.dart
+++ b/tests/compiler/dart2js/impact/impact_test.dart
@@ -9,6 +9,7 @@
 import 'package:compiler/src/elements/entities.dart';
 import 'package:compiler/src/ir/util.dart';
 import 'package:compiler/src/kernel/kernel_strategy.dart';
+import 'package:compiler/src/kernel/element_map_impl.dart';
 import 'package:compiler/src/universe/feature.dart';
 import 'package:compiler/src/universe/use.dart';
 import 'package:compiler/src/universe/world_impact.dart';
@@ -20,6 +21,15 @@
 main(List<String> args) {
   asyncTest(() async {
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
+    print('Testing direct computation of ResolutionImpact');
+    print('==================================================================');
+    useImpactDataForTesting = false;
+    await checkTests(dataDir, const ImpactDataComputer(),
+        args: args, testOmit: false, testFrontend: true);
+
+    print('Testing computation of ResolutionImpact through ImpactData');
+    print('==================================================================');
+    useImpactDataForTesting = true;
     await checkTests(dataDir, const ImpactDataComputer(),
         args: args, testOmit: false, testFrontend: true);
   });
diff --git a/tests/compiler/dart2js/inference/data/call_site.dart b/tests/compiler/dart2js/inference/data/call_site.dart
index 5fd4eea..5af853c 100644
--- a/tests/compiler/dart2js/inference/data/call_site.dart
+++ b/tests/compiler/dart2js/inference/data/call_site.dart
@@ -221,8 +221,10 @@
 class A15 {
   /*element: A15.x15:[exact=JSUInt31]*/
   x15(/*[exact=JSUInt31]*/ p1,
-          [/*Value([exact=JSString], value: "s")*/ p2 = "s"]) =>
-      1;
+      [/*Value([exact=JSString], value: "s")*/ p2 = "s"]) {
+    p2. /*Value([exact=JSString], value: "s")*/ length;
+    return 1;
+  }
 }
 
 /*element: test15:[null]*/
diff --git a/tests/compiler/dart2js/inference/data/field_type.dart b/tests/compiler/dart2js/inference/data/field_type.dart
index 8e2e9c04..4f499a9 100644
--- a/tests/compiler/dart2js/inference/data/field_type.dart
+++ b/tests/compiler/dart2js/inference/data/field_type.dart
@@ -352,7 +352,7 @@
   // TODO(johnniwinther): Investigate why these include `null`. The ast version
   // didn't.
 
-  /*element: A16.f16:Union([exact=JSString], [null|exact=JSUInt31])*/
+  /*element: A16.f16:Union([exact=JSUInt31], [null|exact=JSString])*/
   var f16;
 
   /*element: A16.:[exact=A16]*/
diff --git a/tests/compiler/dart2js/inlining/meta_annotations_test.dart b/tests/compiler/dart2js/inlining/meta_annotations_test.dart
index e62db8e..8904107 100644
--- a/tests/compiler/dart2js/inlining/meta_annotations_test.dart
+++ b/tests/compiler/dart2js/inlining/meta_annotations_test.dart
@@ -49,11 +49,11 @@
       Expect.isNotNull(method);
       Expect.equals(
           expectNoInline,
-          closedWorld.annotationsData.nonInlinableFunctions.contains(method),
+          closedWorld.annotationsData.hasNoInline(method),
           "Unexpected annotation of @noInline on '$method'.");
       Expect.equals(
           expectTryInline,
-          closedWorld.annotationsData.tryInlineFunctions.contains(method),
+          closedWorld.annotationsData.hasTryInline(method),
           "Unexpected annotation of @tryInline on '$method'.");
     }
 
diff --git a/tests/compiler/dart2js/member_usage/data/fields.dart b/tests/compiler/dart2js/member_usage/data/fields.dart
index 22a24a9..5d95285 100644
--- a/tests/compiler/dart2js/member_usage/data/fields.dart
+++ b/tests/compiler/dart2js/member_usage/data/fields.dart
@@ -2,13 +2,13 @@
 // for details. All rights reserved. Use of this source code is governed by a
 // BSD-style license that can be found in the LICENSE file.
 
-/*element: field1a:read*/
+/*element: field1a:init,read*/
 var field1a;
 
-/*element: field1b:write*/
+/*element: field1b:init,write*/
 var field1b;
 
-/*element: field1c:read,write*/
+/*element: field1c:init,read,write*/
 var field1c;
 
 /*element: field2a:read*/
@@ -27,15 +27,14 @@
 /*element: field2c=:write*/
 set field2c(_) {}
 
-/*element: Class.:invoke*/
 class Class {
-  /*element: Class.field1a:read*/
+  /*element: Class.field1a:init,read*/
   var field1a;
 
-  /*element: Class.field1b:write*/
+  /*element: Class.field1b:init,write*/
   var field1b;
 
-  /*element: Class.field1c:read,write*/
+  /*element: Class.field1c:init,read,write*/
   var field1c;
 
   /*element: Class.field2a:read*/
@@ -54,6 +53,15 @@
   /*element: Class.field2c=:write*/
   set field2c(_) {}
 
+  /*element: Class.field3a:init*/
+  var field3a = 0;
+
+  /*element: Class.field3b:init*/
+  var field3b;
+
+  /*element: Class.:invoke=(0)*/
+  Class([this.field3b]);
+
   /*element: Class.test:invoke*/
   test() {
     field1a;
diff --git a/tests/compiler/dart2js/member_usage/data/general.dart b/tests/compiler/dart2js/member_usage/data/general.dart
index 0cb1266..ffab22b 100644
--- a/tests/compiler/dart2js/member_usage/data/general.dart
+++ b/tests/compiler/dart2js/member_usage/data/general.dart
@@ -165,7 +165,7 @@
 
 /*element: Class2.:invoke*/
 class Class2 {
-  /*element: Class2.c:read,write*/
+  /*element: Class2.c:init,read*/
   Class1a c;
 }
 
diff --git a/tests/compiler/dart2js/member_usage/data/native.dart b/tests/compiler/dart2js/member_usage/data/native.dart
new file mode 100644
index 0000000..a787af4
--- /dev/null
+++ b/tests/compiler/dart2js/member_usage/data/native.dart
@@ -0,0 +1,84 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// ignore: import_internal_library
+import 'dart:_js_helper';
+
+/*element: field2a:read*/
+@JSName('field2a')
+get field2a => 42;
+
+@JSName('field2a')
+set field2a(_) {}
+
+@JSName('field2b')
+get field2b => 42;
+
+/*element: field2b=:write*/
+@JSName('field2b')
+set field2b(_) {}
+
+/*element: field2c:read*/
+@JSName('field2c')
+get field2c => 42;
+
+/*element: field2c=:write*/
+@JSName('field2c')
+set field2c(_) {}
+
+@Native('Class')
+class Class {
+  /*element: Class.field1a:read*/
+  var field1a;
+
+  /*element: Class.field1b:write*/
+  var field1b;
+
+  /*element: Class.field1c:read,write*/
+  var field1c;
+
+  /*element: Class.field2a:read*/
+  get field2a => 42;
+
+  set field2a(_) {}
+
+  get field2b => 42;
+
+  /*element: Class.field2b=:write*/
+  set field2b(_) {}
+
+  /*element: Class.field2c:read*/
+  get field2c => 42;
+
+  /*element: Class.field2c=:write*/
+  set field2c(_) {}
+
+  var field3a = 0;
+
+  /*element: Class.field3b:init*/
+  var field3b;
+
+  /*element: Class.:invoke=(0)*/
+  Class([this.field3b]);
+
+  /*element: Class.test:invoke*/
+  test() {
+    field1a;
+    field1b = 42;
+    field1c = field1c;
+
+    field2a;
+    field2b = 42;
+    field2c = field2c;
+  }
+}
+
+/*element: main:invoke*/
+main() {
+  field2a;
+  field2b = 42;
+  field2c = field2c;
+
+  new Class().test();
+}
diff --git a/tests/compiler/dart2js/member_usage/member_usage_test.dart b/tests/compiler/dart2js/member_usage/member_usage_test.dart
index 32853b9..b7e95ee 100644
--- a/tests/compiler/dart2js/member_usage/member_usage_test.dart
+++ b/tests/compiler/dart2js/member_usage/member_usage_test.dart
@@ -33,6 +33,7 @@
 }
 
 class Tags {
+  static const String init = 'init';
   static const String read = 'read';
   static const String write = 'write';
   static const String invoke = 'invoke';
@@ -60,6 +61,9 @@
     MemberUsage memberUsage =
         resolutionWorldBuilder.memberUsageForTesting[member];
     if (memberUsage != null) {
+      if (member.isField && memberUsage.hasInit) {
+        features.add(Tags.init);
+      }
       if (memberUsage.hasRead) {
         features.add(Tags.read);
       }
diff --git a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
index aeb3108..ccc0c12 100644
--- a/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
+++ b/tests/compiler/dart2js/model/strong_mode_closed_world_test.dart
@@ -205,7 +205,7 @@
     List<String> expectedLiveMembers =
         expectedLiveMembersMap[cls.name] ?? const <String>[];
     List<String> actualLiveMembers = <String>[];
-    closedWorld.processedMembers.forEach((MemberEntity member) {
+    closedWorld.liveMemberUsage.forEach((MemberEntity member, _) {
       if (member.enclosingClass != cls) return;
       if (member.isConstructor) return;
       actualLiveMembers.add(member.name);
diff --git a/tests/compiler/dart2js/model/subtype_test.dart b/tests/compiler/dart2js/model/subtype_test.dart
index 40907d7..04a8e63 100644
--- a/tests/compiler/dart2js/model/subtype_test.dart
+++ b/tests/compiler/dart2js/model/subtype_test.dart
@@ -31,8 +31,7 @@
 }
 
 void testTypes(TypeEnvironment env, DartType subtype, DartType supertype,
-    bool expectSubtype, bool expectMoreSpecific) {
-  if (expectMoreSpecific == null) expectMoreSpecific = expectSubtype;
+    bool expectSubtype) {
   Expect.equals(expectSubtype, env.isSubtype(subtype, supertype),
       '$subtype <: $supertype');
   if (expectSubtype) {
@@ -41,11 +40,11 @@
   }
 }
 
-void testElementTypes(TypeEnvironment env, String subname, String supername,
-    bool expectSubtype, bool expectMoreSpecific) {
+void testElementTypes(
+    TypeEnvironment env, String subname, String supername, bool expectSubtype) {
   DartType subtype = env.getElementType(subname);
   DartType supertype = env.getElementType(supername);
-  testTypes(env, subtype, supertype, expectSubtype, expectMoreSpecific);
+  testTypes(env, subtype, supertype, expectSubtype);
 }
 
 Future testInterfaceSubtype() async {
@@ -60,9 +59,8 @@
         new C();
       }
       """, expectNoErrors: true).then((env) {
-    void expect(bool expectSubtype, DartType T, DartType S,
-        {bool expectMoreSpecific}) {
-      testTypes(env, T, S, expectSubtype, expectMoreSpecific);
+    void expect(bool expectSubtype, DartType T, DartType S) {
+      testTypes(env, T, S, expectSubtype);
     }
 
     ClassEntity A = env.getClass('A');
@@ -79,7 +77,7 @@
     expect(true, void_, void_);
     expect(true, void_, dynamic_);
     // Unsure about the next one, see dartbug.com/14933.
-    expect(true, dynamic_, void_, expectMoreSpecific: false);
+    expect(true, dynamic_, void_);
     expect(true, void_, Object_);
     expect(true, Object_, void_);
     expect(true, Null_, void_);
@@ -88,28 +86,28 @@
     expect(true, num_, Object_);
     expect(true, int_, Object_);
     expect(true, String_, Object_);
-    expect(true, dynamic_, Object_, expectMoreSpecific: false);
+    expect(true, dynamic_, Object_);
     expect(true, Null_, Object_);
 
     expect(false, Object_, num_);
     expect(true, num_, num_);
     expect(true, int_, num_);
     expect(false, String_, num_);
-    expect(false, dynamic_, num_, expectMoreSpecific: false);
+    expect(false, dynamic_, num_);
     expect(true, Null_, num_);
 
     expect(false, Object_, int_);
     expect(false, num_, int_);
     expect(true, int_, int_);
     expect(false, String_, int_);
-    expect(false, dynamic_, int_, expectMoreSpecific: false);
+    expect(false, dynamic_, int_);
     expect(true, Null_, int_);
 
     expect(false, Object_, String_);
     expect(false, num_, String_);
     expect(false, int_, String_);
     expect(true, String_, String_);
-    expect(false, dynamic_, String_, expectMoreSpecific: false);
+    expect(false, dynamic_, String_);
     expect(true, Null_, String_);
 
     expect(true, Object_, dynamic_);
@@ -123,7 +121,7 @@
     expect(false, num_, Null_);
     expect(false, int_, Null_);
     expect(false, String_, Null_);
-    expect(false, dynamic_, Null_, expectMoreSpecific: false);
+    expect(false, dynamic_, Null_);
     expect(true, Null_, Null_);
 
     DartType A_Object = instantiate(A, [Object_]);
@@ -144,28 +142,28 @@
     expect(true, A_num, A_Object);
     expect(true, A_int, A_Object);
     expect(true, A_String, A_Object);
-    expect(true, A_dynamic, A_Object, expectMoreSpecific: false);
+    expect(true, A_dynamic, A_Object);
     expect(true, A_Null, A_Object);
 
     expect(false, A_Object, A_num);
     expect(true, A_num, A_num);
     expect(true, A_int, A_num);
     expect(false, A_String, A_num);
-    expect(false, A_dynamic, A_num, expectMoreSpecific: false);
+    expect(false, A_dynamic, A_num);
     expect(true, A_Null, A_num);
 
     expect(false, A_Object, A_int);
     expect(false, A_num, A_int);
     expect(true, A_int, A_int);
     expect(false, A_String, A_int);
-    expect(false, A_dynamic, A_int, expectMoreSpecific: false);
+    expect(false, A_dynamic, A_int);
     expect(true, A_Null, A_int);
 
     expect(false, A_Object, A_String);
     expect(false, A_num, A_String);
     expect(false, A_int, A_String);
     expect(true, A_String, A_String);
-    expect(false, A_dynamic, A_String, expectMoreSpecific: false);
+    expect(false, A_dynamic, A_String);
     expect(true, A_Null, A_String);
 
     expect(true, A_Object, A_dynamic);
@@ -179,7 +177,7 @@
     expect(false, A_num, A_Null);
     expect(false, A_int, A_Null);
     expect(false, A_String, A_Null);
-    expect(false, A_dynamic, A_Null, expectMoreSpecific: false);
+    expect(false, A_dynamic, A_Null);
     expect(true, A_Null, A_Null);
 
     DartType B_Object_Object = instantiate(B, [Object_, Object_]);
@@ -210,10 +208,10 @@
     expect(true, B_int_num, A_dynamic);
 
     expect(true, B_dynamic_dynamic, Object_);
-    expect(true, B_dynamic_dynamic, A_Object, expectMoreSpecific: false);
-    expect(false, B_dynamic_dynamic, A_num, expectMoreSpecific: false);
-    expect(false, B_dynamic_dynamic, A_int, expectMoreSpecific: false);
-    expect(false, B_dynamic_dynamic, A_String, expectMoreSpecific: false);
+    expect(true, B_dynamic_dynamic, A_Object);
+    expect(false, B_dynamic_dynamic, A_num);
+    expect(false, B_dynamic_dynamic, A_int);
+    expect(false, B_dynamic_dynamic, A_String);
     expect(true, B_dynamic_dynamic, A_dynamic);
 
     expect(true, B_String_dynamic, Object_);
@@ -226,19 +224,19 @@
     expect(true, B_Object_Object, B_Object_Object);
     expect(true, B_num_num, B_Object_Object);
     expect(true, B_int_num, B_Object_Object);
-    expect(true, B_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
-    expect(true, B_String_dynamic, B_Object_Object, expectMoreSpecific: false);
+    expect(true, B_dynamic_dynamic, B_Object_Object);
+    expect(true, B_String_dynamic, B_Object_Object);
 
     expect(false, B_Object_Object, B_num_num);
     expect(true, B_num_num, B_num_num);
     expect(true, B_int_num, B_num_num);
-    expect(false, B_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
+    expect(false, B_dynamic_dynamic, B_num_num);
     expect(false, B_String_dynamic, B_num_num);
 
     expect(false, B_Object_Object, B_int_num);
     expect(false, B_num_num, B_int_num);
     expect(true, B_int_num, B_int_num);
-    expect(false, B_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
+    expect(false, B_dynamic_dynamic, B_int_num);
     expect(false, B_String_dynamic, B_int_num);
 
     expect(true, B_Object_Object, B_dynamic_dynamic);
@@ -250,8 +248,7 @@
     expect(false, B_Object_Object, B_String_dynamic);
     expect(false, B_num_num, B_String_dynamic);
     expect(false, B_int_num, B_String_dynamic);
-    expect(false, B_dynamic_dynamic, B_String_dynamic,
-        expectMoreSpecific: false);
+    expect(false, B_dynamic_dynamic, B_String_dynamic);
     expect(true, B_String_dynamic, B_String_dynamic);
 
     DartType C_Object_Object = instantiate(C, [Object_, Object_]);
@@ -277,12 +274,11 @@
     expect(true, C_int_String, B_dynamic_dynamic);
     expect(true, C_int_String, B_String_dynamic);
 
-    expect(true, C_dynamic_dynamic, B_Object_Object, expectMoreSpecific: false);
-    expect(false, C_dynamic_dynamic, B_num_num, expectMoreSpecific: false);
-    expect(false, C_dynamic_dynamic, B_int_num, expectMoreSpecific: false);
+    expect(true, C_dynamic_dynamic, B_Object_Object);
+    expect(false, C_dynamic_dynamic, B_num_num);
+    expect(false, C_dynamic_dynamic, B_int_num);
     expect(true, C_dynamic_dynamic, B_dynamic_dynamic);
-    expect(false, C_dynamic_dynamic, B_String_dynamic,
-        expectMoreSpecific: false);
+    expect(false, C_dynamic_dynamic, B_String_dynamic);
 
     expect(false, C_int_String, A_int);
     expect(true, C_int_String, A_String);
@@ -319,9 +315,8 @@
         a.m5(null, null);
       }
       """, expectNoErrors: true).then((env) {
-    void expect(bool expectSubtype, DartType T, DartType S,
-        {bool expectMoreSpecific}) {
-      testTypes(env, T, S, expectSubtype, expectMoreSpecific);
+    void expect(bool expectSubtype, DartType T, DartType S) {
+      testTypes(env, T, S, expectSubtype);
     }
 
     ClassEntity classA = env.getClass('A');
@@ -338,7 +333,7 @@
     expect(false, A, call);
     expect(false, call, m1);
     expect(false, A, m1);
-    expect(false, A, m2, expectMoreSpecific: false);
+    expect(false, A, m2);
     expect(false, A, m3);
     expect(false, A, m4);
     expect(false, A, m5);
@@ -388,9 +383,8 @@
 }
 
 functionSubtypingHelper(TypeEnvironment env) {
-  void expect(bool expectSubtype, String sub, String sup,
-      {bool expectMoreSpecific}) {
-    testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific);
+  void expect(bool expectSubtype, String sub, String sup) {
+    testElementTypes(env, sub, sup, expectSubtype);
   }
 
   // () -> int <: Function
@@ -403,7 +397,7 @@
   // () -> dynamic <: () -> void
   expect(true, '_', 'void_');
   // () -> void <: () -> dynamic
-  expect(true, 'void_', '_', expectMoreSpecific: false);
+  expect(true, 'void_', '_');
 
   // () -> int <: () -> void
   expect(true, 'int_', 'void_');
@@ -426,7 +420,7 @@
   // (int) -> int <: (int) -> int
   expect(true, 'int__int', 'int__int2');
   // (Object) -> int <: (int) -> Object
-  expect(true, 'int__Object', 'Object__int', expectMoreSpecific: false);
+  expect(true, 'int__Object', 'Object__int');
   // (int) -> int <: (double) -> int
   expect(false, 'int__int', 'int__double');
   // () -> int <: (int) -> int
@@ -482,9 +476,8 @@
 }
 
 functionSubtypingOptionalHelper(TypeEnvironment env) {
-  void expect(bool expectSubtype, String sub, String sup,
-      {bool expectMoreSpecific}) {
-    testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific);
+  void expect(bool expectSubtype, String sub, String sup) {
+    testElementTypes(env, sub, sup, expectSubtype);
   }
 
   // Test ([int])->void <: ()->void.
@@ -496,7 +489,7 @@
   // Test ([int])->void <: ([int])->void.
   expect(true, 'void___int', 'void___int2');
   // Test ([Object])->void <: ([int])->void.
-  expect(true, 'void___Object', 'void___int', expectMoreSpecific: false);
+  expect(true, 'void___Object', 'void___int');
   // Test ([int])->void <: ([Object])->void.
   expect(false, 'void___int', 'void___Object');
   // Test (int,[int])->void <: (int)->void.
@@ -520,7 +513,7 @@
   // Test ([int,int])->void <: ([int])->void.
   expect(true, 'void___int_int', 'void___int');
   // Test ([Object,int])->void <: ([int])->void.
-  expect(true, 'void___Object_int', 'void___int', expectMoreSpecific: false);
+  expect(true, 'void___Object_int', 'void___int');
 }
 
 const List<FunctionTypeData> namedFunctionTypesData = const <FunctionTypeData>[
@@ -564,9 +557,8 @@
 }
 
 functionSubtypingNamedHelper(TypeEnvironment env) {
-  expect(bool expectSubtype, String sub, String sup,
-      {bool expectMoreSpecific}) {
-    testElementTypes(env, sub, sup, expectSubtype, expectMoreSpecific);
+  expect(bool expectSubtype, String sub, String sup) {
+    testElementTypes(env, sub, sup, expectSubtype);
   }
 
   // Test ({int a})->void <: ()->void.
@@ -580,7 +572,7 @@
   // Test ({int a})->void <: ({int b})->void.
   expect(false, 'void___a_int', 'void___b_int');
   // Test ({Object a})->void <: ({int a})->void.
-  expect(true, 'void___a_Object', 'void___a_int', expectMoreSpecific: false);
+  expect(true, 'void___a_Object', 'void___a_int');
   // Test ({int a})->void <: ({Object a})->void.
   expect(false, 'void___a_int', 'void___a_Object');
   // Test (int,{int a})->void <: (int,{int a})->void.
@@ -617,9 +609,8 @@
         new F();
       }
       """, expectNoErrors: true).then((env) {
-    void expect(bool expectSubtype, DartType T, DartType S,
-        {bool expectMoreSpecific}) {
-      testTypes(env, T, S, expectSubtype, expectMoreSpecific);
+    void expect(bool expectSubtype, DartType T, DartType S) {
+      testTypes(env, T, S, expectSubtype);
     }
 
     TypeVariableType getTypeVariable(ClassEntity cls, int index) {
diff --git a/tests/compiler/dart2js/optimization/data/arithmetic.dart b/tests/compiler/dart2js/optimization/data/arithmetic.dart
new file mode 100644
index 0000000..f8aad1b
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/arithmetic.dart
@@ -0,0 +1,489 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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() {
+  negate(1);
+  negateNum(1);
+  negateNum(1.5);
+  negateNull(1);
+  negateNull(null);
+  negateString(1);
+  negateString('');
+
+  add(1, 2);
+  addNumInt(1, 2);
+  addNumInt(1.5, 2);
+  addIntNum(2, 1);
+  addIntNum(2, 1.5);
+  addNumNum(1, 1.5);
+  addNumNum(1.5, 1);
+  addIntNull(2, 1);
+  addIntNull(2, null);
+  addNullInt(1, 2);
+  addNullInt(null, 2);
+  addStringInt(1, 2);
+  addStringInt('', 2);
+  addIntString(2, 1);
+  addIntString(2, '');
+
+  subtract(1, 2);
+  subtractNumInt(1, 2);
+  subtractNumInt(1.5, 2);
+  subtractIntNum(2, 1);
+  subtractIntNum(2, 1.5);
+  subtractNumNum(1, 1.5);
+  subtractNumNum(1.5, 1);
+  subtractIntNull(2, 1);
+  subtractIntNull(2, null);
+  subtractNullInt(1, 2);
+  subtractNullInt(null, 2);
+  subtractStringInt(1, 2);
+  subtractStringInt('', 2);
+  subtractIntString(2, 1);
+  subtractIntString(2, '');
+
+  multiply(1, 2);
+  multiplyNumInt(1, 2);
+  multiplyNumInt(1.5, 2);
+  multiplyIntNum(2, 1);
+  multiplyIntNum(2, 1.5);
+  multiplyNumNum(1, 1.5);
+  multiplyNumNum(1.5, 1);
+  multiplyIntNull(2, 1);
+  multiplyIntNull(2, null);
+  multiplyNullInt(1, 2);
+  multiplyNullInt(null, 2);
+  multiplyStringInt(1, 2);
+  multiplyStringInt('', 2);
+  multiplyIntString(2, 1);
+  multiplyIntString(2, '');
+
+  divide(1, 2);
+  divideZero(1);
+  divideNumInt(1, 2);
+  divideNumInt(1.5, 2);
+  divideIntNum(2, 1);
+  divideIntNum(2, 1.5);
+  divideNumNum(1, 1.5);
+  divideNumNum(1.5, 1);
+  divideIntNull(2, 1);
+  divideIntNull(2, null);
+  divideNullInt(1, 2);
+  divideNullInt(null, 2);
+  divideStringInt(1, 2);
+  divideStringInt('', 2);
+  divideIntString(2, 1);
+  divideIntString(2, '');
+
+  truncatingDivide(1, 2);
+  truncatingDivideZero(1);
+  truncatingDivideIntNonZero1(1);
+  truncatingDivideIntNonZero2(2);
+  truncatingDivideNumInt(1, 2);
+  truncatingDivideNumInt(1.5, 2);
+  truncatingDivideNumNonZero(1);
+  truncatingDivideNumNonZero(1.5);
+  truncatingDivideIntNum(2, 1);
+  truncatingDivideIntNum(2, 1.5);
+  truncatingDivideNumNum(1, 1.5);
+  truncatingDivideNumNum(1.5, 1);
+  truncatingDivideIntNull(2, 1);
+  truncatingDivideIntNull(2, null);
+  truncatingDivideNullInt(1, 2);
+  truncatingDivideNullInt(null, 2);
+  truncatingDivideStringInt(1, 2);
+  truncatingDivideStringInt('', 2);
+  truncatingDivideIntString(2, 1);
+  truncatingDivideIntString(2, '');
+
+  abs(1);
+  absNum(1);
+  absNum(1.5);
+  absNull(1);
+  absNull(null);
+  absString(1);
+  absString('');
+
+  round(1);
+  roundNum(1);
+  roundNum(1.5);
+  roundNull(1);
+  roundNull(null);
+  roundString(1);
+  roundString('');
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Negation
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: negate:Specializer=[Negate],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+negate(o) {
+  return -o;
+}
+
+/*element: negateNum:Specializer=[Negate],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+negateNum(o) {
+  return -o;
+}
+
+/*element: negateNull:Specializer=[Negate],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+negateNull(o) {
+  return -o;
+}
+
+/*element: negateString:Specializer=[!Negate]*/
+@pragma('dart2js:noInline')
+negateString(o) {
+  return -o;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Addition
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: add:Specializer=[Add],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+add(a, b) {
+  return a + b;
+}
+
+/*element: addNumInt:Specializer=[Add],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+addNumInt(a, b) {
+  return a + b;
+}
+
+/*element: addIntNum:Specializer=[Add],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+addIntNum(a, b) {
+  return a + b;
+}
+
+/*element: addNumNum:Specializer=[Add],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+addNumNum(a, b) {
+  return a + b;
+}
+
+/*element: addNullInt:Specializer=[Add],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+addNullInt(a, b) {
+  return a + b;
+}
+
+/*element: addIntNull:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+addIntNull(a, b) {
+  return a + b;
+}
+
+/*element: addStringInt:Specializer=[!Add]*/
+@pragma('dart2js:noInline')
+addStringInt(a, b) {
+  return a + b;
+}
+
+/*element: addIntString:Specializer=[Add],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+addIntString(a, b) {
+  return a + b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Subtraction
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: subtract:Specializer=[Subtract],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+subtract(a, b) {
+  return a - b;
+}
+
+/*element: subtractNumInt:Specializer=[Subtract],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+subtractNumInt(a, b) {
+  return a - b;
+}
+
+/*element: subtractIntNum:Specializer=[Subtract],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+subtractIntNum(a, b) {
+  return a - b;
+}
+
+/*element: subtractNumNum:Specializer=[Subtract],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+subtractNumNum(a, b) {
+  return a - b;
+}
+
+/*element: subtractNullInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+subtractNullInt(a, b) {
+  return a - b;
+}
+
+/*element: subtractIntNull:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+subtractIntNull(a, b) {
+  return a - b;
+}
+
+/*element: subtractStringInt:Specializer=[Subtract],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+subtractStringInt(a, b) {
+  return a - b;
+}
+
+/*element: subtractIntString:Specializer=[Subtract],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+subtractIntString(a, b) {
+  return a - b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Multiplication
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: multiply:Specializer=[Multiply],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+multiply(a, b) {
+  return a * b;
+}
+
+/*element: multiplyNumInt:Specializer=[Multiply],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+multiplyNumInt(a, b) {
+  return a * b;
+}
+
+/*element: multiplyIntNum:Specializer=[Multiply],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+multiplyIntNum(a, b) {
+  return a * b;
+}
+
+/*element: multiplyNumNum:Specializer=[Multiply],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+multiplyNumNum(a, b) {
+  return a * b;
+}
+
+/*element: multiplyNullInt:Specializer=[Multiply],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+multiplyNullInt(a, b) {
+  return a * b;
+}
+
+/*element: multiplyIntNull:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+multiplyIntNull(a, b) {
+  return a * b;
+}
+
+/*element: multiplyStringInt:Specializer=[!Multiply]*/
+@pragma('dart2js:noInline')
+multiplyStringInt(a, b) {
+  return a * b;
+}
+
+/*element: multiplyIntString:Specializer=[Multiply],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+multiplyIntString(a, b) {
+  return a * b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Division
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: divide:Specializer=[Divide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+divide(a, b) {
+  return a / b;
+}
+
+/*element: divideZero:Specializer=[Divide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+divideZero(a) {
+  return a / 0;
+}
+
+/*element: divideNumInt:Specializer=[Divide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+divideNumInt(a, b) {
+  return a / b;
+}
+
+/*element: divideIntNum:Specializer=[Divide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+divideIntNum(a, b) {
+  return a / b;
+}
+
+/*element: divideNumNum:Specializer=[Divide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+divideNumNum(a, b) {
+  return a / b;
+}
+
+/*element: divideNullInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+divideNullInt(a, b) {
+  return a / b;
+}
+
+/*element: divideIntNull:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+divideIntNull(a, b) {
+  return a / b;
+}
+
+/*element: divideStringInt:Specializer=[Divide],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+divideStringInt(a, b) {
+  return a / b;
+}
+
+/*element: divideIntString:Specializer=[Divide],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+divideIntString(a, b) {
+  return a / b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Truncating division
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: truncatingDivide:Specializer=[TruncatingDivide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+truncatingDivide(a, b) {
+  return a ~/ 2;
+}
+
+/*element: truncatingDivideZero:Specializer=[!TruncatingDivide]*/
+@pragma('dart2js:noInline')
+truncatingDivideZero(a) {
+  return a ~/ 0;
+}
+
+/*element: truncatingDivideIntNonZero1:Specializer=[TruncatingDivide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+truncatingDivideIntNonZero1(a) {
+  return a ~/ 1;
+}
+
+/*element: truncatingDivideIntNonZero2:Specializer=[TruncatingDivide],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+truncatingDivideIntNonZero2(a) {
+  return a ~/ 2;
+}
+
+/*element: truncatingDivideNumInt:Specializer=[!TruncatingDivide]*/
+@pragma('dart2js:noInline')
+truncatingDivideNumInt(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideNumNonZero:Specializer=[TruncatingDivide._tdivFast],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+truncatingDivideNumNonZero(a) {
+  return a ~/ 2;
+}
+
+/*element: truncatingDivideIntNum:Specializer=[!TruncatingDivide]*/
+@pragma('dart2js:noInline')
+truncatingDivideIntNum(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideNumNum:Specializer=[!TruncatingDivide]*/
+@pragma('dart2js:noInline')
+truncatingDivideNumNum(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideNullInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+truncatingDivideNullInt(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideIntNull:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+truncatingDivideIntNull(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideStringInt:Specializer=[!TruncatingDivide],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+truncatingDivideStringInt(a, b) {
+  return a ~/ b;
+}
+
+/*element: truncatingDivideIntString:Specializer=[!TruncatingDivide],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+truncatingDivideIntString(a, b) {
+  return a ~/ b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// .abs()
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: abs:Specializer=[Abs]*/
+@pragma('dart2js:noInline')
+abs(o) {
+  return o.abs();
+}
+
+/*element: absNum:Specializer=[Abs]*/
+@pragma('dart2js:noInline')
+absNum(o) {
+  return o.abs();
+}
+
+/*element: absNull:Specializer=[Abs]*/
+@pragma('dart2js:noInline')
+absNull(o) {
+  return o.abs();
+}
+
+/*element: absString:Specializer=[!Abs]*/
+@pragma('dart2js:noInline')
+absString(o) {
+  return o.abs();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// .round()
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: round:Specializer=[Round]*/
+@pragma('dart2js:noInline')
+round(o) {
+  return o.round();
+}
+
+/*element: roundNum:Specializer=[Round]*/
+@pragma('dart2js:noInline')
+roundNum(o) {
+  return o.round();
+}
+
+/*element: roundNull:Specializer=[Round]*/
+@pragma('dart2js:noInline')
+roundNull(o) {
+  return o.round();
+}
+
+/*element: roundString:Specializer=[!Round]*/
+@pragma('dart2js:noInline')
+roundString(o) {
+  return o.round();
+}
diff --git a/tests/compiler/dart2js/optimization/data/arithmetic_simplification.dart b/tests/compiler/dart2js/optimization/data/arithmetic_simplification.dart
new file mode 100644
index 0000000..c479a96
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/arithmetic_simplification.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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 constant folding on numbers.
+
+import 'package:expect/expect.dart';
+
+@AssumeDynamic()
+@pragma('dart2js:noInline')
+int confuse(int x) => x;
+
+/*element: intPlusZero:Specializer=[Add,BitAnd]*/
+@pragma('dart2js:noInline')
+intPlusZero() {
+  int x = confuse(0);
+  return (x & 1) + 0;
+}
+
+/*element: zeroPlusInt:Specializer=[Add,BitAnd]*/
+@pragma('dart2js:noInline')
+zeroPlusInt() {
+  int x = confuse(0);
+  return 0 + (x & 1);
+}
+
+/*element: numPlusZero:Specializer=[Add]*/
+@pragma('dart2js:noInline')
+numPlusZero() {
+  num x = confuse(0);
+  return x + 0;
+}
+
+/*element: zeroPlusNum:Specializer=[Add]*/
+@pragma('dart2js:noInline')
+zeroPlusNum() {
+  num x = confuse(0);
+  return 0 + x;
+}
+
+/*element: intTimesOne:Specializer=[BitAnd,Multiply]*/
+@pragma('dart2js:noInline')
+intTimesOne() {
+  int x = confuse(0);
+  return (x & 1) * 1;
+}
+
+/*element: oneTimesInt:Specializer=[BitAnd,Multiply]*/
+@pragma('dart2js:noInline')
+oneTimesInt() {
+  int x = confuse(0);
+  return 1 * (x & 1);
+}
+
+/*element: numTimesOne:Specializer=[Multiply]*/
+@pragma('dart2js:noInline')
+numTimesOne() {
+  num x = confuse(0);
+  return x * 1;
+}
+
+/*element: oneTimesNum:Specializer=[Multiply]*/
+@pragma('dart2js:noInline')
+oneTimesNum() {
+  num x = confuse(0);
+  return 1 * x;
+}
+
+main() {
+  intPlusZero();
+  zeroPlusInt();
+  numPlusZero();
+  zeroPlusNum();
+  intTimesOne();
+  oneTimesInt();
+  numTimesOne();
+  oneTimesNum();
+}
diff --git a/tests/compiler/dart2js/optimization/data/bit.dart b/tests/compiler/dart2js/optimization/data/bit.dart
new file mode 100644
index 0000000..51e3741
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/bit.dart
@@ -0,0 +1,245 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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() {
+  bitNot(1);
+  bitNotNum(1);
+  bitNotNum(1.5);
+  bitNotNull(1);
+  bitNotNull(null);
+  bitNotString(1);
+  bitNotString('');
+
+  bitAnd(1, 2);
+  bitAndNumInt(1, 2);
+  bitAndNumInt(1.5, 2);
+  bitAndIntNum(2, 1);
+  bitAndIntNum(2, 1.5);
+  bitAndNumNum(1, 1.5);
+  bitAndNumNum(1.5, 1);
+  bitAndIntNull(2, 1);
+  bitAndIntNull(2, null);
+  bitAndNullInt(1, 2);
+  bitAndNullInt(null, 2);
+  bitAndStringInt(1, 2);
+  bitAndStringInt('', 2);
+  bitAndIntString(2, 1);
+  bitAndIntString(2, '');
+
+  bitOr(1, 2);
+  bitOrNumInt(1, 2);
+  bitOrNumInt(1.5, 2);
+  bitOrIntNum(2, 1);
+  bitOrIntNum(2, 1.5);
+  bitOrNumNum(1, 1.5);
+  bitOrNumNum(1.5, 1);
+  bitOrIntNull(2, 1);
+  bitOrIntNull(2, null);
+  bitOrNullInt(1, 2);
+  bitOrNullInt(null, 2);
+  bitOrStringInt(1, 2);
+  bitOrStringInt('', 2);
+  bitOrIntString(2, 1);
+  bitOrIntString(2, '');
+
+  bitXor(1, 2);
+  bitXorNumInt(1, 2);
+  bitXorNumInt(1.5, 2);
+  bitXorIntNum(2, 1);
+  bitXorIntNum(2, 1.5);
+  bitXorNumNum(1, 1.5);
+  bitXorNumNum(1.5, 1);
+  bitXorIntNull(2, 1);
+  bitXorIntNull(2, null);
+  bitXorNullInt(1, 2);
+  bitXorNullInt(null, 2);
+  bitXorStringInt(1, 2);
+  bitXorStringInt('', 2);
+  bitXorIntString(2, 1);
+  bitXorIntString(2, '');
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Bitwise not
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: bitNot:Specializer=[BitNot]*/
+@pragma('dart2js:noInline')
+bitNot(o) {
+  return ~o;
+}
+
+/*element: bitNotNum:Specializer=[BitNot]*/
+@pragma('dart2js:noInline')
+bitNotNum(o) {
+  return ~o;
+}
+
+/*element: bitNotNull:Specializer=[BitNot]*/
+@pragma('dart2js:noInline')
+bitNotNull(o) {
+  return ~o;
+}
+
+/*element: bitNotString:Specializer=[!BitNot]*/
+@pragma('dart2js:noInline')
+bitNotString(o) {
+  return ~o;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Bitwise and
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: bitAnd:Specializer=[BitAnd],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitAnd(a, b) {
+  return a & b;
+}
+
+/*element: bitAndNumInt:Specializer=[BitAnd],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitAndNumInt(a, b) {
+  return a & b;
+}
+
+/*element: bitAndIntNum:Specializer=[BitAnd],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitAndIntNum(a, b) {
+  return a & b;
+}
+
+/*element: bitAndNumNum:Specializer=[BitAnd],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitAndNumNum(a, b) {
+  return a & b;
+}
+
+/*element: bitAndNullInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitAndNullInt(a, b) {
+  return a & b;
+}
+
+/*element: bitAndIntNull:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitAndIntNull(a, b) {
+  return a & b;
+}
+
+/*element: bitAndStringInt:Specializer=[BitAnd],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitAndStringInt(a, b) {
+  return a & b;
+}
+
+/*element: bitAndIntString:Specializer=[BitAnd],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitAndIntString(a, b) {
+  return a & b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Bitwise or
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: bitOr:Specializer=[BitOr],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitOr(a, b) {
+  return a | b;
+}
+
+/*element: bitOrNumInt:Specializer=[BitOr],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitOrNumInt(a, b) {
+  return a | b;
+}
+
+/*element: bitOrIntNum:Specializer=[BitOr],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitOrIntNum(a, b) {
+  return a | b;
+}
+
+/*element: bitOrNumNum:Specializer=[BitOr],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitOrNumNum(a, b) {
+  return a | b;
+}
+
+/*element: bitOrNullInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitOrNullInt(a, b) {
+  return a | b;
+}
+
+/*element: bitOrIntNull:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitOrIntNull(a, b) {
+  return a | b;
+}
+
+/*element: bitOrStringInt:Specializer=[BitOr],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitOrStringInt(a, b) {
+  return a | b;
+}
+
+/*element: bitOrIntString:Specializer=[BitOr],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitOrIntString(a, b) {
+  return a | b;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Bitwise xor
+////////////////////////////////////////////////////////////////////////////////
+
+/*element: bitXor:Specializer=[BitXor],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitXor(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorNumInt:Specializer=[BitXor],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitXorNumInt(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorIntNum:Specializer=[BitXor],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitXorIntNum(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorNumNum:Specializer=[BitXor],TypeConversion=[]*/
+@pragma('dart2js:noInline')
+bitXorNumNum(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorNullInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitXorNullInt(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorIntNull:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitXorIntNull(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorStringInt:Specializer=[BitXor],TypeConversion=[kind=receiver&type=num]*/
+@pragma('dart2js:noInline')
+bitXorStringInt(a, b) {
+  return a ^ b;
+}
+
+/*element: bitXorIntString:Specializer=[BitXor],TypeConversion=[kind=argument&type=num]*/
+@pragma('dart2js:noInline')
+bitXorIntString(a, b) {
+  return a ^ b;
+}
diff --git a/tests/compiler/dart2js/optimization/data/field_get.dart b/tests/compiler/dart2js/optimization/data/field_get.dart
index e200302..349edca 100644
--- a/tests/compiler/dart2js/optimization/data/field_get.dart
+++ b/tests/compiler/dart2js/optimization/data/field_get.dart
@@ -56,8 +56,6 @@
   int field4;
 }
 
-// TODO(johnniwinther,sra): Maybe we should optimize cases like this to a direct
-// property access, because all targets are simple fields?
 @pragma('dart2js:noInline')
 method4(Class4a c) {
   return c.field4;
diff --git a/tests/compiler/dart2js/optimization/data/field_set.dart b/tests/compiler/dart2js/optimization/data/field_set.dart
index 953fe07..3c19021 100644
--- a/tests/compiler/dart2js/optimization/data/field_set.dart
+++ b/tests/compiler/dart2js/optimization/data/field_set.dart
@@ -10,9 +10,13 @@
   method3(new Class3b());
   method4(new Class4a());
   method4(new Class4b());
+  method5(new Class5a());
+  method6(new Class6a());
+  method6(new Class6b());
 }
 
 class Class1a {
+  @pragma('dart2js:noElision')
   int field1;
 }
 
@@ -23,6 +27,7 @@
 }
 
 class Class2a {
+  @pragma('dart2js:noElision')
   int field2 = 42;
 }
 
@@ -56,9 +61,29 @@
   int field4;
 }
 
-// TODO(johnniwinther,sra): Maybe we should optimize cases like this to a direct
-// property write, because all targets are simple fields?
 @pragma('dart2js:noInline')
 method4(Class4a c) {
   c.field4 = 42;
 }
+
+class Class5a {
+  int field5;
+}
+
+/*element: method5:FieldSet=[removed=field5]*/
+@pragma('dart2js:noInline')
+method5(Class5a c) {
+  c.field5 = 42;
+}
+
+class Class6a {
+  int field6 = 42;
+}
+
+class Class6b extends Class6a {}
+
+/*element: method6:FieldSet=[removed=field6]*/
+@pragma('dart2js:noInline')
+method6(Class6a c) {
+  c.field6 = 42;
+}
diff --git a/tests/compiler/dart2js/optimization/data/index.dart b/tests/compiler/dart2js/optimization/data/index.dart
new file mode 100644
index 0000000..12586ad
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/index.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 'dart:collection';
+
+/*element: dynamicIndex:Specializer=[!Index]*/
+@pragma('dart2js:noInline')
+dynamicIndex(var list) {
+  return list[0]; // This not known to be an indexable primitive.
+}
+
+/*element: unknownListIndex:Specializer=[!Index]*/
+@pragma('dart2js:noInline')
+unknownListIndex(List list) {
+  return list[0]; // This not known to be an indexable primitive.
+}
+
+/*element: possiblyNullMutableListIndex:Specializer=[Index]*/
+@pragma('dart2js:noInline')
+possiblyNullMutableListIndex(bool b) {
+  var list = b ? [0] : null;
+  return list[0];
+}
+
+/*element: mutableListIndex:Specializer=[Index]*/
+@pragma('dart2js:noInline')
+mutableListIndex() {
+  var list = [0];
+  return list[0];
+}
+
+/*element: mutableListDynamicIndex:Specializer=[Index]*/
+@pragma('dart2js:noInline')
+mutableListDynamicIndex(dynamic index) {
+  var list = [0];
+  return list[index]; // CFE inserts an implicit cast of the index.
+}
+
+/*strong.element: mutableDynamicListDynamicIndex:Specializer=[!Index]*/
+/*omit.element: mutableDynamicListDynamicIndex:Specializer=[Index]*/
+@pragma('dart2js:noInline')
+mutableDynamicListDynamicIndex(dynamic index) {
+  dynamic list = [0];
+  return list[index];
+}
+
+main() {
+  dynamicIndex([]);
+  dynamicIndex({});
+  unknownListIndex([]);
+  unknownListIndex(new MyList());
+  possiblyNullMutableListIndex(true);
+  possiblyNullMutableListIndex(false);
+  mutableListIndex();
+  mutableListDynamicIndex(0);
+  mutableListDynamicIndex('');
+  mutableDynamicListDynamicIndex(0);
+  mutableDynamicListDynamicIndex('');
+}
+
+class MyList<E> extends ListBase<E> {
+  E operator [](int index) => null;
+  void operator []=(int index, E value) {}
+  int get length => 0;
+  void set length(int value) {}
+}
diff --git a/tests/compiler/dart2js/optimization/data/index_assign.dart b/tests/compiler/dart2js/optimization/data/index_assign.dart
new file mode 100644
index 0000000..35c03ff
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/index_assign.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.
+
+/*element: dynamicIndexAssign:Specializer=[!IndexAssign]*/
+@pragma('dart2js:noInline')
+dynamicIndexAssign(var list) {
+  list[0] = 1;
+}
+
+/*strong.element: unknownListIndexAssign:Specializer=[!IndexAssign]*/
+/*omit.element: unknownListIndexAssign:Specializer=[IndexAssign]*/
+@pragma('dart2js:noInline')
+unknownListIndexAssign(List list) {
+  list[0] = 1;
+}
+
+/*strong.element: possiblyNullMutableListIndexAssign:Specializer=[!IndexAssign]*/
+/*omit.element: possiblyNullMutableListIndexAssign:Specializer=[IndexAssign]*/
+@pragma('dart2js:noInline')
+possiblyNullMutableListIndexAssign(bool b) {
+  var list = b ? [0] : null;
+  list[0] = 1;
+}
+
+/*strong.element: mutableListIndexAssign:Specializer=[!IndexAssign]*/
+/*omit.element: mutableListIndexAssign:Specializer=[IndexAssign]*/
+@pragma('dart2js:noInline')
+mutableListIndexAssign() {
+  var list = [0];
+  list[0] = 1;
+}
+
+/*strong.element: mutableListDynamicIndexAssign:Specializer=[!IndexAssign]*/
+/*omit.element: mutableListDynamicIndexAssign:Specializer=[IndexAssign]*/
+@pragma('dart2js:noInline')
+mutableListDynamicIndexAssign(dynamic index) {
+  var list = [0];
+  list[index] = 1;
+}
+
+/*strong.element: mutableListDynamicValueIndexAssign:Specializer=[!IndexAssign]*/
+/*omit.element: mutableListDynamicValueIndexAssign:Specializer=[IndexAssign]*/
+@pragma('dart2js:noInline')
+mutableListDynamicValueIndexAssign(dynamic value) {
+  var list = [0];
+  list[0] = value;
+}
+
+/*element: immutableListIndexAssign:Specializer=[!IndexAssign]*/
+@pragma('dart2js:noInline')
+immutableListIndexAssign() {
+  var list = const [0];
+  list[0] = 1;
+}
+
+main() {
+  dynamicIndexAssign([]);
+  dynamicIndexAssign({});
+  unknownListIndexAssign([]);
+  unknownListIndexAssign(null);
+  possiblyNullMutableListIndexAssign(true);
+  possiblyNullMutableListIndexAssign(false);
+  mutableListIndexAssign();
+  mutableListDynamicIndexAssign(0);
+  mutableListDynamicIndexAssign('');
+  mutableListDynamicValueIndexAssign(0);
+  mutableListDynamicValueIndexAssign('');
+  immutableListIndexAssign();
+}
diff --git a/tests/compiler/dart2js/optimization/data/modulo_remainder.dart b/tests/compiler/dart2js/optimization/data/modulo_remainder.dart
new file mode 100644
index 0000000..9139d26
--- /dev/null
+++ b/tests/compiler/dart2js/optimization/data/modulo_remainder.dart
@@ -0,0 +1,78 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/*element: mod1:Specializer=[Modulo]*/
+@pragma('dart2js:noInline')
+mod1(param) {
+  var a = param ? 0xFFFFFFFF : 1;
+  return a % 2;
+  // present: ' % 2'
+  // absent: '$mod'
+}
+
+/*element: mod2:Specializer=[!Modulo]*/
+@pragma('dart2js:noInline')
+mod2(param) {
+  var a = param ? 0xFFFFFFFF : -0.0;
+  return a % 2;
+  // Cannot optimize due to potential -0.
+  // present: '$mod'
+  // absent: ' % 2'
+}
+
+/*element: mod3:Specializer=[Modulo]*/
+@pragma('dart2js:noInline')
+mod3(param) {
+  var a = param ? 0xFFFFFFFF : -0.0;
+  return (a + 1) % 2;
+  // 'a + 1' cannot be -0.0, so we can optimize.
+  // present: ' % 2'
+  // absent: '$mod'
+}
+
+/*element: rem1:Specializer=[Remainder]*/
+@pragma('dart2js:noInline')
+rem1(param) {
+  var a = param ? 0xFFFFFFFF : 1;
+  return a.remainder(2);
+  // Above can be compiled to '%'.
+  // present: ' % 2'
+  // absent: 'remainder'
+}
+
+/*element: rem2:Specializer=[Remainder]*/
+@pragma('dart2js:noInline')
+rem2(param) {
+  var a = param ? 123.4 : -1;
+  return a.remainder(3);
+  // Above can be compiled to '%'.
+  // present: ' % 3'
+  // absent: 'remainder'
+}
+
+/*element: rem3:Specializer=[!Remainder]*/
+@pragma('dart2js:noInline')
+rem3(param) {
+  var a = param ? 123 : null;
+  return 100.remainder(a);
+  // No specialization for possibly null inputs.
+  // present: 'remainder'
+  // absent: '%'
+}
+
+main() {
+  mod1(true);
+  mod1(false);
+  mod2(true);
+  mod2(false);
+  mod3(true);
+  mod3(false);
+
+  rem1(true);
+  rem1(false);
+  rem2(true);
+  rem2(false);
+  rem3(true);
+  rem3(false);
+}
diff --git a/tests/compiler/dart2js/optimization/optimization_test.dart b/tests/compiler/dart2js/optimization/optimization_test.dart
index 0f2d013..1f56a1a 100644
--- a/tests/compiler/dart2js/optimization/optimization_test.dart
+++ b/tests/compiler/dart2js/optimization/optimization_test.dart
@@ -5,6 +5,7 @@
 import 'dart:io';
 import 'package:async_helper/async_helper.dart';
 import 'package:compiler/src/closure.dart';
+import 'package:compiler/src/commandline_options.dart';
 import 'package:compiler/src/common.dart';
 import 'package:compiler/src/compiler.dart';
 import 'package:compiler/src/diagnostics/diagnostic_listener.dart';
@@ -22,29 +23,35 @@
 main(List<String> args) {
   asyncTest(() async {
     Directory dataDir = new Directory.fromUri(Platform.script.resolve('data'));
-    await checkTests(dataDir, const OptimizationDataComputer(), args: args);
+    bool strict = args.contains('-s');
+    await checkTests(dataDir, new OptimizationDataComputer(strict: strict),
+        options: [Flags.disableInlining], args: args);
   });
 }
 
-class OptimizationDataValidator implements DataInterpreter<OptimizationLog> {
-  const OptimizationDataValidator();
+class OptimizationDataValidator
+    implements DataInterpreter<OptimizationTestLog> {
+  final bool strict;
+
+  const OptimizationDataValidator({this.strict: false});
 
   @override
-  String getText(OptimizationLog actualData) {
+  String getText(OptimizationTestLog actualData) {
     Features features = new Features();
     for (OptimizationLogEntry entry in actualData.entries) {
-      features.addElement(entry.tag, entry.features.getText());
+      features.addElement(
+          entry.tag, entry.features.getText().replaceAll(',', '&'));
     }
     return features.getText();
   }
 
   @override
-  bool isEmpty(OptimizationLog actualData) {
+  bool isEmpty(OptimizationTestLog actualData) {
     return actualData == null || actualData.entries.isEmpty;
   }
 
   @override
-  String isAsExpected(OptimizationLog actualLog, String expectedLog) {
+  String isAsExpected(OptimizationTestLog actualLog, String expectedLog) {
     expectedLog ??= '';
     if (expectedLog == '') {
       return actualLog.entries.isEmpty
@@ -60,8 +67,12 @@
     expectedLogEntries.forEach((String tag, dynamic expectedEntryData) {
       List<OptimizationLogEntry> actualDataForTag =
           actualDataEntries.where((data) => data.tag == tag).toList();
-      if (expectedEntryData == '' ||
-          expectedEntryData is List && expectedEntryData.isEmpty) {
+      for (OptimizationLogEntry entry in actualDataForTag) {
+        actualDataEntries.remove(entry);
+      }
+      if (expectedEntryData == '') {
+        errorsFound.add("Unknown expected entry '$tag'");
+      } else if (expectedEntryData is List && expectedEntryData.isEmpty) {
         if (actualDataForTag.isNotEmpty) {
           errorsFound.add('Non-empty log found for tag $tag');
         }
@@ -69,7 +80,14 @@
         // Anything allowed.
       } else if (expectedEntryData is List) {
         for (Object object in expectedEntryData) {
-          Features expectedLogEntry = Features.fromText('$object');
+          String expectedLogEntryText = '$object';
+          bool expectMatch = true;
+          if (expectedLogEntryText.startsWith('!')) {
+            expectedLogEntryText = expectedLogEntryText.substring(1);
+            expectMatch = false;
+          }
+          expectedLogEntryText = expectedLogEntryText.replaceAll('&', ',');
+          Features expectedLogEntry = Features.fromText(expectedLogEntryText);
           bool matchFound = false;
           for (OptimizationLogEntry actualLogEntry in actualDataForTag) {
             bool validData = true;
@@ -85,27 +103,40 @@
               break;
             }
           }
-          if (!matchFound) {
-            errorsFound.add("No match found for $tag=[$object]");
+          if (expectMatch) {
+            if (!matchFound) {
+              errorsFound.add("No match found for $tag=[$object]");
+            }
+          } else {
+            if (matchFound) {
+              errorsFound.add("Unexpected match found for $tag=[$object]");
+            }
           }
         }
       } else {
-        errorsFound.add("Unknown expected entry '$expectedEntryData'");
+        errorsFound.add("Unknown expected entry $tag=$expectedEntryData");
       }
     });
+    if (strict) {
+      for (OptimizationLogEntry entry in actualDataEntries) {
+        errorsFound.add("Extra entry ${entry.tag}=${entry.features.getText()}");
+      }
+    }
     return errorsFound.isNotEmpty ? errorsFound.join(', ') : null;
   }
 }
 
-class OptimizationDataComputer extends DataComputer<OptimizationLog> {
-  const OptimizationDataComputer();
+class OptimizationDataComputer extends DataComputer<OptimizationTestLog> {
+  final bool strict;
+
+  const OptimizationDataComputer({this.strict: false});
 
   /// Compute type inference data for [member] from kernel based inference.
   ///
   /// Fills [actualMap] with the data.
   @override
   void computeMemberData(Compiler compiler, MemberEntity member,
-      Map<Id, ActualData<OptimizationLog>> actualMap,
+      Map<Id, ActualData<OptimizationTestLog>> actualMap,
       {bool verbose: false}) {
     JsClosedWorld closedWorld = compiler.backendClosedWorldForTesting;
     JsToElementMap elementMap = closedWorld.elementMap;
@@ -116,31 +147,31 @@
   }
 
   @override
-  DataInterpreter<OptimizationLog> get dataValidator =>
-      const OptimizationDataValidator();
+  DataInterpreter<OptimizationTestLog> get dataValidator =>
+      new OptimizationDataValidator(strict: strict);
 }
 
 /// AST visitor for computing inference data for a member.
-class OptimizationIrComputer extends IrDataExtractor<OptimizationLog> {
+class OptimizationIrComputer extends IrDataExtractor<OptimizationTestLog> {
   final JavaScriptBackend backend;
   final JsToElementMap _elementMap;
   final ClosureData _closureDataLookup;
 
   OptimizationIrComputer(
       DiagnosticReporter reporter,
-      Map<Id, ActualData<OptimizationLog>> actualMap,
+      Map<Id, ActualData<OptimizationTestLog>> actualMap,
       this._elementMap,
       MemberEntity member,
       this.backend,
       this._closureDataLookup)
       : super(reporter, actualMap);
 
-  OptimizationLog getLog(MemberEntity member) {
+  OptimizationTestLog getLog(MemberEntity member) {
     SsaFunctionCompiler functionCompiler = backend.functionCompiler;
     return functionCompiler.optimizer.loggersForTesting[member];
   }
 
-  OptimizationLog getMemberValue(MemberEntity member) {
+  OptimizationTestLog getMemberValue(MemberEntity member) {
     if (member is FunctionEntity) {
       return getLog(member);
     }
@@ -148,12 +179,12 @@
   }
 
   @override
-  OptimizationLog computeMemberValue(Id id, ir.Member node) {
+  OptimizationTestLog computeMemberValue(Id id, ir.Member node) {
     return getMemberValue(_elementMap.getMember(node));
   }
 
   @override
-  OptimizationLog computeNodeValue(Id id, ir.TreeNode node) {
+  OptimizationTestLog computeNodeValue(Id id, ir.TreeNode node) {
     if (node is ir.FunctionExpression || node is ir.FunctionDeclaration) {
       ClosureRepresentationInfo info = _closureDataLookup.getClosureInfo(node);
       return getMemberValue(info.callMethod);
diff --git a/tests/compiler/dart2js/rti/data/no_such_method1.dart b/tests/compiler/dart2js/rti/data/no_such_method1.dart
index 3694cb0..22f13c2 100644
--- a/tests/compiler/dart2js/rti/data/no_such_method1.dart
+++ b/tests/compiler/dart2js/rti/data/no_such_method1.dart
@@ -5,7 +5,7 @@
 import 'package:expect/expect.dart';
 
 class C {
-  /*element: C.noSuchMethod:selectors=[Selector(call, call, arity=0, types=2),Selector(call, foo, arity=0, types=2)]*/
+  /*element: C.noSuchMethod:needsArgs,selectors=[Selector(call, call, arity=0, types=2),Selector(call, foo, arity=0, types=2)]*/
   noSuchMethod(i) => i.typeArguments;
 }
 
diff --git a/tests/compiler/dart2js/rti/data/no_such_method2.dart b/tests/compiler/dart2js/rti/data/no_such_method2.dart
index 81d823c..fc60960 100644
--- a/tests/compiler/dart2js/rti/data/no_such_method2.dart
+++ b/tests/compiler/dart2js/rti/data/no_such_method2.dart
@@ -5,7 +5,7 @@
 import 'package:expect/expect.dart';
 
 class C {
-  /*element: C.noSuchMethod:selectors=[Selector(call, call, arity=0, types=2),Selector(call, foo, arity=0, types=2)]*/
+  /*element: C.noSuchMethod:needsArgs,selectors=[Selector(call, call, arity=0, types=2),Selector(call, foo, arity=0, types=2)]*/
   noSuchMethod(i) => i.typeArguments;
 }
 
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart
index f9a6d06..4170f29 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters.dart
@@ -7,6 +7,15 @@
 main() {
   var c = new Class();
   c. /*1:main*/ instancePositional1(0);
+
+  // Use all optional parameters to ensure that they are not elided.
+  var d = new Class();
+  d.instancePositional1(null, null, null);
+  d.instancePositional2(null, null, null);
+  d.instanceNamed1(null, b: null, c: null, d: null);
+  d.instanceNamed2(null, b: null, c: null, d: null);
+  d.instanceNamed3(null, b: null, c: null, d: null);
+  d.instanceNamed4(null, b: null, c: null, d: null);
 }
 
 class Class {
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/parameters_elided.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters_elided.dart
new file mode 100644
index 0000000..cb0bade
--- /dev/null
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/parameters_elided.dart
@@ -0,0 +1,70 @@
+// 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:meta/dart2js.dart';
+
+main() {
+  var c = new Class();
+  c. /*1:main*/ instancePositional1(0);
+}
+
+class Class {
+  @noInline
+  instancePositional1(a, [b = 42, c = 87]) {
+    print('instancePositional1($a,$b,$c)');
+    /*2:Class.instancePositional1*/ instancePositional2(1, 2);
+  }
+
+  @noInline
+  instancePositional2(a, [b = 42, c = 87]) {
+    print('instancePositional2($a,$b,$c)');
+    /*3:Class.instancePositional2*/ instancePositional3(3, 4, 5);
+  }
+
+  @noInline
+  instancePositional3(a, [b = 42, c = 87]) {
+    print('instancePositional3($a,$b,$c)');
+    /*4:Class.instancePositional3*/ instanceNamed1(0);
+  }
+
+  @noInline
+  instanceNamed1(a, {b: 42, c: 87, d: 735}) {
+    print('instanceNamed1($a,b:$b,c:$c,d:$d)');
+    /*5:Class.instanceNamed1*/ instanceNamed2(1, b: 2);
+  }
+
+  @noInline
+  instanceNamed2(a, {b: 42, c: 87, d: 735}) {
+    print('instanceNamed2($a,b:$b,c:$c,d:$d)');
+    /*6:Class.instanceNamed2*/ instanceNamed3(3, c: 123);
+  }
+
+  @noInline
+  instanceNamed3(a, {b: 42, c: 87, d: 735}) {
+    print('instanceNamed3($a,b:$b,c:$c,d:$d)');
+    /*7:Class.instanceNamed3*/ instanceNamed4(4, c: 45, b: 76);
+  }
+
+  @noInline
+  instanceNamed4(a, {b: 42, c: 87, d: 735}) {
+    print('instanceNamed4($a,b:$b,c:$c,d:$d)');
+    /*8:Class.instanceNamed4*/ instanceNamed5(5, c: 6, b: 7, d: 8);
+  }
+
+  @noInline
+  instanceNamed5(a, {b: 42, c: 87, d: 735}) {
+    print('instanceNamed5($a,b:$b,c:$c,d:$d)');
+    /*12:Class.instanceNamed5[function-entry$0].local*/ local([e = 42]) {
+      print('instanceNamed5.local($e)');
+      /*13:Class.instanceNamed5.local*/ throw '>ExceptionMarker<';
+    }
+
+    var anonymous = /*10:Class.instanceNamed5[function-entry$0].<anonymous function>*/ (
+        {f: 87}) {
+      print('instanceNamed5.<anonymous(f:$f)');
+      /*11:Class.instanceNamed5.<anonymous function>*/ local();
+    };
+    anonymous. /*9:Class.instanceNamed5*/ call();
+  }
+}
diff --git a/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
index 9b5ab60..5ffcaad 100644
--- a/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
+++ b/tests/compiler/dart2js/sourcemaps/stacktrace/setter_inlining.dart
@@ -1,3 +1,7 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
 class MyClass {
   int fieldName;
 
@@ -13,4 +17,5 @@
   confuse(new MyClass(3));
   var m = confuse(null);
   m. /*0:main*/ setterName = 2;
+  print(m.fieldName);
 }
diff --git a/tests/compiler/dart2js_extra/bounds_check3c_test.dart b/tests/compiler/dart2js_extra/bounds_check3c_test.dart
new file mode 100644
index 0000000..696afdd
--- /dev/null
+++ b/tests/compiler/dart2js_extra/bounds_check3c_test.dart
@@ -0,0 +1,15 @@
+// Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'package:expect/expect.dart';
+
+main() {
+  dynamic c = new Class();
+  Expect.equals(c.method(), num);
+}
+
+class Class {
+  @pragma('dart2js:noInline')
+  method<S extends num>() => S;
+}
diff --git a/tests/compiler/dart2js_extra/deferred_with_csp_nonce2_test.dart b/tests/compiler/dart2js_extra/deferred_with_csp_nonce2_test.dart
new file mode 100644
index 0000000..5d6f596
--- /dev/null
+++ b/tests/compiler/dart2js_extra/deferred_with_csp_nonce2_test.dart
@@ -0,0 +1,38 @@
+// 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.
+
+// Test that code loaded via deferred imports uses the same nonce value as the
+// main page.
+
+import "deferred_with_csp_nonce_lib.dart" deferred as lib;
+import "package:expect/expect.dart";
+import "package:async_helper/async_helper.dart";
+import "dart:html";
+
+main() {
+  asyncStart();
+
+  var scripts = document
+      .querySelectorAll<ScriptElement>('script')
+      .where((s) => s.src.contains("generated_compilations"))
+      .toList();
+  Expect.equals(1, scripts.length);
+  Expect.equals('', scripts.first.nonce ?? '');
+  Expect.equals('', scripts.first.getAttribute('nonce') ?? '');
+  scripts.first.setAttribute("nonce", "an-example-nonce-string");
+
+  lib.loadLibrary().then((_) {
+    print(lib.foo());
+    var scripts = document
+        .querySelectorAll<ScriptElement>('script')
+        .where((s) => s.src.contains(".part.js"))
+        .toList();
+    Expect.equals(1, scripts.length);
+    for (var script in scripts) {
+      Expect.equals("an-example-nonce-string", script.nonce);
+      Expect.equals("an-example-nonce-string", script.getAttribute('nonce'));
+    }
+    asyncEnd();
+  });
+}
diff --git a/tests/compiler/dart2js_extra/deferred_with_csp_nonce_test.dart b/tests/compiler/dart2js_extra/deferred_with_csp_nonce_test.dart
index 90d6acb..2725df8 100644
--- a/tests/compiler/dart2js_extra/deferred_with_csp_nonce_test.dart
+++ b/tests/compiler/dart2js_extra/deferred_with_csp_nonce_test.dart
@@ -19,17 +19,19 @@
       .toList();
   Expect.equals(1, scripts.length);
   Expect.equals('', scripts.first.nonce ?? '');
+  Expect.equals('', scripts.first.getAttribute('nonce') ?? '');
   scripts.first.nonce = "an-example-nonce-string";
 
   lib.loadLibrary().then((_) {
     print(lib.foo());
     var scripts = document
         .querySelectorAll<ScriptElement>('script')
-        .where((s) => s.src.contains("generated_compilations"))
+        .where((s) => s.src.contains(".part.js"))
         .toList();
-    Expect.equals(2, scripts.length);
+    Expect.equals(1, scripts.length);
     for (var script in scripts) {
       Expect.equals("an-example-nonce-string", script.nonce);
+      Expect.equals("an-example-nonce-string", script.getAttribute('nonce'));
     }
     asyncEnd();
   });
diff --git a/tests/compiler/dart2js_extra/generator_elided_parameter_test.dart b/tests/compiler/dart2js_extra/generator_elided_parameter_test.dart
new file mode 100644
index 0000000..60bf18b
--- /dev/null
+++ b/tests/compiler/dart2js_extra/generator_elided_parameter_test.dart
@@ -0,0 +1,21 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+/// Test that optional arguments of methods with a generator are forwarded
+/// properly when optional parameters are elided.
+///
+/// This is a regression test for issue #35924
+import "package:expect/expect.dart";
+
+// The type parameter forces us to create a generator body. The call from the
+// method to the body needs to correctly handle elided parameters.
+Future<T> foo<T>(T Function(int, int, int) toT,
+    {int p1: 0, int p2: 1, int p3: 2}) async {
+  await null;
+  return toT(p1, p2, p3);
+}
+
+main() async {
+  Expect.equals(await foo<String>((a, b, c) => "$a $b $c", p2: 4), "0 4 2");
+}
diff --git a/tests/compiler/dart2js_extra/js_interop_no_elide_optional_arg_test.dart b/tests/compiler/dart2js_extra/js_interop_no_elide_optional_arg_test.dart
new file mode 100644
index 0000000..5d6d913
--- /dev/null
+++ b/tests/compiler/dart2js_extra/js_interop_no_elide_optional_arg_test.dart
@@ -0,0 +1,31 @@
+// 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.
+
+/// Test that optional arguments of js-interop factory constructors are not
+/// elided.
+/// This is a regression test for issue 35916
+@JS()
+library test;
+
+import "package:js/js.dart";
+import "package:expect/expect.dart";
+
+@JS()
+@anonymous
+class Margins {
+  external factory Margins(
+      {int top, int start, int end, int right, int bottom, int left});
+  external int get top;
+  external int get right;
+  external int get left;
+  external int get bottom;
+}
+
+main() {
+  var m = new Margins(bottom: 21, left: 88, right: 20, top: 24);
+  Expect.equals(m.top, 24);
+  Expect.equals(m.bottom, 21);
+  Expect.equals(m.left, 88);
+  Expect.equals(m.right, 20);
+}
diff --git a/tests/compiler/dart2js_native/native_method_inlining_test.dart b/tests/compiler/dart2js_native/native_method_inlining_test.dart
index f673eeb..9d7ddc9 100644
--- a/tests/compiler/dart2js_native/native_method_inlining_test.dart
+++ b/tests/compiler/dart2js_native/native_method_inlining_test.dart
@@ -20,7 +20,9 @@
 }
 
 class B {
+  @pragma('dart2js:noElision')
   static var g;
+
   @NoInline()
   method1(a) {
     g = '(Method1Tag)'; // Tag to identify compiled JavaScript method.
diff --git a/tests/corelib_2/corelib_2.status b/tests/corelib_2/corelib_2.status
index b557780..eed9d49 100644
--- a/tests/corelib_2/corelib_2.status
+++ b/tests/corelib_2/corelib_2.status
@@ -53,10 +53,10 @@
 error_stack_trace_test/static: MissingCompileTimeError
 
 [ $compiler == dartdevk ]
-bool_from_environment2_test/03: Crash
+bool_from_environment2_test/03: MissingCompileTimeError
 int_modulo_arith_test/modPow: RuntimeError
 int_modulo_arith_test/none: RuntimeError
-string_from_environment3_test/03: Crash
+string_from_environment3_test/03: MissingCompileTimeError
 
 [ $compiler == fasta ]
 bool_from_environment2_test/03: MissingCompileTimeError
diff --git a/tests/language_2/async_this_bound_test.dart b/tests/language_2/async_this_bound_test.dart
index b71a597..fdbfa6c 100644
--- a/tests/language_2/async_this_bound_test.dart
+++ b/tests/language_2/async_this_bound_test.dart
@@ -27,8 +27,8 @@
 
 class B {
   var f;
-  @NoInline()
   var b = 10;
+
   B(this.f);
 
   bar(x) => b;
diff --git a/tests/language_2/const_types_test.dart b/tests/language_2/const_types_test.dart
index 4160878..3199c0c 100644
--- a/tests/language_2/const_types_test.dart
+++ b/tests/language_2/const_types_test.dart
@@ -18,7 +18,7 @@
     use(const <Unresolved>[]); //# 02: compile-time error
 
     use(const {});
-    use(const <Class>{}); //# 03: compile-time error
+    use(const <Class>{});
     use(const <String, Class>{});
     use(const <String, Class<int>>{});
     use(const <String, Class<Unresolved>>{}); //# 04: compile-time error
diff --git a/tests/language_2/control_flow_collections/experimental_flag_test.dart b/tests/language_2/control_flow_collections/experimental_flag_test.dart
new file mode 100644
index 0000000..aa3d8a1
--- /dev/null
+++ b/tests/language_2/control_flow_collections/experimental_flag_test.dart
@@ -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.
+
+// Check that control flow is not enabled without the experimental flag.
+
+// Do enable set literals, just not the new syntax in them.
+// SharedOptions=--enable-experiment=set-literals
+
+// TODO(rnystrom): Remove this test when the feature is enabled without a flag.
+
+void main() {
+  var _ = <int>[if (true) 1]; //# 01: compile-time error
+  var _ = <int, int>{if (true) 1: 1}; //# 02: compile-time error
+  var _ = <int>{if (true) 1}; //# 03: compile-time error
+
+  var _ = <int>[if (true) 1 else 2]; //# 04: compile-time error
+  var _ = <int, int>{if (true) 1: 1 else 2: 2}; //# 05: compile-time error
+  var _ = <int>{if (true) 1 else 2}; //# 06: compile-time error
+
+  var _ = <int>[for (var i in []) 1]; //# 07: compile-time error
+  var _ = <int, int>{for (var i in []) 1: 1}; //# 08: compile-time error
+  var _ = <int>{for (var i in []) 1}; //# 09: compile-time error
+
+  var _ = <int>[for (; false;) 1]; //# 10: compile-time error
+  var _ = <int, int>{for (; false;) 1: 1}; //# 11: compile-time error
+  var _ = <int>{for (; false;) 1}; //# 12: compile-time error
+
+  () async {
+    var _ = <int>[await for (var i in []) 1]; //# 13: compile-time error
+    var _ = <int, int>{await  for (var i in []) 1: 1}; //# 14: compile-time error
+    var _ = <int>{await for (var i in []) 1}; //# 15: compile-time error
+  }();
+}
diff --git a/tests/language_2/control_flow_collections/for_const_test.dart b/tests/language_2/control_flow_collections/for_const_test.dart
new file mode 100644
index 0000000..022ec24
--- /dev/null
+++ b/tests/language_2/control_flow_collections/for_const_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=set-literals,control-flow-collections
+
+void main() {
+  // For cannot be used in a const collection.
+  const _ = [for (var i in []) 1]; //# 00: compile-time error
+  const _ = {for (var i in []) 1: 1}; //# 01: compile-time error
+  const _ = {for (var i in []) 1}; //# 02: compile-time error
+
+  const _ = [for (; false;) 1]; //# 03: compile-time error
+  const _ = {for (; false;) 1: 1}; //# 04: compile-time error
+  const _ = {for (; false;) 1}; //# 05: compile-time error
+
+  () async {
+    const _ = <int>[await for (var i in []) 1]; //# 06: compile-time error
+    const _ = <int, int>{await  for (var i in []) 1: 1}; //# 07: compile-time error
+    const _ = <int>{await for (var i in []) 1}; //# 08: compile-time error
+  }();
+}
diff --git a/tests/language_2/control_flow_collections/for_inference_test.dart b/tests/language_2/control_flow_collections/for_inference_test.dart
new file mode 100644
index 0000000..1834edb
--- /dev/null
+++ b/tests/language_2/control_flow_collections/for_inference_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.
+
+// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+
+// Test how control flow interacts with inference.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testLoopVariableInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  // Lists.
+  Expect.type<List<int>>([for (; false;) 1]);
+  Expect.type<List<int>>([for (; false;) 1, for (; false;) 2]);
+  Expect.type<List<num>>([for (; false;) 1, for (; false;) 0.2]);
+  Expect.type<List<int>>([for (; false;) 1, 2]);
+  Expect.type<List<num>>([for (; false;) 1, 0.2]);
+  Expect.type<List<dynamic>>([for (; false;) ...[]]);
+  Expect.type<List<int>>([for (; false;) ...<int>[]]);
+
+  // Maps.
+  Expect.type<Map<int, int>>({for (; false;) 1: 1});
+  Expect.type<Map<int, int>>({for (; false;) 1: 1, for (; false;) 2: 2});
+  Expect.type<Map<num, num>>({for (; false;) 1: 0.1, for (; false;) 0.2: 2});
+  Expect.type<Map<int, int>>({for (; false;) 1: 1, 2: 2});
+  Expect.type<Map<num, num>>({for (; false;) 1: 0.1, 0.2: 2});
+  Expect.type<Map<dynamic, dynamic>>({for (; false;) ...{}});
+  Expect.type<Map<int, int>>({for (; false;) ...<int, int>{}});
+
+  // Sets.
+  Expect.type<Set<int>>({for (; false;) 1});
+  Expect.type<Set<int>>({for (; false;) 1, for (; false;) 2});
+  Expect.type<Set<num>>({for (; false;) 1, for (; false;) 0.2});
+  Expect.type<Set<int>>({for (; false;) 1, 2});
+  Expect.type<Set<num>>({for (; false;) 1, 0.2});
+  Expect.type<Set<dynamic>>({if (true) ...[]});
+  Expect.type<Set<int>>({if (true) ...<int>[]});
+
+  // If a nested iterable's type is dynamic, the element type is dynamic.
+  Expect.type<List<dynamic>>([for (; false;) ...([] as dynamic)]);
+  Expect.type<Set<dynamic>>({1, for (; false;) ...([] as dynamic)});
+
+  // If a nested maps's type is dynamic, the key and value types are dynamic.
+  Expect.type<Map<dynamic, dynamic>>({1: 1, for (; false;) ...({} as dynamic)});
+}
+
+void testLoopVariableInference() {
+  // Infers loop variable from iterable.
+  Expect.type<List<int>>([for (var i in <int>[1]) i]);
+  Expect.type<List<String>>([for (var i in <int>[1]) i.toRadixString(10)]);
+
+  // Infers loop variable from initializer.
+  Expect.type<List<int>>([for (var i = 1; i < 2; i++) i]);
+  Expect.type<List<String>>([for (var i = 1; i < 2; i++) i.toRadixString(10)]);
+
+  // Loop variable type is not pushed into iterable.
+  Expect.listEquals(<int>[1], [for (int i in expectDynamic([1]))]);
+
+  // Loop variable type is pushed into initializer.
+  Expect.listEquals(<int>[1], [for (int i = expectInt(1), i < 2; i++) i]);
+}
+
+void testTopDownInference() {
+  // Lists.
+
+  // The context element type is pushed into the body.
+  Expect.listEquals(<int>[1], <int>[for (; false;) expectInt(1)]);
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.listEquals(<int>[1, 2], [1, for (; false;) expectDynamic(2)]);
+
+  // Maps.
+
+  // The context element type is pushed into the body.
+  Expect.mapEquals(<int, String>{1: "s"},
+      <int, String>{for (; false;) expectInt(1): expectString("s")});
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.mapEquals(<int, String>{1: "s", 2: "t"},
+      {1: "s", for (; false;) expectDynamic(2): expectDynamic("t")});
+
+  // Sets.
+
+  // The context element type is pushed into the body.
+  Expect.setEquals(<int>{1}, <int>{for (; false;) expectInt(1)});
+
+  // Bottom up-inference from elements is not pushed back down into the body.
+  Expect.setEquals(<int>{1, 2}, {1, for (; false;) expectDynamic(2)});
+}
diff --git a/tests/language_2/control_flow_collections/for_test.dart b/tests/language_2/control_flow_collections/for_test.dart
new file mode 100644
index 0000000..108b82f
--- /dev/null
+++ b/tests/language_2/control_flow_collections/for_test.dart
@@ -0,0 +1,267 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections,spread-collections
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+final list = [1, 2, 3, 4];
+final map = {1: 1, 2: 2, 3: 3, 4: 4};
+final set = {1, 2, 3, 4};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testDuplicateKeys();
+  testKeyOrder();
+  testRuntimeErrors();
+}
+
+void testList() {
+  // Only for.
+  Expect.listEquals(list, <int>[for (var i in list) i]);
+
+  // For at beginning.
+  Expect.listEquals(list, <int>[for (var i in <int>[1, 2]) i, 3, 4]);
+
+  // For in middle.
+  Expect.listEquals(list, <int>[1, for (var i in <int>[2, 3]) i, 4]);
+
+  // For at end.
+  Expect.listEquals(list, <int>[1, 2, for (var i in <int>[3, 4]) i]);
+
+  // Empty for.
+  Expect.listEquals(list,
+      <int>[1, for (var i in <int>[]) i, 2, 3, for (; false;) 9, 4]);
+
+  // Multiple fors.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1]) i, 2, for (var i = 3; i <= 4; i++) i]);
+
+  // Spread inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[0, 2]) ...<int>[1 + i, 2 + i]]);
+
+  // If inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i]);
+
+  // Else inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i]);
+
+  // For inside for.
+  Expect.listEquals(list,
+      <int>[for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j]);
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], [for (var i = 1; i < 2; i++) [i]].first;
+  Expect.mapEquals({1: 1}, [for (var i = 1; i < 2; i++) {i: i}].first;
+  Expect.setEquals({1}, [for (var i = 1; i < 2; i++) {i}].first;
+
+  // Downcast variable.
+  Expect.listEquals(list, <int>[for (int n in <num>[1, 2, 3, 4]) n]);
+
+  // Downcast element.
+  Expect.listEquals(list, <int>[for (num n in <num>[1, 2, 3, 4]) n]);
+
+  // Downcast condition.
+  Expect.listEquals([1], <int>[for (var i = 1; (i < 2) as dynamic; i++) i]);
+  Expect.listEquals([1], <int>[for (var i = 1; (i < 2) as Object; i++) i]);
+}
+
+void testMap() {
+  // Only for.
+  Expect.mapEquals(map, <int, int>{for (var i in list) i: i});
+
+  // For at beginning.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, 2]) i: i, 3: 3, 4: 4});
+
+  // For in middle.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, for (var i in <int>[2, 3]) i: i, 4: 4});
+
+  // For at end.
+  Expect.mapEquals(map,
+      <int, int>{1: 1, 2: 2, for (var i in <int>[3, 4]) i: i});
+
+  // Empty for.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    for (var i in <int>[]) i: i,
+    2: 2,
+    3: 3,
+    for (; false;) 9: 9,
+    4: 4
+  });
+
+  // Multiple fors.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[1]) i: i,
+    2: 2,
+    for (var i = 3; i <= 4; i++) i: i
+  });
+
+  // Spread inside for.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[0, 2]) ...<int>{1 + i: 1 + i, 2 + i: 2 + i}
+  });
+
+  // If inside for.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i: i});
+
+  // Else inside for.
+  Expect.mapEquals(map,
+      <int, int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i: i});
+
+  // For inside for.
+  Expect.mapEquals(map, <int, int>{
+    for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j: i + j
+  });
+
+  // Downcast variable.
+  Expect.mapEquals(map, <int, int>{for (int n in <num>[1, 2, 3, 4]) n: n});
+
+  // Downcast element.
+  Expect.mapEquals(map, <int, int>{for (num n in <num>[1, 2, 3, 4]) n: n});
+
+  // Downcast condition.
+  Expect.mapEquals([1],
+      <int, int>{for (var i = 1; (i < 2) as dynamic; i++) i: i});
+  Expect.mapEquals([1],
+      <int, int>{for (var i = 1; (i < 2) as Object; i++) i: i});
+}
+
+void testSet() {
+  // Only for.
+  Expect.setEquals(set, <int>{for (var i in list) i});
+
+  // For at beginning.
+  Expect.setEquals(set, <int>{for (var i in <int>[1, 2]) i, 3, 4});
+
+  // For in middle.
+  Expect.setEquals(set, <int>{1, for (var i in <int>[2, 3]) i, 4});
+
+  // For at end.
+  Expect.setEquals(set, <int>{1, 2, for (var i in <int>[3, 4]) i});
+
+  // Empty for.
+  Expect.setEquals(set,
+      <int>{1, for (var i in <int>[]) i, 2, 3, for (; false;) 9, 4});
+
+  // Multiple fors.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1]) i, 2, for (var i = 3; i <= 4; i++) i});
+
+  // Spread inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[0, 2]) ...<int>[1 + i, 2 + i]});
+
+  // If inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1, 9, 2, 3, 9, 4]) if (i != 9) i});
+
+  // Else inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[1, -2, 3, -4]) if (i < 0) -i else i});
+
+  // For inside for.
+  Expect.setEquals(set,
+      <int>{for (var i in <int>[0, 2]) for (var j = 1; j <= 2; j++) i + j});
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], {for (var i = 1; i < 2; i++) [i]}.first;
+  Expect.mapEquals({1: 1}, {for (var i = 1; i < 2; i++) {i: i}}.first;
+  Expect.setEquals({1}, }for (var i = 1; i < 2; i++) {i}}.first;
+
+  // Downcast variable.
+  Expect.setEquals(set, <int>{for (int n in <num>[1, 2, 3, 4]) n});
+
+  // Downcast element.
+  Expect.setEquals(set, <int>{for (num n in <num>[1, 2, 3, 4]) n});
+
+  // Downcast condition.
+  Expect.setEquals({1}, <int>{for (var i = 1; (i < 2) as dynamic; i++) i});
+  Expect.setEquals({1}, <int>{for (var i = 1; (i < 2) as Object; i++) i});
+}
+
+void testDuplicateKeys() {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    for (var i in <int>[1, 2, 3]) i: i,
+    for (var i = 2; i <= 3; i++) i: i,
+    3: 3
+  });
+  Expect.setEquals(set, <int>{
+    1,
+    for (var i in <int>[1, 2, 3]) i,
+    for (var i = 2; i <= 3; i++) i,
+    3
+  });
+}
+
+void testKeyOrder() {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+  var keys = [e1b, e2a, e2b];
+  var values = [2, 3, 4];
+
+  var map = <Equality, int>{
+    e1a: 1,
+    for (var i = 0; i < keys.length; i++) keys[i]: values[i]
+  };
+  Expect.equals("1:a,2:a", map.keys.join(","));
+
+  var set = <Equality>{e1a, for (var i = 0; i < keys.length; i++) keys[i]};
+  Expect.equals("1:a,2:a", set.join(","));
+}
+
+void testRuntimeErrors() {
+  // Non-bool condition expression.
+  dynamic nonBool = 3;
+  Expect.throwsCastError(() => <int>[for (; nonBool;) 1]);
+  Expect.throwsCastError(() => <int, int>{for (; nonBool;) 1: 1});
+  Expect.throwsCastError(() => <int>{for (; nonBool;) 1});
+
+  // Null condition expression.
+  bool nullBool = null;
+  Expect.throwsAssertionError(() => <int>[for (; nullBool;) 1]);
+  Expect.throwsAssertionError(() => <int, int>{for (; nullBool;) 1: 1});
+  Expect.throwsAssertionError(() => <int>{for (; nullBool;) 1});
+
+  // Cast for variable.
+  dynamic nonInt = "string";
+  Expect.throwsCastError(() => <int>[for (int i = nonInt; false;) 1]);
+  Expect.throwsCastError(() => <int, int>{for (int i = nonInt; false;) 1: 1});
+  Expect.throwsCastError(() => <int>{for (int i = nonInt; false;) 1});
+
+  // Cast for-in variable.
+  dynamic nonIterable = 3;
+  Expect.throwsCastError(() => <int>[for (int i in nonIterable) 1]);
+  Expect.throwsCastError(() => <int, int>{for (int i in nonIterable) 1: 1});
+  Expect.throwsCastError(() => <int>{for (int i in nonIterable) 1});
+
+  // Null iterable.
+  Iterable<int> nullIterable = null;
+  Expect.throwsNoSuchMethodError(() => <int>[for (var i in nullIterable) 1]);
+  Expect.throwsNoSuchMethodError(
+      () => <int, int>{for (var i in nullIterable) 1: 1});
+  Expect.throwsNoSuchMethodError(() => <int>{for (var i in nullIterable) 1});
+
+  // Wrong element type.
+  Expect.throwsCastError(() => <int>[for (var i = 0; i < 1; i++) nonInt]);
+  Expect.throwsCastError(
+      () => <int, int>{for (var i = 0; i < 1; i++) nonInt: 1});
+  Expect.throwsCastError(
+      () => <int, int>{for (var i = 0; i < 1; i++) 1: nonInt});
+  Expect.throwsCastError(() => <int>{for (var i = 0; i < 1; i++) nonInt});
+}
diff --git a/tests/language_2/control_flow_collections/for_variable_test.dart b/tests/language_2/control_flow_collections/for_variable_test.dart
new file mode 100644
index 0000000..732e2ca
--- /dev/null
+++ b/tests/language_2/control_flow_collections/for_variable_test.dart
@@ -0,0 +1,204 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections,spread-collections
+
+/// Tests for how variables and scoping work with for elements.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+String global = "global";
+
+void main() {
+  testClosure();
+  Test().shadowing();
+  Test().reuseVariable();
+}
+
+void testClosure() {
+  var closures = [];
+  capture(callback) {
+    closures.add(callback);
+    return callback();
+  }
+
+  reset() {
+    closures.clear();
+  }
+
+  // Close over for-in loop variable in element.
+  var list = [for (var i in [0, 1]) () => i];
+  Expect.equals(0, list[0]());
+  Expect.equals(1, list[1]());
+
+  // Close over loop variable in element.
+  list = [for (var i = 0; i < 2; i++) () => i];
+  Expect.equals(0, list[0]());
+  Expect.equals(1, list[1]());
+
+  // Close over variable in condition expression.
+  list = [for (var i = 0; capture(() => i++) < 2;) i];
+  Expect.equals(1, closures[0]());
+  Expect.equals(2, closures[1]());
+  Expect.listEquals([1, 2], list);
+  reset();
+
+  // Close over variable in increment expression.
+  list = [for (var i = 0; i < 2; capture(() => i++)) i];
+  Expect.equals(1, closures[0]());
+  Expect.equals(2, closures[1]());
+  Expect.listEquals([0, 1], list);
+  reset();
+}
+
+class TestBase {
+  String inherited = "inherited";
+}
+
+class Test extends TestBase {
+  static String staticField = "static field";
+
+  String field = "field";
+
+  void shadowing() {
+    var local = "local";
+
+    // C-style for.
+    var list = [
+      for (var global = "for"; global != null; global = null) global
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (var staticField = "for"; staticField != null; staticField = null)
+        staticField
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (var field = "for"; field != null; field = null) field
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (var inherited = "for"; inherited != null; inherited = null) inherited
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (var local = "for"; local != null; local = null) local
+    ];
+    Expect.listEquals(["for"], list);
+
+    list = [
+      for (var outer = "outer"; outer != null; outer = null)
+        for (var outer = "for"; outer != null; outer = null)
+          outer
+    ];
+    Expect.listEquals(["for"], list);
+
+    // For-in.
+    list = [for (var global in ["for"]) global];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var staticField in ["for"]) staticField];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var field in ["for"]) field];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var inherited in ["for"]) inherited];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var local in ["for"]) local];
+    Expect.listEquals(["for"], list);
+
+    list = [for (var outer in ["outer"]) for (var outer in ["for"]) outer];
+    Expect.listEquals(["for"], list);
+  }
+
+  void reuseVariable() {
+    var local = "local";
+
+    // C-style for.
+    var list = [
+      for (global = "for"; global == "for"; global = "after") global
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", global);
+    global = "global";
+
+    list = [
+      for (staticField = "for"; staticField == "for"; staticField = "after")
+        staticField
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", staticField);
+    staticField = "staticField";
+
+    list = [
+      for (field = "for"; field == "for"; field = "after") field
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", field);
+    field = "field";
+
+    list = [
+      for (inherited = "for"; inherited == "for"; inherited = "after") inherited
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", inherited);
+    inherited = "inherited";
+
+    list = [
+      for (local = "for"; local == "for"; local = "after") local
+    ];
+    Expect.listEquals(["for"], list);
+    Expect.equals("after", local);
+    local = "local";
+
+    list = [
+      for (var outer = "outer"; outer == "outer"; outer = "outer after") ...[
+        for (outer = "for"; outer == "for"; outer = "after") outer,
+        outer
+      ]
+    ];
+    Expect.listEquals(["for", "after"], list);
+
+    // For-in.
+    list = [for (global in ["for"]) global];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", global);
+    global = "global";
+
+    list = [for (staticField in ["for"]) staticField];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", staticField);
+    staticField = "staticField";
+
+    list = [for (field in ["for"]) field];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", field);
+    field = "field";
+
+    list = [for (inherited in ["for"]) inherited];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", inherited);
+    inherited = "inherited";
+
+    list = [for (local in ["for"]) local];
+    Expect.listEquals(["for"], list);
+    Expect.equals("for", local);
+    local = "local";
+
+    list = [
+      for (var outer in ["outer"]) ...[
+        for (outer in ["for"]) outer,
+        outer
+      ]
+    ];
+    Expect.listEquals(["for", "for"], list);
+  }
+}
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
new file mode 100644
index 0000000..4e100a6
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_const_error_test.dart
@@ -0,0 +1,139 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections
+
+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() {
+  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_test.dart b/tests/language_2/control_flow_collections/if_const_test.dart
new file mode 100644
index 0000000..8ccac19
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_const_test.dart
@@ -0,0 +1,262 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+
+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]);
+
+  // Nested for in then.
+  Expect.identical(list, const <int>[if (true) for (var i in list) i]);
+
+  // Nested for in else.
+  Expect.identical(list, const <int>[if (false) 9 for (var i in list) i]);
+}
+
+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});
+
+  // Nested for in then.
+  Expect.identical(map, const <int, int>{if (true) for (var i in list) i: i});
+
+  // Nested for in else.
+  Expect.identical(map,
+      const <int, int>{if (false) 9: 9 for (var i in list) i: i});
+}
+
+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({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 <int>{if (true) [1]}.first;
+  Expect.identical(const <int, int>{1: 1}, const <int>{if (true) {1: 1}}.first;
+  Expect.identical(const <int>{1}, const <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});
+
+  // Nested for in then.
+  Expect.identical(set, const <int>{if (true) for (var i in list) i});
+
+  // Nested for in else.
+  Expect.identical(set, const <int>{if (false) 9 for (var i in list) i});
+}
+
+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>{
+    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>{1: 1}, const <int, int>{
+    if (true) 1: 1,
+    if (false) nonInt: 9,
+    if (false) 9: nonInt
+  });
+  Expect.identical(const <int, int>{1: 1, 2: 2}, const <int, int>{
+    if (true) 1: 1 else nonInt: 9,
+    if (false) 9: nonInt else 2: 2
+  });
+
+  Expect.identical(const <int>{1}, const <int>{if (true) 1, if (false) nonInt};
+  Expect.identical(const <int>{1, 2},
+      const <int>{if (true) 1 else nonInt, if (false) nonInt else 2});
+}
+
+void testDuplicateKeys() {
+  // Duplicate keys from unchosen branches are not an error.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    if (false) 1: 1,
+    if (true) 2: 2 else 3: 3,
+    3: 3
+  });
+
+  Expect.setEquals(set, const <int>{1, if (false) 1, if (true) 2 else 3, 3});
+}
+
+void testKeyOrder() {
+  // Canonicalization isn't affected by which elements are conditional.
+  Expect.identical(map,
+      const <int, int>{1: 1, if (true) 2: 2, if (false) 9: 9, 3: 3});
+  Expect.identical(map,
+      const <int, int>{if (false) 9: 9 else 1: 1, 2: 2, if (true) 3: 3});
+
+  Expect.identical(set, const <int>{1, if (true) 2, if (false) 9, 3});
+  Expect.identical(set, const <int>{if (false) 9 else 1, 2, if (true) 3});
+
+  // Ordering does affect canonicalization.
+  Expect.notIdentical(map, const <int, int>{1: 1, if (true) 3: 3, 2: 2});
+  Expect.notIdentical(set, const <int>{1, if (true) 3, 2});
+}
diff --git a/tests/language_2/control_flow_collections/if_inference_test.dart b/tests/language_2/control_flow_collections/if_inference_test.dart
new file mode 100644
index 0000000..adc6e65
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_inference_test.dart
@@ -0,0 +1,83 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+
+// Test how control flow interacts with inference.
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  // Lists.
+  expectListOf<int>([if (true) 1]);
+  expectListOf<int>([if (true) 1 else 2]);
+  expectListOf<num>([if (true) 1 else 0.2]);
+  expectListOf<int>([if (true) 1, 2]);
+  expectListOf<num>([if (true) 1, 0.2]);
+  expectListOf<dynamic>([if (true) ...[]]);
+  expectListOf<int>([if (true) ...<int>[]]);
+
+  // Maps.
+  expectMapOf<int, int>({if (true) 1: 1});
+  expectMapOf<int, int>({if (true) 1: 1 else 2: 2});
+  expectMapOf<num, num>({if (true) 1: 0.1 else 0.2: 2});
+  expectMapOf<int, int>({if (true) 1: 1, 2: 2});
+  expectMapOf<num, num>({if (true) 1: 0.1, 0.2: 2});
+  expectMapOf<dynamic, dynamic>({if (true) ...{}});
+  expectMapOf<int, int>({if (true) ...<int, int>{}});
+
+  // Sets.
+  expectSetOf<int>({if (true) 1});
+  expectSetOf<int>({if (true) 1 else 2});
+  expectSetOf<num>({if (true) 1 else 0.2});
+  expectSetOf<int>({if (true) 1, 2});
+  expectSetOf<num>({if (true) 1, 0.2});
+  expectSetOf<dynamic>({if (true) ...[]});
+  expectSetOf<int>({if (true) ...<int>[]});
+
+  // If a nested iterable's type is dynamic, the element type is dynamic.
+  expectListOf<dynamic>([if (true) ...([] as dynamic)]);
+  expectSetOf<dynamic>({1, if (true) ...([] as dynamic)});
+
+  // If a nested maps's type is dynamic, the key and value types are dynamic.
+  expectMapOf<dynamic, dynamic>({1: 1, if (true) ...({} as dynamic)});
+}
+
+void testTopDownInference() {
+  // Lists.
+
+  // The context element type is pushed into the branches.
+  Expect.listEquals(<int>[1], <int>[if (true) expectInt(1)]);
+  Expect.listEquals(<int>[1], <int>[if (false) 9 else expectInt(1)]);
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.listEquals(<int>[1, 2], [1, if (true) expectDynamic(2)]);
+  Expect.listEquals(<int>[1, 2], [1, if (false) 9 else expectDynamic(2)]);
+
+  // Maps.
+
+  // The context element type is pushed into the branches.
+  Expect.mapEquals(<int, String>{1: "s"},
+      <int, String>{if (true) expectInt(1): expectString("s")});
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.mapEquals(<int, String>{1: "s", 2: "t"},
+      {1: "s", if (true) expectDynamic(2): expectDynamic("t")});
+
+  // Sets.
+
+  // The context element type is pushed into the branches.
+  Expect.setEquals(<int>{1}, <int>{if (true) expectInt(1)});
+  Expect.setEquals(<int>{1}, <int>{if (false) 9 else expectInt(1)});
+
+  // Bottom up-inference from elements is not pushed back down into branches.
+  Expect.setEquals(<int>{1, 2}, {1, if (true) expectDynamic(2)});
+  Expect.setEquals(<int>{1, 2}, {1, if (false) 9 else expectDynamic(2)});
+}
diff --git a/tests/language_2/control_flow_collections/if_test.dart b/tests/language_2/control_flow_collections/if_test.dart
new file mode 100644
index 0000000..8aa7ba5
--- /dev/null
+++ b/tests/language_2/control_flow_collections/if_test.dart
@@ -0,0 +1,243 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections,spread-collections
+
+import 'package:expect/expect.dart';
+
+import 'utils.dart';
+
+final list = [1, 2, 3];
+final map = {1: 1, 2: 2, 3: 3};
+final set = {1, 2, 3};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testShortCircuit();
+  testDuplicateKeys();
+  testKeyOrder();
+  testRuntimeFailures();
+}
+
+void testList() {
+  // Then if true.
+  Expect.listEquals(list, <int>[1, if (true) 2, 3]);
+
+  // Nothing if false and no else.
+  Expect.listEquals(list, <int>[1, if (false) 9, 2, 3]);
+
+  // Else if false.
+  Expect.listEquals(list, <int>[1, if (false) 9 else 2, 3]);
+
+  // Only if.
+  Expect.listEquals([1], <int>[if (true) 1]);
+
+  // If at beginning.
+  Expect.listEquals(list, <int>[if (true) 1, 2, 3]);
+
+  // If in middle.
+  Expect.listEquals(list, <int>[1, if (true) 2, 3]);
+
+  // If at end.
+  Expect.listEquals(list, <int>[1, 2, if (true) 3]);
+
+  // Multiple ifs.
+  Expect.listEquals(list,
+      <int>[if (true) 1, if (false) 9, 2, if (true) 3]);
+
+  // Cast condition.
+  Expect.listEquals(<int>[1], <int>[if (true as dynamic) 1]);
+  Expect.listEquals(<int>[1], <int>[if (true as Object) 1]);
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], [if (true) [1]].first;
+  Expect.mapEquals({1: 1}, [if (true) {1: 1}].first;
+  Expect.setEquals({1}, [if (true) {1}].first;
+
+  // Nested spread.
+  Expect.listEquals(list,
+      <int>[if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]]);
+
+  // Nested if in then.
+  Expect.listEquals([1], <int>[if (true) if (true) 1, if (true) if (false) 9]);
+
+  // Nested if in else.
+  Expect.listEquals([1], <int>[if (false) 9 else if (true) 1]);
+
+  // Nested for in then.
+  Expect.listEquals(list, <int>[if (true) for (var i in list) i]);
+
+  // Nested for in else.
+  Expect.listEquals(list, <int>[if (false) 9 for (var i in list) i]);
+}
+
+void testMap() {
+  // Then if true.
+  Expect.mapEquals(map, <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // Nothing if false and no else.
+  Expect.mapEquals(map, <int, int>{1: 1, if (false) 9: 9, 2: 2, 3: 3});
+
+  // Else if false.
+  Expect.mapEquals(map, <int, int>{1: 1, if (false) 9: 9 else 2: 2, 3: 3});
+
+  // Only if.
+  Expect.mapEquals(<int, int>{1: 1}, <int, int>{if (true) 1: 1});
+
+  // If at beginning.
+  Expect.mapEquals(map, <int, int>{if (true) 1: 1, 2: 2, 3: 3});
+
+  // If in middle.
+  Expect.mapEquals(map, <int, int>{1: 1, if (true) 2: 2, 3: 3});
+
+  // If at end.
+  Expect.mapEquals(map, <int, int>{1: 1, 2: 2, if (true) 3: 3});
+
+  // Multiple ifs.
+  Expect.mapEquals(map,
+      <int, int>{if (true) 1: 1, if (false) 9: 9, 2: 2, if (true) 3: 3});
+
+  // Cast condition.
+  Expect.mapEquals(<int, int>{1: 1}, <int, int>{if (true as dynamic) 1: 1});
+  Expect.mapEquals(<int, int>{1: 1}, <int, int>{if (true as Object) 1: 1});
+
+  // Nested spread.
+  Expect.mapEquals(map, <int, int>{
+    if (true) ...<int, int>{1: 1, 2: 2},
+    if (false) 9: 9 else ...<int, int>{3: 3}
+  });
+
+  // Nested if in then.
+  Expect.mapEquals({1: 1},
+      <int, int>{if (true) if (true) 1: 1, if (true) if (false) 9: 9});
+
+  // Nested if in else.
+  Expect.mapEquals({1: 1},
+      <int, int>{if (false) 9: 9 else if (true) 1: 1});
+
+  // Nested for in then.
+  Expect.mapEquals(map, <int, int>{if (true) for (var i in list) i: i});
+
+  // Nested for in else.
+  Expect.mapEquals(map, <int, int>{if (false) 9: 9 for (var i in list) i: i});
+}
+
+void testSet() {
+  // Then if true.
+  Expect.setEquals(set, <int>{1, if (true) 2, 3});
+
+  // Nothing if false and no else.
+  Expect.setEquals(set, <int>{1, if (false) 9, 2, 3});
+
+  // Else if false.
+  Expect.setEquals(set, <int>{1, if (false) 9 else 2, 3});
+
+  // Only if.
+  Expect.setEquals({1}, <int>{if (true) 1});
+
+  // If at beginning.
+  Expect.setEquals(set, <int>{if (true) 1, 2, 3});
+
+  // If in middle.
+  Expect.setEquals(set, <int>{1, if (true) 2, 3});
+
+  // If at end.
+  Expect.setEquals(set, <int>{1, 2, if (true) 3});
+
+  // Multiple ifs.
+  Expect.setEquals(set,
+      <int>{if (true) 1, if (false) 9, 2, if (true) 3});
+
+  // Cast condition.
+  Expect.setEquals({1}, <int>{if (true as dynamic) 1});
+  Expect.setEquals({1}, <int>{if (true as Object) 1});
+
+  // Does not flatten nested collection literal.
+  Expect.listEquals([1], {if (true) [1]}.first;
+  Expect.mapEquals({1: 1}, {if (true) {1: 1}}.first;
+  Expect.setEquals({1}, {if (true) {1}}.first;
+
+  // Nested spread.
+  Expect.setEquals(set,
+      <int>{if (true) ...<int>[1, 2], if (false) 9 else ...<int>[3]});
+
+  // Nested if in then.
+  Expect.setEquals({1}, <int>{if (true) if (true) 1, if (true) if (false) 9});
+
+  // Nested if in else.
+  Expect.setEquals({1}, <int>{if (false) 9 else if (true) 1});
+
+  // Nested for in then.
+  Expect.setEquals(set, <int>{if (true) for (var i in list) i});
+
+  // Nested for in else.
+  Expect.setEquals(set, <int>{if (false) 9 for (var i in list) i});
+}
+
+void testShortCircuit() {
+  var transcript = <String>[];
+  T log<T>(T value) {
+    transcript.add(value.toString());
+    return value;
+  }
+
+  // With no else.
+  Expect.listEquals([1], [if (true) log(1), if (false) log(2)]);
+  Expect.equals("1", transcript.join(","));
+  transcript.clear();
+
+  // With else.
+  Expect.listEquals([1, 4],
+      [if (true) log(1) else log(2), if (false) log(3) else log(4)]);
+  Expect.equals("1,4", transcript.join(","));
+}
+
+void testDuplicateKeys() {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    if (true) 1: 1,
+    if (false) 9: 9 else 2: 2,
+    2: 2,
+    3: 3
+  });
+  Expect.setEquals(set, <int>{1, if (true) 1, if (false) 9 else 2, 2, 3});
+}
+
+void testKeyOrder() {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+
+  var map = <Equality, int>{
+    e1a: 0,
+    if (true) e1b: 0,
+    if (true) e2a: 0,
+    if (true) e2b: 0
+  };
+  Expect.equals("1:a,2:a", map.keys.join(","));
+
+  var set = <Equality>{
+    e1a,
+    if (true) e1b,
+    if (true) e2a,
+    if (true) e2b
+  };
+  Expect.equals("1:a,2:a", set.join(","));
+}
+
+void testRuntimeFailures() {
+  dynamic nonBool = 3;
+  Expect.throwsCastError(() => <int>[if (nonBool) 1]);
+  Expect.throwsCastError(() => <int, int>{if (nonBool) 1: 1});
+  Expect.throwsCastError(() => <int>{if (nonBool) 1});
+
+  bool nullBool = null;
+  Expect.throwsAssertionError(() => <int>[if (nullBool) 1]);
+  Expect.throwsAssertionError(() => <int, int>{if (nullBool) 1: 1});
+  Expect.throwsAssertionError(() => <int>{if (nullBool) 1});
+}
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_error_test.dart
new file mode 100644
index 0000000..5296956
--- /dev/null
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_error_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.
+
+// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+
+// Test cases where the syntax is ambiguous between maps and sets when control
+// flow elements contain spreads.
+import 'dart:collection';
+
+import 'utils.dart';
+
+void main() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dyn = map;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  var _ = {if (true) ...dyn}; //# 00: compile-time error
+  var _ = {if (true) ...map else ...set}; //# 01: compile-time error
+  var _ = {if (true) ...map else ...iterable}; //# 02: compile-time error
+  var _ = {if (true) ...map else ...customSet}; //# 03: compile-time error
+  var _ = {if (true) ...set else ...customMap}; //# 04: compile-time error
+  var _ = {if (true) ...dyn else ...dyn}; //# 05: compile-time error
+  var _ = {if (true) ...iterable else ...customMap}; //# 06: compile-time error
+  var _ = {if (true) ...customSet else ...customMap}; //# 07: compile-time error
+
+  var _ = {for (; false;) ...dyn}; //# 08: compile-time error
+  var _ = {for (; false;) ...map, ...set}; //# 09: compile-time error
+  var _ = {for (; false;) ...map, ...iterable}; //# 10: compile-time error
+  var _ = {for (; false;) ...map, ...customSet}; //# 11: compile-time error
+  var _ = {for (; false;) ...set, ...customMap}; //# 12: compile-time error
+  var _ = {for (; false;) ...dyn, ...dyn}; //# 13: compile-time error
+  var _ = {for (; false;) ...iterable, ...customMap}; //# 14: compile-time error
+  var _ = {for (; false;) ...customSet, ...customMap}; //# 15: compile-time error
+}
diff --git a/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
new file mode 100644
index 0000000..abd6f58
--- /dev/null
+++ b/tests/language_2/control_flow_collections/map_set_ambiguity_test.dart
@@ -0,0 +1,129 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,control-flow-collections,spread-collections
+
+// Test cases where the syntax is ambiguous between maps and sets because of
+// spreads inside control flow.
+import 'dart:collection';
+
+import 'utils.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dyn = map;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  // Note: The commented out cases are the error cases. They are shown here for
+  // completeness and tested in map_set_ambiguity_error_test.dart.
+  expectMapOf<int, int>({if (true) ...map});
+  expectSetOf<int>({if (true) ...set});
+  // expect___Of<...>({if (true) ...dyn});
+  expectSetOf<int>({if (true) ...iterable});
+  expectSetOf<int>({if (true) ...customSet});
+  expectMapOf<int, int>({if (true) ...customMap});
+
+  expectMapOf<int, int>({if (true) ...map else ...map});
+  // expect___Of<...>({if (true) ...map else ...set});
+  expectMapOf<dynamic, dynamic>({if (true) ...map else ...dyn});
+  // expect___Of<...>({if (true) ...map else ...iterable});
+  // expect___Of<...>({if (true) ...map else ...customSet});
+  expectMapOf<int, int>({if (true) ...map else ...customMap});
+
+  expectSetOf<int>({if (true) ...set else ...set});
+  expectSetOf<dynamic>({if (true) ...set else ...dyn});
+  expectSetOf<int>({if (true) ...set else ...iterable});
+  expectSetOf<int>({if (true) ...set else ...customSet});
+  // expect___Of<...>({if (true) ...set else ...customMap});
+
+  // expect___Of<...>({if (true) ...dyn else ...dyn});
+  expectSetOf<dynamic>({if (true) ...dyn else ...iterable});
+  expectSetOf<dynamic>({if (true) ...dyn else ...customSet});
+  expectMapOf<dynamic, dynamic>({if (true) ...dyn else ...customMap});
+
+  expectSetOf<int>({if (true) ...iterable else ...iterable});
+  expectSetOf<int>({if (true) ...iterable else ...customSet});
+  // expect___Of<...>({if (true) ...iterable else ...customMap});
+
+  expectSetOf<int>({if (true) ...customSet else ...customSet});
+  // expect___Of<...>({if (true) ...customSet else ...customMap});
+
+  expectMapOf<int, int>({if (true) ...customMap else ...customMap});
+
+  // Note: The commented out cases are the error cases. They are shown here for
+  // completeness and tested in map_set_ambiguity_error_test.dart.
+  expectMapOf<int, int>({for (; false;) ...map});
+  expectSetOf<int>({for (; false;) ...set});
+  // expect___Of<...>({for (; false;) ...dyn});
+  expectSetOf<int>({for (; false;) ...iterable});
+  expectSetOf<int>({for (; false;) ...customSet});
+  expectMapOf<int, int>({for (; false;) ...customMap});
+
+  expectMapOf<int, int>({for (; false;) ...map, for (; false;) ...map});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...set});
+  expectMapOf<dynamic, dynamic>(
+      {for (; false;) ...map, for (; false;) ...dyn});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...iterable});
+  // expect___Of<...>({for (; false;) ...map, for (; false;) ...customSet});
+  expectMapOf<int, int>(
+      {for (; false;) ...map, for (; false;) ...customMap});
+
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...set});
+  expectSetOf<dynamic>({for (; false;) ...set, for (; false;) ...dyn});
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...iterable});
+  expectSetOf<int>({for (; false;) ...set, for (; false;) ...customSet});
+  // expect___Of<...>({for (; false;) ...set, for (; false;) ...customMap});
+
+  // expect___Of<...>({for (; false;) ...dyn, for (; false;) ...dyn});
+  expectSetOf<dynamic>(
+      {for (; false;) ...dyn, for (; false;) ...iterable});
+  expectSetOf<dynamic>(
+      {for (; false;) ...dyn, for (; false;) ...customSet});
+  expectMapOf<dynamic, dynamic>(
+      {for (; false;) ...dyn, for (; false;) ...customMap});
+
+  expectSetOf<int>(
+      {for (; false;) ...iterable, for (; false;) ...iterable});
+  expectSetOf<int>(
+      {for (; false;) ...iterable, for (; false;) ...customSet});
+  // expect___Of<...>(
+  //     {for (; false;) ...iterable, for (; false;) ...customMap});
+
+  expectSetOf<int>(
+      {for (; false;) ...customSet, for (; false;) ...customSet});
+  // expect___Of<...>(
+  //     {for (; false;) ...customSet, for (; false;) ...customMap});
+
+  expectMapOf<int, int>(
+      {for (; false;) ...customMap, for (; false;) ...customMap});
+}
+
+void testTopDownInference() {
+  dynamic untypedMap = <int, int>{};
+  dynamic untypedIterable = <int>[];
+
+  Map<int, int> map = {if (true) ...untypedMap};
+  Set<int> set = {if (true) ...untypedIterable};
+  Iterable<int> iterable = {if (true) ...untypedIterable};
+
+  expectMapOf<int, int>(map);
+  expectSetOf<int>(set);
+  expectSetOf<int>(iterable);
+
+  map = {for (; false;) ...untypedMap};
+  set = {for (; false;) ...untypedIterable};
+  iterable = {for (; false;) ...untypedIterable};
+
+  expectMapOf<int, int>(map);
+  expectSetOf<int>(set);
+  expectSetOf<int>(iterable);
+}
diff --git a/tests/language_2/control_flow_collections/syntax_error_test.dart b/tests/language_2/control_flow_collections/syntax_error_test.dart
new file mode 100644
index 0000000..6e070df
--- /dev/null
+++ b/tests/language_2/control_flow_collections/syntax_error_test.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.
+
+// SharedOptions=--enable-experiment=control-flow-collections,spread-collections
+
+void main() {
+  // No then element.
+  var _ = [if (true)]; //# 00: compile-time error
+
+  // No then element with else.
+  var _ = [if (true) else 0]; //# 01: compile-time error
+
+  // No else element.
+  var _ = [if (true) 0 else]; //# 02: compile-time error
+
+  // Spread if.
+  var _ = [...if (true) 0]; //# 03: compile-time error
+
+  // Spread for.
+  var _ = [...for (; false;) 0]; //# 04: compile-time error
+
+  // Use if in map entry.
+  var _ = {if (true) 1: 1: 2}; //# 05: compile-time error
+  var _ = {1: if (true) 2: 2}; //# 06: compile-time error
+
+  // Use for in map entry.
+  var _ = {for (; false;) 1: 1: 2}; //# 07: compile-time error
+  var _ = {1: for (; false;) 2: 2}; //# 08: compile-time error
+
+  // Use for variable out of scope.
+  var _ = [for (var i = 0; false;) 1, i]; //# 09: compile-time error
+
+  // Use for-in variable out of scope.
+  var _ = [for (var i in [1]; false;) 1, i]; //# 10: compile-time error
+
+  // Use for variable in own initializer.
+  var _ = [for (var i = i; false;) 1]; //# 11: compile-time error
+
+  // Use for-in variable in own initializer.
+  var _ = [for (var i in [i]) 1]; //# 12: compile-time error
+}
diff --git a/tests/language_2/control_flow_collections/syntax_test.dart b/tests/language_2/control_flow_collections/syntax_test.dart
new file mode 100644
index 0000000..48206cd2
--- /dev/null
+++ b/tests/language_2/control_flow_collections/syntax_test.dart
@@ -0,0 +1,46 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections
+
+// Tests syntax edge cases.
+import 'package:expect/expect.dart';
+
+void main() {
+  // Trailing comma after then.
+  Expect.listEquals([1], [if (true) 1,]);
+  Expect.mapEquals({1: 1}, {if (true) 1: 1,});
+  Expect.setEquals({1}, {if (true) 1,});
+
+  // Trailing comma after else.
+  Expect.listEquals([1], [if (true) 1 else 2,]);
+  Expect.mapEquals({1: 1}, {if (true) 1: 1 else 2: 2,});
+  Expect.setEquals({1}, {if (true) 1 else 2,});
+
+  // Trailing comma after for.
+  Expect.listEquals([1], [1, for (; false;) 2,]);
+  Expect.mapEquals({1: 1}, {1: 1, for (; false;) 2: 2,});
+  Expect.setEquals({1}, {1, for (; false;) 2,});
+
+  // Dangling else.
+  Expect.listEquals([1], [if (true) if (false) else 1]);
+  Expect.listEquals([1], [if (true) if (false) else 1 else 2]);
+  Expect.listEquals([2], [if (false) if (false) else 1 else 2]);
+
+  // Precedence of then.
+  Expect.listEquals([1, 2, 3], [1, if (true) true ? 2 : 0, 3]);
+  var a = 0;
+  Expect.listEquals([1, 2, 3], [1, if (true) a = 2, 3]);
+
+  // Precedence of else.
+  Expect.listEquals([1, 2, 3], [1, if (false) 0 else true ? 2 : 0, 3]);
+  var a = 0;
+  Expect.listEquals([1, 2, 3], [1, if (false) 0 else a = 2, 3]);
+
+  // Precedence of for.
+  Expect.listEquals([1, 2, 3],
+      [1, for (var i = 0; i < 1; i++) true ? 2 : 0, 3]);
+  var a = 0;
+  Expect.listEquals([1, 2, 3], [1, for (var i = 0; i < 1; i++) a = 2, 3]);
+}
diff --git a/tests/language_2/control_flow_collections/type_error_test.dart b/tests/language_2/control_flow_collections/type_error_test.dart
new file mode 100644
index 0000000..ace6588
--- /dev/null
+++ b/tests/language_2/control_flow_collections/type_error_test.dart
@@ -0,0 +1,48 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,control-flow-collections
+
+void main() {
+  Object obj = true;
+
+  // Non-Boolean if condition.
+  var _ = <int>[if (1) 2]; //# 00: compile-time error
+  var _ = <int, int>{if (1) 2: 2}; //# 01: compile-time error
+  var _ = <int>{if (1) 2}; //# 02: compile-time error
+
+  // Wrong then element type.
+  var _ = <int>[if (true) "s"]; //# 06: compile-time error
+  var _ = <int, int>{if (true) "s": 1}; //# 07: compile-time error
+  var _ = <int, int>{if (true) 1: "s"}; //# 08: compile-time error
+  var _ = <int>{if (true) "s"}; //# 09: compile-time error
+
+  // Wrong else element type.
+  var _ = <int>[if (false) 1 else "s"]; //# 10: compile-time error
+  var _ = <int, int>{if (false) 1: 1 else "s": 2}; //# 11: compile-time error
+  var _ = <int, int>{if (false) 1: 1 else 2: "s"}; //# 12: compile-time error
+  var _ = <int>{if (false) 1 else "s"}; //# 13: compile-time error
+
+  // Non-Boolean for condition.
+  var _ = <int>[for (; 1;) 2]; //# 14: compile-time error
+  var _ = <int, int>{for (; 1;) 2: 2}; //# 15: compile-time error
+  var _ = <int>{for (; 1;) 2}; //# 16: compile-time error
+
+  // Wrong for-in element type.
+  List<String> s = ["s"];
+  var _ = <int>[for (int i in s) 1]; //# 20: compile-time error
+  var _ = <int, int>[for (int i in s) 1: 1]; //# 21: compile-time error
+  var _ = <int>{for (int i in s) 1}; //# 22: compile-time error
+
+  // Wrong for declaration element type.
+  var _ = <int>[for (int i = "s";;) 1]; //# 23: compile-time error
+  var _ = <int, int>[for (int i = "s";;) 1: 1]; //# 24: compile-time error
+  var _ = <int>{for (int i = "s";;) 1}; //# 25: compile-time error
+
+  // Wrong for body element type.
+  var _ = <int>[for (; false;) "s"]; //# 26: compile-time error
+  var _ = <int, int>{for (; false;) "s": 1}; //# 27: compile-time error
+  var _ = <int, int>{for (; false;) 1: "s"}; //# 28: compile-time error
+  var _ = <int>{for (; false;) "s"}; //# 29: compile-time error
+}
diff --git a/tests/language_2/control_flow_collections/utils.dart b/tests/language_2/control_flow_collections/utils.dart
new file mode 100644
index 0000000..9684b3d
--- /dev/null
+++ b/tests/language_2/control_flow_collections/utils.dart
@@ -0,0 +1,99 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+import 'package:expect/expect.dart';
+
+class CustomMap with MapMixin<int, String> {
+  Iterable<int> get keys => [];
+  String operator [](Object key) => "";
+  operator []=(int key, String value) {}
+  String remove(Object key) => throw UnsupportedError("unsupported");
+  void clear() => throw UnsupportedError("unsupported");
+}
+
+class CustomSet extends SetBase<int> {
+  bool add(int value) => throw UnsupportedError("unsupported");
+  bool contains(Object value) => throw UnsupportedError("unsupported");
+  Iterator<int> get iterator => <int>[].iterator;
+  int get length => 0;
+  int lookup(Object value) => throw UnsupportedError("unsupported");
+  bool remove(Object value) => throw UnsupportedError("unsupported");
+  Set<int> toSet() => this;
+}
+
+class Equality {
+  final int id;
+  final String name;
+  const Equality(this.id, this.name);
+  int get hashCode => id;
+  bool operator ==(Object other) => other is Equality && id == other.id;
+  String toString() => "$id:$name";
+}
+
+T expectDynamic<T>(dynamic value) {
+  Expect.identical(dynamic, T);
+  return value;
+}
+
+T expectInt<T>(dynamic value) {
+  Expect.identical(int, T);
+  return value;
+}
+
+T expectString<T>(dynamic value) {
+  Expect.identical(String, T);
+  return value;
+}
+
+Set<T> expectIntSet<T>() {
+  Expect.identical(int, T);
+  return Set();
+}
+
+Set<T> expectDynamicSet<T>() {
+  Expect.identical(dynamic, T);
+  return Set();
+}
+
+/// Hacky way of testing the inferred generic type arguments of [object].
+///
+/// [Expect.type()] only performs a subtype test, which means that it will
+/// return `true` when asked if a `List<int>` is a `List<num>` or
+/// `List<dynamic>`. For inference, we want to test the type more precisely.
+///
+/// There isn't a good way to do that in tests yet so, for now, we just see if
+/// the runtime type contains the given type argument string.
+// TODO(rnystrom): Do something less horribly brittle.
+void _expectTypeArguments(String typeArguments, Object object) {
+  var typeName = object.runtimeType.toString();
+
+  // If an implementation prints dynamic instantiations like a raw type,
+  // handle that.
+  if (!typeName.contains("<") &&
+      (typeArguments == "dynamic" || typeArguments == "dynamic, dynamic")) {
+    return;
+  }
+
+  if (!typeName.contains("<$typeArguments>")) {
+    Expect.fail("Object should have had generic type '<$typeArguments>', "
+        "but was '$typeName'.");
+  }
+}
+
+void expectListOf<T>(Object object) {
+  Expect.type<List>(object);
+  _expectTypeArguments(T.toString(), object);
+}
+
+void expectSetOf<T>(Object object) {
+  Expect.type<Set>(object);
+  _expectTypeArguments(T.toString(), object);
+}
+
+void expectMapOf<K, V>(Object object) {
+  Expect.type<Map>(object);
+  _expectTypeArguments("$K, $V", object);
+}
diff --git a/tests/language_2/language_2_analyzer.status b/tests/language_2/language_2_analyzer.status
index 027ba25..2ceb689 100644
--- a/tests/language_2/language_2_analyzer.status
+++ b/tests/language_2/language_2_analyzer.status
@@ -69,7 +69,6 @@
 issue34498_test: MissingCompileTimeError # Issue 34500
 large_class_declaration_test: Slow, Pass
 malformed2_test: Pass, MissingCompileTimeError # Flaky: issue 31056.
-mixin_declaration/mixin_declaration_factory_test/02: Crash # Issue 34809
 mixin_method_override_test/01: MissingCompileTimeError
 mixin_super_2_test: CompileTimeError
 mixin_super_use_test: CompileTimeError
diff --git a/tests/language_2/language_2_kernel.status b/tests/language_2/language_2_kernel.status
index 71d479e..5b34f04 100644
--- a/tests/language_2/language_2_kernel.status
+++ b/tests/language_2/language_2_kernel.status
@@ -1,8 +1,6 @@
 # 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.
-# Sections in this file should contain "$compiler == dartk" or
-# "$compiler == dartkp".
 
 enum_initialization_near_stack_overflow_test: Pass, CompileTimeError, OK
 
@@ -39,6 +37,16 @@
 const_nested_test: RuntimeError
 const_string_test: RuntimeError
 constructor12_test: RuntimeError
+control_flow_collections/for_inference_test: DartkCrash
+control_flow_collections/for_test: DartkCrash
+control_flow_collections/for_variable_test: DartkCrash
+control_flow_collections/if_const_test: DartkCrash
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: DartkCrash
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_error_test/09: DartkCrash
+control_flow_collections/syntax_error_test/10: DartkCrash
+control_flow_collections/syntax_test: CompileTimeError
 covariant_subtyping_test: RuntimeError
 ct_const_test: RuntimeError
 cyclic_type2_test: CompileTimeError
@@ -125,6 +133,11 @@
 regress_29025_test: CompileTimeError
 regress_29405_test: CompileTimeError
 regress_30339_test: CompileTimeError
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
 string_interpolation_and_buffer_test: RuntimeError
 super_bound_closure_test/none: CompileTimeError
 super_test: RuntimeError
@@ -151,8 +164,21 @@
 private_method_tearoff_test: RuntimeError
 
 [ $compiler == dartkp ]
+control_flow_collections/for_inference_test: CompileTimeError
+control_flow_collections/for_test: CompileTimeError
+control_flow_collections/for_variable_test: CompileTimeError
+control_flow_collections/if_const_test: CompileTimeError
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: CompileTimeError
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_test: CompileTimeError
 covariant_subtyping_test: RuntimeError
 generic_no_such_method_dispatcher_test: RuntimeError # Issue 31424
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
 web_int_literals_test/*: SkipByDesign # Test applies only to JavaScript targets
 
 [ $compiler == fasta ]
@@ -172,6 +198,16 @@
 const_constructor_nonconst_param_test/01: MissingCompileTimeError
 constructor5_test: CompileTimeError # Verification error
 constructor6_test: CompileTimeError # Verification error
+control_flow_collections/for_inference_test: Crash
+control_flow_collections/for_test: Crash
+control_flow_collections/for_variable_test: Crash
+control_flow_collections/if_const_test: Crash
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: Crash
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_error_test/09: Crash
+control_flow_collections/syntax_error_test/10: Crash
+control_flow_collections/syntax_test: CompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e1: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e10: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e11: MissingCompileTimeError
@@ -193,6 +229,11 @@
 implicit_creation/implicit_const_not_default_values_test/e7: MissingCompileTimeError
 implicit_creation/implicit_const_not_default_values_test/e8: MissingCompileTimeError
 mixin_method_override_test/G4: Crash # Assertion error: mixin_full_resolution.dart': 'src.typeParameters.length == dst.typeParameters.length': is not true.
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
 vm/regress_33469_test/01: MissingCompileTimeError
 vm/regress_33469_test/02: MissingCompileTimeError
 vm/regress_33469_test/03: MissingCompileTimeError
@@ -230,7 +271,6 @@
 set_literals/invalid_set_literal_test/08: MissingCompileTimeError # Requires constant evaluation
 set_literals/invalid_set_literal_test/09: MissingCompileTimeError # Requires constant evaluation
 set_literals/invalid_set_literal_test/10: MissingCompileTimeError # Requires constant evaluation
-set_literals/invalid_set_literal_test/23: MissingCompileTimeError # Exact types
 set_literals/invalid_set_literal_test/29: MissingCompileTimeError # Requires constant evaluation
 set_literals/invalid_set_literal_test/30: MissingCompileTimeError # Requires constant evaluation
 set_literals/invalid_set_literal_test/31: MissingCompileTimeError # Requires constant evaluation
@@ -250,6 +290,38 @@
 vm/debug_break_enabled_vm_test/none: CompileTimeError # KernelVM bug: Bad test using extended break syntax.
 vm/regress_27201_test: CompileTimeError # Fasta/KernelVM bug: Deferred loading kernel issue 30273.
 
+[ $arch != simarm && $arch != simarm64 && $arch != simdbc64 && $compiler == dartk ]
+control_flow_collections/for_inference_test: DartkCrash
+control_flow_collections/for_test: DartkCrash
+control_flow_collections/for_variable_test: DartkCrash
+control_flow_collections/if_const_test: DartkCrash
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: DartkCrash
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_error_test/09: DartkCrash
+control_flow_collections/syntax_error_test/10: DartkCrash
+control_flow_collections/syntax_test: CompileTimeError
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
+
+[ $arch == simdbc64 && $compiler == dartk ]
+control_flow_collections/for_inference_test: CompileTimeError
+control_flow_collections/for_test: CompileTimeError
+control_flow_collections/for_variable_test: CompileTimeError
+control_flow_collections/if_const_test: CompileTimeError
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: CompileTimeError
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_test: CompileTimeError
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
+
 [ $builder_tag == obfuscated && $compiler == dartkp ]
 generic_function_dcall_test/01: SkipByDesign # Prints type names
 invocation_mirror_test: RuntimeError # Issue 34911
@@ -328,6 +400,9 @@
 [ $compiler != dart2js && $fasta ]
 type_constants_test/01: MissingCompileTimeError # Issue 32557
 
+[ $compiler == dartk && $mode == debug && ($hot_reload || $hot_reload_rollback) ]
+inference_enum_list_test: Skip # Issue 35885
+
 [ $compiler == dartk && $runtime == vm && !$checked && $strong ]
 assertion_initializer_const_error2_test/cc01: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc02: MissingCompileTimeError # Not reporting failed assert() at compile time.
@@ -340,14 +415,44 @@
 assertion_initializer_const_error2_test/cc09: MissingCompileTimeError # Not reporting failed assert() at compile time.
 assertion_initializer_const_error2_test/cc10: MissingCompileTimeError # Not reporting failed assert() at compile time.
 
+[ $compiler == dartk && ($arch == simarm || $arch == simarm64) ]
+control_flow_collections/for_inference_test: CompileTimeError
+control_flow_collections/for_test: CompileTimeError
+control_flow_collections/for_variable_test: CompileTimeError
+control_flow_collections/if_const_test: CompileTimeError
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: CompileTimeError
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_error_test/09: Pass
+control_flow_collections/syntax_error_test/10: Pass
+control_flow_collections/syntax_test: CompileTimeError
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
+
 [ $compiler == dartkb && $runtime == vm && $strong ]
 async_star_test/03: Pass, RuntimeError # Please triage
 async_star_test/04: Pass, RuntimeError # Please triage
 compile_time_constant_o_test/01: Pass
 compile_time_constant_o_test/02: Pass
 const_dynamic_type_literal_test/02: Pass
+control_flow_collections/for_inference_test: CompileTimeError
+control_flow_collections/for_test: CompileTimeError
+control_flow_collections/for_variable_test: CompileTimeError
+control_flow_collections/if_const_test: CompileTimeError
+control_flow_collections/if_inference_test: CompileTimeError
+control_flow_collections/if_test: CompileTimeError
+control_flow_collections/map_set_ambiguity_test: CompileTimeError
+control_flow_collections/syntax_test: CompileTimeError
 map_literal3_test/01: Pass
 map_literal3_test/02: Pass
+spread_collections/const_test: CompileTimeError
+spread_collections/inference_test: CompileTimeError
+spread_collections/map_set_ambiguity_test: CompileTimeError
+spread_collections/spread_test: CompileTimeError
+spread_collections/syntax_test: CompileTimeError
 vm/bool_check_stack_traces_test/02: Pass
 vm/causal_async_exception_stack2_test: RuntimeError # Please triage
 vm/causal_async_exception_stack_test: RuntimeError # Please triage
diff --git a/tests/language_2/set_literals/const_set_flag_test.dart b/tests/language_2/set_literals/const_set_flag_test.dart
deleted file mode 100644
index 339acaf..0000000
--- a/tests/language_2/set_literals/const_set_flag_test.dart
+++ /dev/null
@@ -1,23 +0,0 @@
-// 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.
-
-// Canary test to check that set literals are not enabled *without* an
-// experimental flag.
-
-// Remove this test when the set literals feature is enabled without a flag.
-
-main() {
-  var _ = {1}; //# 01: compile-time error
-  var _ = <int>{}; //# 02: compile-time error
-  Set _ = {}; //# 03: compile-time error
-  Set _ = <int>{}; //# 04: compile-time error
-  var _ = const {1}; //# 05: compile-time error
-  var _ = const <int>{}; //# 06: compile-time error
-  Set _ = const {}; //# 07: compile-time error
-  Set _ = const <int>{}; //# 08: compile-time error
-  const _ = {1}; //# 09: compile-time error
-  const _ = <int>{}; //# 10: compile-time error
-  const Set _ = {}; //# 11: compile-time error
-  const Set _ = <int>{}; //# 12: compile-time error
-}
diff --git a/tests/language_2/spread_collections/const_error_test.dart b/tests/language_2/spread_collections/const_error_test.dart
new file mode 100644
index 0000000..7ea27a5
--- /dev/null
+++ b/tests/language_2/spread_collections/const_error_test.dart
@@ -0,0 +1,68 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,spread-collections
+
+import 'dart:collection';
+
+import 'package:expect/expect.dart';
+import 'helper_classes.dart';
+
+var nonConstList = <int>[];
+var nonConstMap = <int, String>{};
+const dynamic nonIterable = 3;
+const dynamic nonMap = 3;
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+}
+
+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_test.dart b/tests/language_2/spread_collections/const_test.dart
new file mode 100644
index 0000000..7ae1df2
--- /dev/null
+++ b/tests/language_2/spread_collections/const_test.dart
@@ -0,0 +1,181 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,spread-collections
+
+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 <int>[1, 2, <int>[3], 4], const <int>[1, ...<int>[2, <int>[3], 4]]);
+
+  // Establishes const context.
+  Expect.identical(const <Symbol>[Symbol("sym")],
+      const <Symbol>[...<Symbol>[Symbol("sym")]]);
+}
+
+void testMap() {
+  // Only spread.
+  Expect.identical(map, const <int, int>{...map});
+
+  // Spread at beginning.
+  Expect.identical(map,
+      const <int, int>{...<int, int>{1: 1, 2: 2}, 3: 3, 4: 4});
+
+  // Spread in middle.
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2, 3: 3}, 4: 4});
+
+  // Spread at end.
+  Expect.identical(map,
+      const <int, int>{1: 1, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Empty spreads.
+  Expect.identical(map, const <int, int>{
+    ...<int, int>{},
+    1: 1,
+    2: 2,
+    ...<int, int>{},
+    3: 3,
+    4: 4,
+    ...<int, int>{}
+  });
+
+  // Multiple spreads.
+  Expect.identical(map,
+      const <int, int>{...<int, int>{1: 1}, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Nested spreads.
+  Expect.identical(map, const <int, int>{
+    ...<int, int>{
+      ...<int, int>{1: 1, 2: 2},
+      ...<int, int>{3: 3, 4: 4}
+    }
+  });
+
+  // Null-aware.
+  Expect.identical(map, const <int, int>{
+    1: 1,
+    ...?<int, int>{2: 2, 3: 3},
+    ...?(null),
+    ...?<int, int>{4: 4}
+  });
+
+  // Does not deep flatten.
+  Expect.identical(const <int, Object>{
+    1: 1,
+    2: 2,
+    3: <int, int>{3: 3},
+    4: 4
+  }, const <int, Object>{
+    1: 1,
+    ...<int, Object>{
+      2: 2,
+      3: <int, int>{3: 3},
+      4: 4
+    }
+  });
+
+  // Establishes const context.
+  Expect.identical(const <Symbol, Symbol>{
+    Symbol("sym"): Symbol("bol")
+  }, const <Symbol, Symbol>{
+    ...<Symbol, Symbol>{Symbol("sym"): Symbol("bol")}
+  });
+}
+
+void testSet() {
+  // Only spread.
+  Expect.identical(set, const <int>{...set});
+  Expect.identical(set, const <int>{...list});
+
+  // Spread at beginning.
+  Expect.identical(set, const <int>{...<int>[1, 2], 3, 4});
+
+  // Spread in middle.
+  Expect.identical(set, const <int>{1, ...<int>[2, 3], 4});
+
+  // Spread at end.
+  Expect.identical(set, const <int>{1, 2, ...<int>[3, 4]});
+
+  // Empty spreads.
+  Expect.identical(set,
+      const <int>{...<int>[], 1, 2, ...<int>[], 3, 4, ...<int>[]});
+
+  // Multiple spreads.
+  Expect.identical(set, const <int>{...<int>[1], 2, ...<int>[3, 4]});
+
+  // Nested spreads.
+  Expect.identical(set, const <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
+
+  // Null-aware.
+  Expect.identical(set,
+      const <int>{1, ...?<int>[2, 3], ...?(null), ...?<int>[4]});
+
+  // Does not deep flatten.
+  Expect.identical(const <Object>{1, 2, <int>{3}, 4},
+      const <Object>{1, ...<Object>{2, <int>{3}, 4}});
+
+  // Establishes const context.
+  Expect.identical(const <Symbol>{Symbol("sym")},
+      const <Symbol>{...<Symbol>{Symbol("sym")}});
+}
+
+void testKeyOrder() {
+  // Canonicalization isn't affected by which elements are spread.
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2, 3: 3}, 4: 4});
+  Expect.identical(map,
+      const <int, int>{1: 1, ...<int, int>{2: 2}, 3: 3, ...<int, int>{4: 4}});
+
+  Expect.identical(set, const <int>{1, ...<int>{2, 3}, 4});
+  Expect.identical(set, const <int>{1, ...<int>{2}, 3, ...<int>{4}});
+
+  // Ordering does affect canonicalization.
+  Expect.notIdentical(const <int, int>{1: 1, 2: 2, 3: 3},
+      const <int, int>{1: 1, ...<int, int>{3: 3, 2: 2}});
+  Expect.notIdentical(const <int>{1, 2, 3}, const <int>{1, ...<int>{3, 2}});
+}
diff --git a/tests/language_2/spread_collections/experimental_flag_test.dart b/tests/language_2/spread_collections/experimental_flag_test.dart
new file mode 100644
index 0000000..a1c8bf7
--- /dev/null
+++ b/tests/language_2/spread_collections/experimental_flag_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// Check that spread collections are not enabled without the experimental flag.
+
+// Do enable sets, just not spread inside them.
+// SharedOptions=--enable-experiment=set-literals
+
+// TODO(rnystrom): Remove this test when the feature is enabled without a flag.
+
+void main() {
+  var _ = <int>[...<int>[1]]; //# 01: compile-time error
+  var _ = <int, int>{...<int, int>{1: 1}}; //# 02: compile-time error
+  var _ = <int>{...<int>{1}}; //# 03: compile-time error
+  var _ = <int>[...?null]; //# 04: compile-time error
+  var _ = <int, int>{...?null}; //# 05: compile-time error
+  var _ = <int>{...?null}; //# 06: compile-time error
+}
diff --git a/tests/language_2/spread_collections/helper_classes.dart b/tests/language_2/spread_collections/helper_classes.dart
new file mode 100644
index 0000000..9c35975
--- /dev/null
+++ b/tests/language_2/spread_collections/helper_classes.dart
@@ -0,0 +1,74 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+import 'dart:collection';
+
+class ConstIterable extends IterableBase<int> {
+  const ConstIterable();
+
+  Iterator<int> get iterator => <int>[].iterator;
+}
+
+class ConstMap implements Map<int, String> {
+  const ConstMap();
+
+  Iterable<MapEntry<int, String>> get entries => const [];
+
+  bool get isEmpty => throw UnsupportedError("unsupported");
+  bool get isNotEmpty => throw UnsupportedError("unsupported");
+  Iterable<int> get keys => throw UnsupportedError("unsupported");
+  int get length => throw UnsupportedError("unsupported");
+  Iterable<String> get values => throw UnsupportedError("unsupported");
+  String operator [](Object key) => throw UnsupportedError("unsupported");
+  operator []=(int key, String value) => throw UnsupportedError("unsupported");
+  bool add(Object value) => throw UnsupportedError("unsupported");
+  void addAll(Map<int, String> map) => throw UnsupportedError("unsupported");
+  void addEntries(Iterable<MapEntry<int, String>> entries) =>
+      throw UnsupportedError("unsupported");
+  Map<RK, RV> cast<RK, RV>() => throw UnsupportedError("unsupported");
+  void clear() => throw UnsupportedError("unsupported");
+  bool containsKey(Object key) => throw UnsupportedError("unsupported");
+  bool containsValue(Object value) => throw UnsupportedError("unsupported");
+  void forEach(void Function(int key, String value) f) =>
+      throw UnsupportedError("unsupported");
+  Map<K2, V2> map<K2, V2>(MapEntry<K2, V2> Function(int key, String value) f) =>
+      throw UnsupportedError("unsupported");
+  String putIfAbsent(int key, String Function() ifAbsent) =>
+      throw UnsupportedError("unsupported");
+  String remove(Object key) => throw UnsupportedError("unsupported");
+  void removeWhere(bool Function(int key, String value) predicate) =>
+      throw UnsupportedError("unsupported");
+  String update(int key, String Function(String value) update,
+          {String Function() ifAbsent}) =>
+      throw UnsupportedError("unsupported");
+  void updateAll(String Function(int key, String value) update) =>
+      throw UnsupportedError("unsupported");
+}
+
+class CustomMap with MapMixin<int, String> {
+  Iterable<int> get keys => [];
+  String operator [](Object key) => "";
+  operator []=(int key, String value) {}
+  String remove(Object key) => throw UnsupportedError("unsupported");
+  void clear() => throw UnsupportedError("unsupported");
+}
+
+class CustomSet extends SetBase<int> {
+  bool add(int value) => throw UnsupportedError("unsupported");
+  bool contains(Object value) => throw UnsupportedError("unsupported");
+  Iterator<int> get iterator => <int>[].iterator;
+  int get length => 0;
+  int lookup(Object value) => throw UnsupportedError("unsupported");
+  bool remove(Object value) => throw UnsupportedError("unsupported");
+  Set<int> toSet() => this;
+}
+
+class Equality {
+  final int id;
+  final String name;
+  const Equality(this.id, this.name);
+  int get hashCode => id;
+  bool operator ==(Object other) => other is Equality && id == other.id;
+  String toString() => "$id:$name";
+}
diff --git a/tests/language_2/spread_collections/inference_test.dart b/tests/language_2/spread_collections/inference_test.dart
new file mode 100644
index 0000000..0b3d4e5
--- /dev/null
+++ b/tests/language_2/spread_collections/inference_test.dart
@@ -0,0 +1,117 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,spread-collections
+
+// Test how spread interacts with inference.
+import 'package:expect/expect.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  // Lists.
+  Expect.type<List<dynamic>>([...[]]);
+  Expect.type<List<int>>([...<int>[]]);
+  Expect.type<List<int>>([...[1]]);
+  Expect.type<List<int>>([1, ...[2]]);
+  Expect.type<List<num>>([1, ...[0.2]]);
+  Expect.type<List<int>>([...[1, 2]]);
+  Expect.type<List<num>>([...[1, 0.2]]);
+  Expect.type<List<int>>([...[1], ...[2]]);
+  Expect.type<List<num>>([...[1], ...[0.2]]);
+
+  // Maps.
+  Expect.type<Map<dynamic, dynamic>>({...{}});
+  Expect.type<Map<int, int>>({...<int, int>{}});
+  Expect.type<Map<int, int>>({...{1: 1}});
+  Expect.type<Map<int, int>>({1: 1, ...{2: 2}});
+  Expect.type<Map<num, num>>({1: 1, ...{0.2: 0.2}});
+  Expect.type<Map<int, int>>({...{1: 1, 2: 2}});
+  Expect.type<Map<num, num>>({...{1: 1, 0.2: 0.2}});
+  Expect.type<Map<int, int>>({...{1: 1}, ...{2: 2}});
+  Expect.type<Map<num, num>>({...{1: 1}, ...{0.2: 0.2}});
+
+  // Sets.
+  Expect.type<Set<dynamic>>({...[]});
+  Expect.type<Set<int>>({...<int>[]});
+  Expect.type<Set<int>>({...[1]});
+  Expect.type<Set<int>>({1, ...[2]});
+  Expect.type<Set<num>>({1, ...[0.2]});
+  Expect.type<Set<int>>({...[1, 2]});
+  Expect.type<Set<num>>({...[1, 0.2]});
+  Expect.type<Set<int>>({...[1], ...[2]});
+  Expect.type<Set<num>>({...[1], ...[0.2]});
+  Expect.type<Set<num>>({...{1}, ...[0.2]});
+  Expect.type<Set<num>>({...{1}, ...{0.2}});
+
+  // If the iterable's type is dynamic, the element type is inferred as dynamic.
+  Expect.type<List<dynamic>>([...([] as dynamic)]);
+  Expect.type<Set<dynamic>>({1, ...([] as dynamic)});
+
+  // If the iterable's type is dynamic, the key and value types are inferred as
+  // dynamic.
+  Expect.type<Map<dynamic, dynamic>>({1: 1, ...({} as dynamic)});
+}
+
+void testTopDownInference() {
+  // Lists.
+  Iterable<T> expectIntIterable<T>() {
+    Expect.identical(int, T);
+    return [];
+  }
+
+  Iterable<T> expectDynamicIterable<T>() {
+    Expect.identical(dynamic, T);
+    return [];
+  }
+
+  // The context element type is pushed into the spread expression if it is
+  // Iterable<T>.
+  Expect.listEquals(<int>[], <int>[...expectIntIterable()]);
+
+  // Bottom up-inference from elements is not pushed back down into spread.
+  Expect.listEquals(<int>[1], [1, ...expectDynamicIterable()]);
+
+  // Maps.
+  Map<K, V> expectIntStringMap<K, V>() {
+    Expect.identical(int, K);
+    Expect.identical(String, V);
+    return {};
+  }
+
+  Map<K, V> expectDynamicDynamicMap<K, V>() {
+    Expect.identical(dynamic, K);
+    Expect.identical(dynamic, V);
+    return {};
+  }
+
+  // The context element type is pushed into the spread expression if it is
+  // Map<K, V>.
+  Expect.mapEquals(<int, String>{}, <int, String>{...expectIntStringMap()});
+
+  // Bottom up-inference from elements is not pushed back down into spread.
+  Expect.mapEquals(<int, String>{1: "s"},
+      {1: "s", ...expectDynamicDynamicMap()});
+
+  // Sets.
+  Set<T> expectIntSet<T>() {
+    Expect.identical(int, T);
+    return Set();
+  }
+
+  Set<T> expectDynamicSet<T>() {
+    Expect.identical(dynamic, T);
+    return Set();
+  }
+
+  // The context element type is pushed into the spread expression if it is
+  // Iterable<T>.
+  Expect.setEquals(<int>{}, <int>{...expectIntSet()});
+
+  // Bottom up-inference from elements is not pushed back down into spread.
+  Expect.setEquals(<int>{}, {1, ...expectDynamicSet()});
+}
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
new file mode 100644
index 0000000..ab9b822
--- /dev/null
+++ b/tests/language_2/spread_collections/map_set_ambiguity_error_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,spread-collections
+
+// Test cases where the syntax is ambiguous between maps and sets.
+import 'dart:collection';
+
+import 'helper_classes.dart';
+
+void main() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dyn = map;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  var _ = {...dyn}; //# 00: compile-time error
+  var _ = {...map, ...set}; //# 01: compile-time error
+  var _ = {...map, ...iterable}; //# 02: compile-time error
+  var _ = {...map, ...customSet}; //# 03: compile-time error
+  var _ = {...set, ...customMap}; //# 04: compile-time error
+  var _ = {...dyn, ...dyn}; //# 05: compile-time error
+  var _ = {...iterable, ...customMap}; //# 06: compile-time error
+  var _ = {...customSet, ...customMap}; //# 07: compile-time error
+}
diff --git a/tests/language_2/spread_collections/map_set_ambiguity_test.dart b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
new file mode 100644
index 0000000..48ce5a7
--- /dev/null
+++ b/tests/language_2/spread_collections/map_set_ambiguity_test.dart
@@ -0,0 +1,75 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,spread-collections
+
+// Test cases where the syntax is ambiguous between maps and sets.
+import 'dart:collection';
+
+import 'package:expect/expect.dart';
+
+import 'helper_classes.dart';
+
+void main() {
+  testBottomUpInference();
+  testTopDownInference();
+}
+
+void testBottomUpInference() {
+  Map<int, int> map = {};
+  Set<int> set = Set();
+  dynamic dyn = map;
+  Iterable<int> iterable = [];
+  CustomSet customSet = CustomSet();
+  CustomMap customMap = CustomMap();
+
+  // Note: The commented out cases are the error cases. They are shown here for
+  // completeness and tested in map_set_ambiguity_error_test.dart.
+  Expect.type<Map<int, int>>({...map});
+  Expect.type<Set<int>>({...set});
+  // Expect.type<...>({...dyn});
+  Expect.type<Set<int>>({...iterable});
+  Expect.type<Set<int>>({...customSet});
+  Expect.type<Map<int, int>>({...customMap});
+
+  Expect.type<Map<int, int>>({...map, ...map});
+  // Expect.type<...>({...map, ...set});
+  Expect.type<Map<dynamic, dynamic>>({...map, ...dyn});
+  // Expect.type<...>({...map, ...iterable});
+  // Expect.type<...>({...map, ...customSet});
+  Expect.type<Map<int, int>>({...map, ...customMap});
+
+  Expect.type<Set<int>>({...set, ...set});
+  Expect.type<Set<dynamic>>({...set, ...dyn});
+  Expect.type<Set<int>>({...set, ...iterable});
+  Expect.type<Set<int>>({...set, ...customSet});
+  // Expect.type<...>({...set, ...customMap});
+
+  // Expect.type<...>({...dyn, ...dyn});
+  Expect.type<Set<dynamic>>({...dyn, ...iterable});
+  Expect.type<Set<dynamic>>({...dyn, ...customSet});
+  Expect.type<Map<dynamic, dynamic>>({...dyn, ...customMap});
+
+  Expect.type<Set<int>>({...iterable, ...iterable});
+  Expect.type<Set<int>>({...iterable, ...customSet});
+  // Expect.type<...>({...iterable, ...customMap});
+
+  Expect.type<Set<int>>({...customSet, ...customSet});
+  // Expect.type<...>({...customSet, ...customMap});
+
+  Expect.type<Map<int, int>>({...customMap, ...customMap});
+}
+
+void testTopDownInference() {
+  dynamic untypedMap = <int, int>{};
+  dynamic untypedIterable = <int>[];
+
+  Map<int, int> map = {...untypedMap};
+  Set<int> set = {...untypedIterable};
+  Iterable<int> iterable = {...untypedIterable};
+
+  Expect.type<Map<int, int>>(map);
+  Expect.type<Set<int>>(set);
+  Expect.type<Set<int>>(iterable);
+}
diff --git a/tests/language_2/spread_collections/spread_test.dart b/tests/language_2/spread_collections/spread_test.dart
new file mode 100644
index 0000000..aab98da
--- /dev/null
+++ b/tests/language_2/spread_collections/spread_test.dart
@@ -0,0 +1,222 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for 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=set-literals,spread-collections
+
+import 'package:expect/expect.dart';
+
+import 'helper_classes.dart';
+
+// Typed as dynamic to also test spreading a value of type dynamic.
+final dynamic list = [1, 2, 3, 4];
+final dynamic map = {1: 1, 2: 2, 3: 3, 4: 4};
+final dynamic set = {1, 2, 3, 4};
+
+void main() {
+  testList();
+  testMap();
+  testSet();
+  testDuplicateKeys();
+  testKeyOrder();
+  testCastFailures();
+}
+
+void testList() {
+  // Only spread.
+  Expect.listEquals(list, <int>[...list]);
+
+  // Spread at beginning.
+  Expect.listEquals(list, <int>[...<int>[1, 2], 3, 4]);
+
+  // Spread in middle.
+  Expect.listEquals(list, <int>[1, ...<int>[2, 3], 4]);
+
+  // Spread at end.
+  Expect.listEquals(list, <int>[1, 2, ...<int>[3, 4]]);
+
+  // Empty spreads.
+  Expect.listEquals(list,
+      <int>[...<int>[], 1, 2, ...<int>[], 3, 4, ...<int>[]]);
+
+  // Multiple spreads.
+  Expect.listEquals(list, <int>[...<int>[1], 2, ...<int>[3, 4]]);
+
+  // Nested spreads.
+  Expect.listEquals(list, <int>[...<int>[...<int>[1, 2], ...<int>[3, 4]]]);
+
+  // Null-aware.
+  Expect.listEquals(list, <int>[1, ...?<int>[2, 3], ...?(null), ...?<int>[4]]);
+
+  // Does not deep flatten.
+  var innerList = <int>[3];
+  Expect.listEquals(
+      <int>[1, 2, innerList, 4], <int>[1, ...<int>[2, innerList, 4]]);
+
+  // Downcast element.
+  Expect.listEquals(list, <int>[...<num>[1, 2, 3, 4]]);
+}
+
+void testMap() {
+  // Only spread.
+  Expect.mapEquals(map, <int, int>{...map});
+
+  // Spread at beginning.
+  Expect.mapEquals(map, <int, int>{...<int, int>{1: 1, 2: 2}, 3: 3, 4: 4});
+
+  // Spread in middle.
+  Expect.mapEquals(map, <int, int>{1: 1, ...<int, int>{2: 2, 3: 3}, 4: 4});
+
+  // Spread at end.
+  Expect.mapEquals(map, <int, int>{1: 1, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Empty spreads.
+  Expect.mapEquals(map, <int, int>{
+    ...<int, int>{},
+    1: 1,
+    2: 2,
+    ...<int, int>{},
+    3: 3,
+    4: 4,
+    ...<int, int>{}
+  });
+
+  // Multiple spreads.
+  Expect.mapEquals(map,
+      <int, int>{...<int, int>{1: 1}, 2: 2, ...<int, int>{3: 3, 4: 4}});
+
+  // Nested spreads.
+  Expect.mapEquals(map, <int, int>{
+    ...<int, int>{
+      ...<int, int>{1: 1, 2: 2},
+      ...<int, int>{3: 3, 4: 4}
+    }
+  });
+
+  // Null-aware.
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    ...?<int, int>{2: 2, 3: 3},
+    ...?(null),
+    ...?<int, int>{4: 4}
+  });
+
+  // Does not deep flatten.
+  var innerMap = <int, int>{3: 3};
+  Expect.mapEquals(<int, Object>{
+    1: 1,
+    2: 2,
+    3: innerMap,
+    4: 4
+  }, <int, Object>{
+    1: 1,
+    ...<int, Object>{
+      2: 2,
+      3: innerMap,
+      4: 4
+    }
+  });
+
+  // Downcast element.
+  Expect.mapEquals(map, <int, int>{...<num, num>{1: 1, 2: 2, 3: 3, 4: 4}});
+}
+
+void testSet() {
+  // Only spread.
+  Expect.setEquals(set, <int>{...set});
+
+  // Spread at beginning.
+  Expect.setEquals(set, <int>{...<int>[1, 2], 3, 4});
+
+  // Spread in middle.
+  Expect.setEquals(set, <int>{1, ...<int>[2, 3], 4});
+
+  // Spread at end.
+  Expect.setEquals(set, <int>{1, 2, ...<int>[3, 4]});
+
+  // Empty spreads.
+  Expect.setEquals(set, <int>{...<int>[], 1, 2, ...<int>[], 3, 4, ...<int>[]});
+
+  // Multiple spreads.
+  Expect.setEquals(set, <int>{...<int>[1], 2, ...<int>[3, 4]});
+
+  // Nested spreads.
+  Expect.setEquals(set, <int>{...<int>{...<int>[1, 2], ...<int>[3, 4]}});
+
+  // Null-aware.
+  Expect.setEquals(set, <int>{1, ...?<int>[2, 3], ...?(null), ...?<int>[4]});
+
+  // Does not deep flatten.
+  var innerSet = <int>{3};
+  Expect.setEquals(<Object>{1, 2, innerSet, 4},
+      <Object>{1, ...<Object>[2, innerSet, 4]});
+
+  // Downcast element.
+  Expect.setEquals(set, <int>{...<num>[1, 2, 3, 4]});
+}
+
+void testDuplicateKeys() {
+  Expect.mapEquals(map, <int, int>{
+    1: 1,
+    2: 2,
+    ...<int, int>{2: 2, 3: 3, 4: 4},
+    ...<int, int>{3: 3},
+    4: 4
+  });
+  Expect.setEquals(set, <int>{1, 2, ...<int>[1, 2, 3, 4], ...<int>[2, 3], 4});
+}
+
+void testKeyOrder() {
+  // First equal key wins.
+  var e1a = Equality(1, "a");
+  var e1b = Equality(1, "b");
+  var e2a = Equality(2, "a");
+  var e2b = Equality(2, "b");
+
+  var map = <Equality, int>{e1a: 1, ...<Equality, int>{e1b: 2, e2a: 3, e2b: 4}};
+  Expect.equals("1:a,2:a", map.keys.join(","));
+
+  var set = <Equality>{e1a, ...<Equality>[e1b, e2a, e2b]};
+  Expect.equals("1:a,2:a", set.join(","));
+
+  // All elements are evaluated, left to right.
+  var transcript = <String>[];
+  T log<T>(T value) {
+    transcript.add(value.toString());
+    return value;
+  }
+
+  map = <Equality, int>{
+    log(e1a): log(1),
+    ...<Equality, int>{log(e1b): log(2), log(e2a): log(3), log(e2b): log(4)}
+  };
+  Expect.equals("1:a,1,1:b,2,2:a,3,2:b,4", transcript.join(","));
+
+  transcript.clear();
+  set = <Equality>{log(e1a), ...<Equality>[log(e1b), log(e2a), log(e2b)]};
+  Expect.equals("1:a,1:b,2:a,2:b", transcript.join(","));
+}
+
+void testCastFailures() {
+  dynamic nonIterable = 3;
+  Expect.throwsCastError(() => <int>[...nonIterable]);
+  Expect.throwsCastError(() => <int>{...nonIterable});
+
+  dynamic nonMap = 3;
+  Expect.throwsCastError(() => <int, int>{...nonMap});
+
+  dynamic wrongIterableType = <String>["s"];
+  Expect.throwsCastError(() => <int>[...wrongIterableType]);
+  Expect.throwsCastError(() => <int>{...wrongIterableType});
+
+  dynamic wrongKeyType = <String, int>{"s": 1};
+  dynamic wrongValueType = <int, String>{1: "s"};
+  Expect.throwsCastError(() => <int, int>{...wrongKeyType});
+  Expect.throwsCastError(() => <int, int>{...wrongValueType});
+
+  // Mismatched collection types.
+  Expect.throwsCastError(() => <int>[...map]);
+  Expect.throwsCastError(() => <int, int>{...list});
+  Expect.throwsCastError(() => <int, int>{...set});
+  Expect.throwsCastError(() => <int>{...map});
+}
diff --git a/tests/language_2/spread_collections/syntax_error_test.dart b/tests/language_2/spread_collections/syntax_error_test.dart
new file mode 100644
index 0000000..9f38d74
--- /dev/null
+++ b/tests/language_2/spread_collections/syntax_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=set-literals,spread-collections
+
+void main() {
+  // Spread nothing.
+  var _ = [...]; //# 00: compile-time error
+  var _ = [...?]; //# 01: compile-time error
+  var _ = [...,]; //# 02: compile-time error
+
+  // Use `...` in map entry.
+  var _ = {"a": ...{}}; //# 03: compile-time error
+  var _ = {...{}: "b"}; //# 04: compile-time error
+  var _ = {"a": ...?{}}; //# 05: compile-time error
+  var _ = {...?{}: "b"}; //# 06: compile-time error
+
+  // Treats `...?` as single token.
+  var _ = [... ?null]; //# 07: compile-time error
+  var _ = {1: 2, ... ?null}; //# 08: compile-time error
+}
diff --git a/tests/language_2/spread_collections/syntax_test.dart b/tests/language_2/spread_collections/syntax_test.dart
new file mode 100644
index 0000000..c46b589
--- /dev/null
+++ b/tests/language_2/spread_collections/syntax_test.dart
@@ -0,0 +1,28 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+// SharedOptions=--enable-experiment=set-literals,spread-collections
+
+// Tests syntax edge cases.
+import 'package:expect/expect.dart';
+
+void main() {
+  // Trailing comma.
+  Expect.listEquals([1, 2], [...[1, 2],]);
+  Expect.mapEquals({1: 1, 2: 2}, {...{1: 1, 2: 2},});
+  Expect.setEquals({1, 2}, {...{1, 2},});
+
+  // Precedence.
+  Expect.listEquals([1, 2, 3], [1, ...true ? [2] : [], 3]);
+  Expect.listEquals([1, 3], [1, ...?true ? null : [], 3]);
+
+  var a = [0];
+  Expect.listEquals([1, 2, 3], [1, ...a = [2], 3]);
+  Expect.listEquals([1, 3], [1, ...?a = null, 3]);
+
+  var b = [2];
+  Expect.listEquals([1, 2, 3, 4], [1, ...b..add(3), 4]);
+  b = [2];
+  Expect.listEquals([1, 2, 3, 4], [1, ...?b..add(3), 4]);
+}
diff --git a/tests/language_2/spread_collections/type_error_test.dart b/tests/language_2/spread_collections/type_error_test.dart
new file mode 100644
index 0000000..06f1cab
--- /dev/null
+++ b/tests/language_2/spread_collections/type_error_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.
+
+// SharedOptions=--enable-experiment=set-literals,spread-collections
+
+void main() {
+  // Spread non-iterable or non-map.
+  var _ = [...(3)]; //# 00: compile-time error
+  var _ = <int, int>{...(3)}; //# 01: compile-time error
+  var _ = <int>{...(3)}; //# 02: compile-time error
+
+  // Object.
+  var _ = [...([] as Object)]; //# 03: compile-time error
+  var _ = <int, int>{...({} as Object)}; //# 04: compile-time error
+  var _ = <int>{...([] as Object)}; //# 05: compile-time error
+
+  // Wrong element type.
+  var _ = <int>[...<String>[]]; //# 06: compile-time error
+  var _ = <int, int>{...<String, int>{}}; //# 07: compile-time error
+  var _ = <int, int>{...<int, String>{}}; //# 08: compile-time error
+  var _ = <int>{...<String>[]}; //# 09: compile-time error
+}
diff --git a/tests/language_2/switch_test.dart b/tests/language_2/switch_test.dart
index a0cb2df..0b12c0e7 100644
--- a/tests/language_2/switch_test.dart
+++ b/tests/language_2/switch_test.dart
@@ -110,6 +110,37 @@
   Expect.equals(expect, result);
 }
 
+void testSwitchString(String input, int expect) {
+  int result = null;
+  switch (input) {
+    case 'one':
+      result = 1;
+      break;
+    case 'two':
+      result = 2;
+      break;
+  }
+  Expect.equals(expect, result);
+}
+
+switchConstString() {
+  const c = 'a';
+  switch (c) {
+    case 'a':
+      return 'aa';
+    case 'b':
+      return 'bb';
+    case 'c':
+      return 'cc';
+    case 'd':
+      return 'dd';
+    case 'e':
+      return 'ee';
+    case 'f':
+      return 'ff';
+  }
+}
+
 main() {
   SwitchTest.testMain();
 
@@ -127,4 +158,11 @@
 
   testSwitchBool(true, 12);
   testSwitchBool(false, 22);
+
+  testSwitchString(null, null);
+  testSwitchString('one', 1);
+  testSwitchString('two', 2);
+  testSwitchString('three', null);
+
+  Expect.equals('aa', switchConstString());
 }
diff --git a/tests/language_2/vm/modtruncdiv_int_test.dart b/tests/language_2/vm/modtruncdiv_int_test.dart
index 8314628..b838b15 100644
--- a/tests/language_2/vm/modtruncdiv_int_test.dart
+++ b/tests/language_2/vm/modtruncdiv_int_test.dart
@@ -92,6 +92,12 @@
   Expect.equals(0, mod(minInt64, 1 << 63));
 }
 
+doModVarConstant() {
+  for (int i = -10; i < 10; i++) {
+    Expect.equals(i & maxInt64, mod(i, minInt64));
+  }
+}
+
 doTruncDivConstants() {
   Expect.equals(0, truncdiv(0, 1));
   Expect.equals(0, truncdiv(0, -1));
@@ -175,6 +181,7 @@
     // Constants.
 
     doModConstants();
+    doModVarConstant();
     doTruncDivConstants();
 
     // Variable ranges.
diff --git a/tests/lib_2/convert/json_test.dart b/tests/lib_2/convert/json_test.dart
index 22e5f24..8ebfe63 100644
--- a/tests/lib_2/convert/json_test.dart
+++ b/tests/lib_2/convert/json_test.dart
@@ -15,22 +15,24 @@
       Expect.isTrue(actual is List);
       Expect.equals(expected.length, actual.length, "$path: List length");
       for (int i = 0; i < expected.length; i++) {
-        compare(expected[i], actual[i], "$path[$i]");
+        compare(expected[i], actual[i], "$path[$i] in $jsonText");
       }
     } else if (expected is Map) {
       Expect.isTrue(actual is Map);
-      Expect.equals(expected.length, actual.length, "$path: Map size");
+      Expect.equals(expected.length, actual.length,
+          "$path: Map size in $jsonText");
       expected.forEach((key, value) {
         Expect.isTrue(actual.containsKey(key));
-        compare(value, actual[key], "$path[$key]");
+        compare(value, actual[key], "$path[$key] in $jsonText");
       });
     } else if (expected is num) {
-      Expect.equals(expected is int, actual is int, "$path: same number type");
+      Expect.equals(expected is int, actual is int,
+          "$path: not same number type in $jsonText");
       Expect.isTrue(expected.compareTo(actual) == 0,
-          "$path: Expected: $expected, was: $actual");
+          "$path: Expected: $expected, was: $actual in $jsonText");
     } else {
       // String, bool, null.
-      Expect.equals(expected, actual, path);
+      Expect.equals(expected, actual, "$path in $jsonText");
     }
   }
 
@@ -142,6 +144,45 @@
     }
   }
 
+  // Regression test.
+  // Detect and handle overflow on integer literals by making them doubles
+  // (work like `num.parse`).
+  testJson("9223372036854774784", 9223372036854774784);
+  testJson("-9223372036854775808", -9223372036854775808);
+  testJson("9223372036854775808", 9223372036854775808.0);
+  testJson("-9223372036854775809", -9223372036854775809.0);
+  testJson("9223372036854775808.0", 9223372036854775808.0);
+  testJson("9223372036854775810", 9223372036854775810.0);
+  testJson("18446744073709551616.0", 18446744073709551616.0);
+  testJson("1e309", double.infinity);
+  testJson("-1e309", double.negativeInfinity);
+  testJson("1e-325", 0.0);
+  testJson("-1e-325", -0.0);
+  // No overflow on exponent.
+  testJson("1e18446744073709551616", double.infinity);
+  testJson("-1e18446744073709551616", double.negativeInfinity);
+  testJson("1e-18446744073709551616", 0.0);
+  testJson("-1e-18446744073709551616", -0.0);
+
+  // (Wrapping numbers in list because the chunked parsing handles top-level
+  // numbers by buffering and then parsing using platform parser).
+  testJson("[9223372036854774784]", [9223372036854774784]);
+  testJson("[-9223372036854775808]", [-9223372036854775808]);
+  testJson("[9223372036854775808]", [9223372036854775808.0]);
+  testJson("[-9223372036854775809]", [-9223372036854775809.0]);
+  testJson("[9223372036854775808.0]", [9223372036854775808.0]);
+  testJson("[9223372036854775810]", [9223372036854775810.0]);
+  testJson("[18446744073709551616.0]", [18446744073709551616.0]);
+  testJson("[1e309]", [double.infinity]);
+  testJson("[-1e309]", [double.negativeInfinity]);
+  testJson("[1e-325]", [0.0]);
+  testJson("[-1e-325]", [-0.0]);
+  // No overflow on exponent.
+  testJson("[1e18446744073709551616]", [double.infinity]);
+  testJson("[-1e18446744073709551616]", [double.negativeInfinity]);
+  testJson("[1e-18446744073709551616]", [0.0]);
+  testJson("[-1e-18446744073709551616]", [-0.0]);
+
   // Negative tests (syntax error).
   // testError thoroughly tests the given parts with a lot of valid
   // values for the other parts.
diff --git a/tests/lib_2/lib_2_dartdevc.status b/tests/lib_2/lib_2_dartdevc.status
index 55192e7..0532e64 100644
--- a/tests/lib_2/lib_2_dartdevc.status
+++ b/tests/lib_2/lib_2_dartdevc.status
@@ -43,6 +43,7 @@
 convert/utf85_test: Slow, Pass
 html/async_spawnuri_test: RuntimeError # Issue 29922
 html/async_test: RuntimeError # Issue 29922
+html/callback_list_test: Skip # Test requires user interaction to accept permissions.
 html/custom/attribute_changed_callback_test: Skip # Issue 31577
 html/custom/constructor_calls_created_synchronously_test: Skip # Issue 31577
 html/custom/created_callback_test: RuntimeError
diff --git a/tests/standalone_2/ffi/coordinate.dart b/tests/standalone_2/ffi/coordinate.dart
new file mode 100644
index 0000000..fbca952
--- /dev/null
+++ b/tests/standalone_2/ffi/coordinate.dart
@@ -0,0 +1,40 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+/// Sample struct for dart:ffi library.
+@ffi.struct
+class Coordinate extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  double x;
+
+  @ffi.Double()
+  double y;
+
+  @ffi.Pointer()
+  Coordinate next;
+
+  /// generated by @ffi.struct annotation
+  external static int sizeOf();
+
+  Coordinate offsetBy(int offsetInBytes) =>
+      super.offsetBy(offsetInBytes).cast();
+
+  Coordinate elementAt(int index) => offsetBy(sizeOf() * index);
+
+  static Coordinate allocate({int count: 1}) =>
+      ffi.allocate<ffi.Uint8>(count: count * sizeOf()).cast();
+
+  /// Allocate a new [Coordinate] in C memory and populate its fields.
+  factory Coordinate(double x, double y, Coordinate next) {
+    Coordinate result = Coordinate.allocate()
+      ..x = x
+      ..y = y
+      ..next = next;
+    return result;
+  }
+}
diff --git a/tests/standalone_2/ffi/coordinate_bare.dart b/tests/standalone_2/ffi/coordinate_bare.dart
new file mode 100644
index 0000000..764cb9f
--- /dev/null
+++ b/tests/standalone_2/ffi/coordinate_bare.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.
+
+library FfiTestCoordinateBare;
+
+import 'dart:ffi' as ffi;
+
+/// Stripped down sample struct for dart:ffi library.
+@ffi.struct
+class Coordinate extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  double x;
+
+  @ffi.Double()
+  double y;
+
+  @ffi.Pointer()
+  Coordinate next;
+}
diff --git a/tests/standalone_2/ffi/coordinate_manual.dart b/tests/standalone_2/ffi/coordinate_manual.dart
new file mode 100644
index 0000000..d4d1aca
--- /dev/null
+++ b/tests/standalone_2/ffi/coordinate_manual.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.
+
+library FfiTestCoordinateManual;
+
+import 'dart:ffi' as ffi;
+
+/// Sample struct for dart:ffi library without use of ffi annotations.
+class Coordinate extends ffi.Pointer<ffi.Void> {
+  ffi.Pointer<ffi.Double> get _xPtr => cast();
+  set x(double v) => _xPtr.store(v);
+  double get x => _xPtr.load();
+
+  ffi.Pointer<ffi.Double> get _yPtr =>
+      offsetBy(ffi.sizeOf<ffi.Double>() * 1).cast();
+  set y(double v) => _yPtr.store(v);
+  double get y => _yPtr.load();
+
+  ffi.Pointer<Coordinate> get _nextPtr =>
+      offsetBy(ffi.sizeOf<ffi.Double>() * 2).cast();
+  set next(Coordinate v) => _nextPtr.store(v);
+  Coordinate get next => _nextPtr.load();
+
+  static int sizeOf() =>
+      ffi.sizeOf<ffi.Double>() * 2 + ffi.sizeOf<ffi.IntPtr>();
+
+  Coordinate offsetBy(int offsetInBytes) =>
+      super.offsetBy(offsetInBytes).cast();
+
+  Coordinate elementAt(int index) => offsetBy(sizeOf() * index);
+
+  static Coordinate allocate({int count: 1}) =>
+      ffi.allocate<ffi.Uint8>(count: count * sizeOf()).cast();
+
+  /// Allocate a new [Coordinate] in C memory and populate its fields.
+  factory Coordinate(double x, double y, Coordinate next) {
+    Coordinate result = Coordinate.allocate()
+      ..x = x
+      ..y = y
+      ..next = next;
+    return result;
+  }
+}
diff --git a/tests/standalone_2/ffi/cstring.dart b/tests/standalone_2/ffi/cstring.dart
new file mode 100644
index 0000000..b976007
--- /dev/null
+++ b/tests/standalone_2/ffi/cstring.dart
@@ -0,0 +1,32 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+
+library FfiTest;
+
+import 'dart:convert';
+import 'dart:ffi' as ffi;
+
+/// Sample non-struct subtype of Pointer for dart:ffi library.
+class CString extends ffi.Pointer<ffi.Uint8> {
+  CString elementAt(int index) => super.elementAt(index).cast();
+
+  String fromUtf8() {
+    List<int> units = [];
+    int len = 0;
+    while (true) {
+      int char = elementAt(len++).load<int>();
+      if (char == 0) break;
+      units.add(char);
+    }
+    return Utf8Decoder().convert(units);
+  }
+
+  factory CString.toUtf8(String s) {
+    CString result = ffi.allocate<ffi.Uint8>(count: s.length + 1).cast();
+    List<int> units = Utf8Encoder().convert(s);
+    for (int i = 0; i < s.length; i++) result.elementAt(i).store(units[i]);
+    result.elementAt(s.length).store(0);
+    return result;
+  }
+}
diff --git a/tests/standalone_2/ffi/data_not_asan_test.dart b/tests/standalone_2/ffi/data_not_asan_test.dart
new file mode 100644
index 0000000..2be8598
--- /dev/null
+++ b/tests/standalone_2/ffi/data_not_asan_test.dart
@@ -0,0 +1,29 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi primitive data pointers.
+// This test tries to allocate too much memory on purpose to test the Exception
+// thrown on malloc failing.
+// This malloc also triggers an asan alarm, so this test is in a separate file
+// which is excluded in asan mode.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+void main() {
+  testPointerAllocateTooLarge();
+}
+
+/// This test is skipped in asan mode.
+void testPointerAllocateTooLarge() {
+  int maxInt = 9223372036854775807; // 2^63 - 1
+  Expect.throws(
+      () => ffi.allocate<ffi.Int64>(count: maxInt)); // does not fit in range
+  int maxInt1_8 = 1152921504606846975; // 2^60 -1
+  Expect.throws(
+      () => ffi.allocate<ffi.Int64>(count: maxInt1_8)); // not enough memory
+}
diff --git a/tests/standalone_2/ffi/data_test.dart b/tests/standalone_2/ffi/data_test.dart
new file mode 100644
index 0000000..26edd6f
--- /dev/null
+++ b/tests/standalone_2/ffi/data_test.dart
@@ -0,0 +1,492 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi primitive data pointers.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+void main() {
+  testPointerBasic();
+  testPointerFromPointer();
+  testPointerPointerArithmetic();
+  testPointerPointerArithmeticSizes();
+  testPointerAllocateNonPositive();
+  testPointerCast();
+  testCastGeneric();
+  testCastGeneric2();
+  testCastNativeType();
+  testCondensedNumbersInt8();
+  testCondensedNumbersFloat();
+  testRangeInt8();
+  testRangeUint8();
+  testRangeInt16();
+  testRangeUint16();
+  testRangeInt32();
+  testRangeUint32();
+  testRangeInt64();
+  testRangeUint64();
+  testRangeIntPtr();
+  testFloat();
+  testDouble();
+  testVoid();
+  testPointerPointer();
+  testPointerPointerNull();
+  testPointerStoreNull();
+  testSizeOf();
+  testPointerChain(100);
+  testTypeTest();
+  testToString();
+  testEquality();
+  testAllocateGeneric();
+  testAllocateVoid();
+  testAllocateNativeFunction();
+  testAllocateNativeType();
+  testSizeOfGeneric();
+  testSizeOfVoid();
+  testSizeOfNativeFunction();
+  testSizeOfNativeType();
+  testFreeZeroOut();
+}
+
+void testPointerBasic() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  p.store(42);
+  Expect.equals(42, p.load<int>());
+  p.free();
+}
+
+void testPointerFromPointer() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  p.store(1337);
+  int ptr = p.address;
+  ffi.Pointer<ffi.Int64> p2 = ffi.fromAddress(ptr);
+  Expect.equals(1337, p2.load<int>());
+  p.free();
+}
+
+void testPointerPointerArithmetic() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate(count: 2);
+  ffi.Pointer<ffi.Int64> p2 = p.elementAt(1);
+  p2.store(100);
+  ffi.Pointer<ffi.Int64> p3 = p.offsetBy(8);
+  Expect.equals(100, p3.load<int>());
+  p.free();
+}
+
+void testPointerPointerArithmeticSizes() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate(count: 2);
+  ffi.Pointer<ffi.Int64> p2 = p.elementAt(1);
+  int addr = p.address;
+  Expect.equals(addr + 8, p2.address);
+  p.free();
+
+  ffi.Pointer<ffi.Int32> p3 = ffi.allocate(count: 2);
+  ffi.Pointer<ffi.Int32> p4 = p3.elementAt(1);
+  addr = p3.address;
+  Expect.equals(addr + 4, p4.address);
+  p3.free();
+}
+
+void testPointerAllocateNonPositive() {
+  Expect.throws(() => ffi.allocate<ffi.Int8>(count: 0));
+  Expect.throws(() => ffi.allocate<ffi.Int8>(count: -1));
+}
+
+void testPointerCast() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  ffi.Pointer<ffi.Int32> p2 = p.cast(); // gets the correct type args back
+  p.free();
+}
+
+void testCastGeneric() {
+  ffi.Pointer<T> generic<T extends ffi.NativeType>(ffi.Pointer<ffi.Int16> p) {
+    return p.cast();
+  }
+
+  ffi.Pointer<ffi.Int16> p = ffi.allocate();
+  ffi.Pointer<ffi.Int64> p2 = generic(p);
+  p.free();
+}
+
+void testCastGeneric2() {
+  ffi.Pointer<ffi.Int64> generic<T extends ffi.NativeType>(ffi.Pointer<T> p) {
+    return p.cast();
+  }
+
+  ffi.Pointer<ffi.Int16> p = ffi.allocate();
+  ffi.Pointer<ffi.Int64> p2 = generic(p);
+  p.free();
+}
+
+void testCastNativeType() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  Expect.throws(() {
+    p.cast<ffi.Pointer>();
+  });
+  p.free();
+}
+
+void testCondensedNumbersInt8() {
+  ffi.Pointer<ffi.Int8> p = ffi.allocate(count: 8);
+  for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+    p.elementAt(i).store(i * 3);
+  }
+  for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+    Expect.equals(i * 3, p.elementAt(i).load<int>());
+  }
+  p.free();
+}
+
+void testCondensedNumbersFloat() {
+  ffi.Pointer<ffi.Float> p = ffi.allocate(count: 8);
+  for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+    p.elementAt(i).store(1.511366173271439e-13);
+  }
+  for (var i in [0, 1, 2, 3, 4, 5, 6, 7]) {
+    Expect.equals(1.511366173271439e-13, p.elementAt(i).load<double>());
+  }
+  p.free();
+}
+
+void testRangeInt8() {
+  ffi.Pointer<ffi.Int8> p = ffi.allocate();
+  p.store(127);
+  Expect.equals(127, p.load<int>());
+  p.store(-128);
+  Expect.equals(-128, p.load<int>());
+
+  Expect.equals(0x0000000000000080, 128);
+  Expect.equals(0xFFFFFFFFFFFFFF80, -128);
+  p.store(128);
+  Expect.equals(-128, p.load<int>()); // truncated and sign extended
+
+  Expect.equals(0xFFFFFFFFFFFFFF7F, -129);
+  Expect.equals(0x000000000000007F, 127);
+  p.store(-129);
+  Expect.equals(127, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeUint8() {
+  ffi.Pointer<ffi.Uint8> p = ffi.allocate();
+  p.store(255);
+  Expect.equals(255, p.load<int>());
+  p.store(0);
+  Expect.equals(0, p.load<int>());
+
+  Expect.equals(0x0000000000000000, 0);
+  Expect.equals(0x0000000000000100, 256);
+  p.store(256);
+  Expect.equals(0, p.load<int>()); // truncated
+
+  Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
+  Expect.equals(0x00000000000000FF, 255);
+  p.store(-1);
+  Expect.equals(255, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeInt16() {
+  ffi.Pointer<ffi.Int16> p = ffi.allocate();
+  p.store(0x7FFF);
+  Expect.equals(0x7FFF, p.load<int>());
+  p.store(-0x8000);
+  Expect.equals(-0x8000, p.load<int>());
+  p.store(0x8000);
+  Expect.equals(
+      0xFFFFFFFFFFFF8000, p.load<int>()); // truncated and sign extended
+  p.store(-0x8001);
+  Expect.equals(0x7FFF, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeUint16() {
+  ffi.Pointer<ffi.Uint16> p = ffi.allocate();
+  p.store(0xFFFF);
+  Expect.equals(0xFFFF, p.load<int>());
+  p.store(0);
+  Expect.equals(0, p.load<int>());
+  p.store(0x10000);
+  Expect.equals(0, p.load<int>()); // truncated
+  p.store(-1);
+  Expect.equals(0xFFFF, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeInt32() {
+  ffi.Pointer<ffi.Int32> p = ffi.allocate();
+  p.store(0x7FFFFFFF);
+  Expect.equals(0x7FFFFFFF, p.load<int>());
+  p.store(-0x80000000);
+  Expect.equals(-0x80000000, p.load<int>());
+  p.store(0x80000000);
+  Expect.equals(
+      0xFFFFFFFF80000000, p.load<int>()); // truncated and sign extended
+  p.store(-0x80000001);
+  Expect.equals(0x7FFFFFFF, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeUint32() {
+  ffi.Pointer<ffi.Uint32> p = ffi.allocate();
+  p.store(0xFFFFFFFF);
+  Expect.equals(0xFFFFFFFF, p.load<int>());
+  p.store(0);
+  Expect.equals(0, p.load<int>());
+  p.store(0x100000000);
+  Expect.equals(0, p.load<int>()); // truncated
+  p.store(-1);
+  Expect.equals(0xFFFFFFFF, p.load<int>()); // truncated
+  p.free();
+}
+
+void testRangeInt64() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
+  Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
+  p.store(-0x8000000000000000); // -2 ^ 63
+  Expect.equals(-0x8000000000000000, p.load<int>());
+  p.free();
+}
+
+void testRangeUint64() {
+  ffi.Pointer<ffi.Uint64> p = ffi.allocate();
+  p.store(0x7FFFFFFFFFFFFFFF); // 2 ^ 63 - 1
+  Expect.equals(0x7FFFFFFFFFFFFFFF, p.load<int>());
+  p.store(-0x8000000000000000); // -2 ^ 63 interpreted as 2 ^ 63
+  Expect.equals(-0x8000000000000000, p.load<int>());
+
+  // Dart allows interpreting bits both signed and unsigned
+  Expect.equals(0xFFFFFFFFFFFFFFFF, -1);
+  p.store(-1); // -1 interpreted as 2 ^ 64 - 1
+  Expect.equals(-1, p.load<int>());
+  Expect.equals(0xFFFFFFFFFFFFFFFF, p.load<int>());
+  p.free();
+}
+
+void testRangeIntPtr() {
+  ffi.Pointer<ffi.IntPtr> p = ffi.allocate();
+  int pAddr = p.address;
+  p.store(pAddr); // its own address should fit
+  p.store(0x7FFFFFFF); // and 32 bit addresses should fit
+  Expect.equals(0x7FFFFFFF, p.load<int>());
+  p.store(-0x80000000);
+  Expect.equals(-0x80000000, p.load<int>());
+  p.free();
+}
+
+void testFloat() {
+  ffi.Pointer<ffi.Float> p = ffi.allocate();
+  p.store(1.511366173271439e-13);
+  Expect.equals(1.511366173271439e-13, p.load<double>());
+  p.store(1.4260258159703532e-105); // float does not have enough precision
+  Expect.notEquals(1.4260258159703532e-105, p.load<double>());
+  p.free();
+}
+
+void testDouble() {
+  ffi.Pointer<ffi.Double> p = ffi.allocate();
+  p.store(1.4260258159703532e-105);
+  Expect.equals(1.4260258159703532e-105, p.load<double>());
+  p.free();
+}
+
+void testVoid() {
+  ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
+  ffi.Pointer<ffi.Void> p2 = p1.cast(); // make this dart pointer opaque
+  p2.address; // we can print the address
+  p2.free();
+}
+
+void testPointerPointer() {
+  ffi.Pointer<ffi.Int16> p = ffi.allocate();
+  p.store(17);
+  ffi.Pointer<ffi.Pointer<ffi.Int16>> p2 = ffi.allocate();
+  p2.store(p);
+  Expect.equals(17, p2.load<ffi.Pointer<ffi.Int16>>().load<int>());
+  p2.free();
+  p.free();
+}
+
+void testPointerPointerNull() {
+  ffi.Pointer<ffi.Pointer<ffi.Int8>> pointerToPointer = ffi.allocate();
+  ffi.Pointer<ffi.Int8> value = null;
+  pointerToPointer.store(value);
+  value = pointerToPointer.load();
+  Expect.isNull(value);
+  value = ffi.allocate();
+  pointerToPointer.store(value);
+  value = pointerToPointer.load();
+  Expect.isNotNull(value);
+  value.free();
+  value = null;
+  pointerToPointer.store(value);
+  value = pointerToPointer.load();
+  Expect.isNull(value);
+  pointerToPointer.free();
+}
+
+void testPointerStoreNull() {
+  int i = null;
+  ffi.Pointer<ffi.Int8> p = ffi.allocate();
+  Expect.throws(() => p.store(i));
+  p.free();
+  double d = null;
+  ffi.Pointer<ffi.Float> p2 = ffi.allocate();
+  Expect.throws(() => p2.store(d));
+  p2.free();
+}
+
+void testSizeOf() {
+  Expect.equals(1, ffi.sizeOf<ffi.Int8>());
+  Expect.equals(2, ffi.sizeOf<ffi.Int16>());
+  Expect.equals(4, ffi.sizeOf<ffi.Int32>());
+  Expect.equals(8, ffi.sizeOf<ffi.Int64>());
+  Expect.equals(1, ffi.sizeOf<ffi.Uint8>());
+  Expect.equals(2, ffi.sizeOf<ffi.Uint16>());
+  Expect.equals(4, ffi.sizeOf<ffi.Uint32>());
+  Expect.equals(8, ffi.sizeOf<ffi.Uint64>());
+  Expect.equals(
+      true, 4 == ffi.sizeOf<ffi.IntPtr>() || 8 == ffi.sizeOf<ffi.IntPtr>());
+  Expect.equals(4, ffi.sizeOf<ffi.Float>());
+  Expect.equals(8, ffi.sizeOf<ffi.Double>());
+}
+
+// note: stack overflows at around 15k calls
+void testPointerChain(int length) {
+  void createChain(ffi.Pointer<ffi.IntPtr> head, int length, int value) {
+    if (length == 0) {
+      head.store(value);
+      return;
+    }
+    ffi.Pointer<ffi.IntPtr> next = ffi.allocate();
+    head.store(next.address);
+    createChain(next, length - 1, value);
+  }
+
+  int getChainValue(ffi.Pointer<ffi.IntPtr> head, int length) {
+    if (length == 0) {
+      return head.load();
+    }
+    ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
+    return getChainValue(next, length - 1);
+  }
+
+  void freeChain(ffi.Pointer<ffi.IntPtr> head, int length) {
+    ffi.Pointer<ffi.IntPtr> next = ffi.fromAddress(head.load());
+    head.free();
+    if (length == 0) {
+      return;
+    }
+    freeChain(next, length - 1);
+  }
+
+  ffi.Pointer<ffi.IntPtr> head = ffi.allocate();
+  createChain(head, length, 512);
+  int tailValue = getChainValue(head, length);
+  Expect.equals(512, tailValue);
+  freeChain(head, length);
+}
+
+void testTypeTest() {
+  ffi.Pointer<ffi.Int8> p = ffi.allocate();
+  Expect.isTrue(p is ffi.Pointer);
+  p.free();
+}
+
+void testToString() {
+  ffi.Pointer<ffi.Int16> p = ffi.allocate();
+  Expect.stringEquals(
+      "Pointer<Int16>: address=0x", p.toString().substring(0, 26));
+  p.free();
+}
+
+void testEquality() {
+  ffi.Pointer<ffi.Int8> p = ffi.fromAddress(12345678);
+  ffi.Pointer<ffi.Int8> p2 = ffi.fromAddress(12345678);
+  Expect.equals(p, p2);
+  Expect.equals(p.hashCode, p2.hashCode);
+  ffi.Pointer<ffi.Int16> p3 = p.cast();
+  Expect.equals(p, p3);
+  Expect.equals(p.hashCode, p3.hashCode);
+  Expect.notEquals(p, null);
+  Expect.notEquals(null, p);
+  ffi.Pointer<ffi.Int8> p4 = p.offsetBy(1337);
+  Expect.notEquals(p, p4);
+}
+
+typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
+
+void testAllocateGeneric() {
+  ffi.Pointer<T> generic<T extends ffi.NativeType>() {
+    ffi.Pointer<T> pointer;
+    pointer = ffi.allocate();
+    return pointer;
+  }
+
+  ffi.Pointer p = generic<ffi.Int64>();
+  p.free();
+}
+
+void testAllocateVoid() {
+  Expect.throws(() {
+    ffi.Pointer<ffi.Void> p = ffi.allocate();
+  });
+}
+
+void testAllocateNativeFunction() {
+  Expect.throws(() {
+    ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.allocate();
+  });
+}
+
+void testAllocateNativeType() {
+  Expect.throws(() {
+    ffi.allocate();
+  });
+}
+
+void testSizeOfGeneric() {
+  int generic<T extends ffi.Pointer>() {
+    int size;
+    size = ffi.sizeOf<T>();
+    return size;
+  }
+
+  int size = generic<ffi.Pointer<ffi.Int64>>();
+  Expect.equals(8, size);
+}
+
+void testSizeOfVoid() {
+  Expect.throws(() {
+    ffi.sizeOf<ffi.Void>();
+  });
+}
+
+void testSizeOfNativeFunction() {
+  Expect.throws(() {
+    ffi.sizeOf<ffi.NativeFunction<Int8UnOp>>();
+  });
+}
+
+void testSizeOfNativeType() {
+  Expect.throws(() {
+    ffi.sizeOf();
+  });
+}
+
+void testFreeZeroOut() {
+  // at least one of these pointers should have address != 0 on all platforms
+  ffi.Pointer<ffi.Int8> p1 = ffi.allocate();
+  ffi.Pointer<ffi.Int8> p2 = ffi.allocate();
+  Expect.notEquals(0, p1.address & p2.address);
+  p1.free();
+  p2.free();
+  Expect.equals(0, p1.address);
+  Expect.equals(0, p2.address);
+}
diff --git a/tests/standalone_2/ffi/dynamic_library_test.dart b/tests/standalone_2/ffi/dynamic_library_test.dart
new file mode 100644
index 0000000..1c3c45d
--- /dev/null
+++ b/tests/standalone_2/ffi/dynamic_library_test.dart
@@ -0,0 +1,63 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi dynamic library loading.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import 'package:expect/expect.dart';
+
+void main() {
+  testOpen();
+  testOpenError();
+  testLookup();
+  testLookupError();
+  testToString();
+  testEquality();
+}
+
+void testOpen() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  Expect.notEquals(null, l);
+}
+
+void testOpenError() {
+  Expect.throws(
+      () => ffi.DynamicLibrary.open("doesnotexistforsurelibrary123409876"));
+}
+
+typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
+
+typedef DoubleUnOp = double Function(double);
+
+void testLookup() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  var timesFour = l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>("timesFour");
+  Expect.approxEquals(12.0, timesFour(3));
+}
+
+void testLookupError() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  Expect.throws(() => l.lookupFunction<NativeDoubleUnOp, DoubleUnOp>(
+      "functionnamethatdoesnotexistforsure749237593845"));
+}
+
+void testToString() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  Expect.stringEquals(
+      "DynamicLibrary: handle=0x", l.toString().substring(0, 25));
+}
+
+void testEquality() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  ffi.DynamicLibrary l2 = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  Expect.equals(l, l2);
+  Expect.equals(l.hashCode, l2.hashCode);
+  Expect.notEquals(l, null);
+  Expect.notEquals(null, l);
+  ffi.DynamicLibrary l3 = ffi.DynamicLibrary.open("ffi_test_functions");
+  Expect.notEquals(l, l3);
+}
diff --git a/tests/standalone_2/ffi/enable_ffi_test.dart b/tests/standalone_2/ffi/enable_ffi_test.dart
new file mode 100644
index 0000000..5396312
--- /dev/null
+++ b/tests/standalone_2/ffi/enable_ffi_test.dart
@@ -0,0 +1,20 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing the --enable-ffi=false flag.
+//
+// VMOptions=--enable-ffi=false
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+void main() {
+  ffi.Pointer<ffi.Int64> p = ffi.allocate();
+  p.store(42);
+  Expect.equals(42, p.load<int>());
+  p.free();
+}
diff --git a/tests/standalone_2/ffi/function_callbacks_test.dart b/tests/standalone_2/ffi/function_callbacks_test.dart
new file mode 100644
index 0000000..2f3212b
--- /dev/null
+++ b/tests/standalone_2/ffi/function_callbacks_test.dart
@@ -0,0 +1,90 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi function pointers with callbacks.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+import 'coordinate.dart';
+
+typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+
+typedef CoordinateTrice = Coordinate Function(
+    ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>, Coordinate);
+
+void main() {
+  testFunctionWithFunctionPointer();
+  testNativeFunctionWithFunctionPointer();
+  testFromFunction();
+}
+
+ffi.DynamicLibrary ffiTestFunctions =
+    ffi.DynamicLibrary.open("ffi_test_functions");
+
+/// pass a pointer to a c function as an argument to a c function
+void testFunctionWithFunctionPointer() {
+  ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>>
+      transposeCoordinatePointer =
+      ffiTestFunctions.lookup("TransposeCoordinate");
+
+  ffi.Pointer<ffi.NativeFunction<CoordinateTrice>> p2 =
+      ffiTestFunctions.lookup("CoordinateUnOpTrice");
+  CoordinateTrice coordinateUnOpTrice = p2.asFunction();
+
+  Coordinate c1 = Coordinate(10.0, 20.0, null);
+  c1.next = c1;
+
+  Coordinate result = coordinateUnOpTrice(transposeCoordinatePointer, c1);
+
+  print(result.runtimeType);
+  print(result.x);
+  print(result.y);
+
+  c1.free();
+}
+
+typedef BinaryOp = int Function(int, int);
+
+typedef NativeIntptrBinOp = ffi.IntPtr Function(ffi.IntPtr, ffi.IntPtr);
+
+typedef NativeIntptrBinOpLookup
+    = ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> Function();
+
+void testNativeFunctionWithFunctionPointer() {
+  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOpLookup>> p1 =
+      ffiTestFunctions.lookup("IntptrAdditionClosure");
+  NativeIntptrBinOpLookup intptrAdditionClosure = p1.asFunction();
+
+  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> intptrAdditionPointer =
+      intptrAdditionClosure();
+  BinaryOp intptrAddition = intptrAdditionPointer.asFunction();
+  Expect.equals(37, intptrAddition(10, 27));
+}
+
+int myPlus(int a, int b) => a + b;
+
+typedef NativeApplyTo42And74Type = ffi.IntPtr Function(
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+
+typedef ApplyTo42And74Type = int Function(
+    ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>>);
+
+void testFromFunction() {
+  ffi.Pointer<ffi.NativeFunction<NativeIntptrBinOp>> pointer =
+      ffi.fromFunction(myPlus);
+  Expect.isNotNull(pointer);
+
+  ffi.Pointer<ffi.NativeFunction<NativeApplyTo42And74Type>> p17 =
+      ffiTestFunctions.lookup("ApplyTo42And74");
+  ApplyTo42And74Type applyTo42And74 = p17.asFunction();
+
+  // TODO(dacoharkes): implement this
+
+  // int result = applyTo42And74(pointer);
+  // print(result);
+}
diff --git a/tests/standalone_2/ffi/function_structs_test.dart b/tests/standalone_2/ffi/function_structs_test.dart
new file mode 100644
index 0000000..6f74a90
--- /dev/null
+++ b/tests/standalone_2/ffi/function_structs_test.dart
@@ -0,0 +1,116 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi function pointers with struct
+// arguments.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+import 'coordinate.dart';
+import 'very_large_struct.dart';
+
+typedef NativeCoordinateOp = Coordinate Function(Coordinate);
+
+void main() {
+  testFunctionWithStruct();
+  testFunctionWithStructArray();
+  testFunctionWithVeryLargeStruct();
+}
+
+ffi.DynamicLibrary ffiTestFunctions =
+    ffi.DynamicLibrary.open("ffi_test_functions");
+
+/// pass a struct to a c function and get a struct as return value
+void testFunctionWithStruct() {
+  ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+      ffiTestFunctions.lookup("TransposeCoordinate");
+  NativeCoordinateOp f1 = p1.asFunction();
+
+  Coordinate c1 = Coordinate(10.0, 20.0, null);
+  Coordinate c2 = Coordinate(42.0, 84.0, c1);
+  c1.next = c2;
+
+  Coordinate result = f1(c1);
+
+  Expect.approxEquals(20.0, c1.x);
+  Expect.approxEquals(30.0, c1.y);
+
+  Expect.approxEquals(42.0, result.x);
+  Expect.approxEquals(84.0, result.y);
+
+  c1.free();
+  c2.free();
+}
+
+/// pass an array of structs to a c funtion
+void testFunctionWithStructArray() {
+  ffi.Pointer<ffi.NativeFunction<NativeCoordinateOp>> p1 =
+      ffiTestFunctions.lookup("CoordinateElemAt1");
+  NativeCoordinateOp f1 = p1.asFunction();
+
+  Coordinate c1 = Coordinate.allocate(count: 3);
+  Coordinate c2 = c1.elementAt(1);
+  Coordinate c3 = c1.elementAt(2);
+  c1.x = 10.0;
+  c1.y = 10.0;
+  c1.next = c3;
+  c2.x = 20.0;
+  c2.y = 20.0;
+  c2.next = c1;
+  c3.x = 30.0;
+  c3.y = 30.0;
+  c3.next = c2;
+
+  Coordinate result = f1(c1);
+  Expect.approxEquals(20.0, result.x);
+  Expect.approxEquals(20.0, result.y);
+
+  c1.free();
+}
+
+typedef VeryLargeStructSum = int Function(VeryLargeStruct);
+typedef NativeVeryLargeStructSum = ffi.Int64 Function(VeryLargeStruct);
+
+void testFunctionWithVeryLargeStruct() {
+  ffi.Pointer<ffi.NativeFunction<NativeVeryLargeStructSum>> p1 =
+      ffiTestFunctions.lookup("SumVeryLargeStruct");
+  VeryLargeStructSum f = p1.asFunction();
+
+  VeryLargeStruct vls1 = VeryLargeStruct.allocate(count: 2);
+  VeryLargeStruct vls2 = vls1.elementAt(1);
+  List<VeryLargeStruct> structs = [vls1, vls2];
+  for (VeryLargeStruct struct in structs) {
+    struct.a = 1;
+    struct.b = 2;
+    struct.c = 4;
+    struct.d = 8;
+    struct.e = 16;
+    struct.f = 32;
+    struct.g = 64;
+    struct.h = 128;
+    struct.i = 256;
+    struct.j = 512;
+    struct.k = 1024;
+    struct.smallLastField = 1;
+  }
+  vls1.parent = vls2;
+  vls1.numChidlren = 2;
+  vls1.children = vls1;
+  vls2.parent = vls2;
+  vls2.parent = null;
+  vls2.numChidlren = 0;
+  vls2.children = null;
+
+  int result = f(vls1);
+  Expect.equals(2051, result);
+
+  result = f(vls2);
+  Expect.equals(2048, result);
+
+  vls1.free();
+}
diff --git a/tests/standalone_2/ffi/function_test.dart b/tests/standalone_2/ffi/function_test.dart
new file mode 100644
index 0000000..bed0264
--- /dev/null
+++ b/tests/standalone_2/ffi/function_test.dart
@@ -0,0 +1,284 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi function pointers.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+void main() {
+  testNativeFunctionFromCast();
+  testNativeFunctionFromLookup();
+  test64bitInterpretations();
+  testTruncation();
+  testNativeFunctionDoubles();
+  testNativeFunctionFloats();
+  testNativeFunctionManyArguments1();
+  testNativeFunctionManyArguments2();
+  testNativeFunctionManyArguments3();
+  testNativeFunctionPointer();
+  testNullInt();
+  testNullDouble();
+  testNullManyArgs();
+  testNullPointers();
+  testFloatRounding();
+}
+
+ffi.DynamicLibrary ffiTestFunctions =
+    ffi.DynamicLibrary.open("ffi_test_functions");
+
+typedef NativeBinaryOp = ffi.Int32 Function(ffi.Int32, ffi.Int32);
+typedef UnaryOp = int Function(int);
+typedef BinaryOp = int Function(int, int);
+typedef GenericBinaryOp<T> = int Function(int, T);
+
+void testNativeFunctionFromCast() {
+  ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
+  ffi.Pointer<ffi.NativeFunction<NativeBinaryOp>> p2 = p1.cast();
+  BinaryOp f = p2.asFunction<BinaryOp>();
+  BinaryOp f2 = p2.asFunction<GenericBinaryOp<int>>();
+  p1.free();
+}
+
+typedef NativeQuadOpSigned = ffi.Int64 Function(
+    ffi.Int64, ffi.Int32, ffi.Int16, ffi.Int8);
+typedef QuadOp = int Function(int, int, int, int);
+typedef NativeQuadOpUnsigned = ffi.Uint64 Function(
+    ffi.Uint64, ffi.Uint32, ffi.Uint16, ffi.Uint8);
+
+void testNativeFunctionFromLookup() {
+  BinaryOp sumPlus42 =
+      ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+  Expect.equals(49, sumPlus42(3, 4));
+
+  QuadOp intComputation = ffiTestFunctions
+      .lookupFunction<NativeQuadOpSigned, QuadOp>("IntComputation");
+  Expect.equals(625, intComputation(125, 250, 500, 1000));
+
+  Expect.equals(
+      0x7FFFFFFFFFFFFFFF, intComputation(0, 0, 0, 0x7FFFFFFFFFFFFFFF));
+  Expect.equals(
+      -0x8000000000000000, intComputation(0, 0, 0, -0x8000000000000000));
+}
+
+void test64bitInterpretations() {
+  QuadOp uintComputation = ffiTestFunctions
+      .lookupFunction<NativeQuadOpUnsigned, QuadOp>("UintComputation");
+
+  // 2 ^ 63 - 1
+  Expect.equals(
+      0x7FFFFFFFFFFFFFFF, uintComputation(0, 0, 0, 0x7FFFFFFFFFFFFFFF));
+  // -2 ^ 63 interpreted as 2 ^ 63
+  Expect.equals(
+      -0x8000000000000000, uintComputation(0, 0, 0, -0x8000000000000000));
+  // -1 interpreted as 2 ^ 64 - 1
+  Expect.equals(-1, uintComputation(0, 0, 0, -1));
+}
+
+typedef NativeSenaryOp = ffi.Int64 Function(
+    ffi.Int8, ffi.Int16, ffi.Int32, ffi.Uint8, ffi.Uint16, ffi.Uint32);
+typedef SenaryOp = int Function(int, int, int, int, int, int);
+
+void testTruncation() {
+  SenaryOp sumSmallNumbers = ffiTestFunctions
+      .lookupFunction<NativeSenaryOp, SenaryOp>("SumSmallNumbers");
+
+  // TODO(dacoharkes): implement truncation and sign extension in trampolines
+  // for values smaller than 32 bits.
+  sumSmallNumbers(128, 0, 0, 0, 0, 0);
+  sumSmallNumbers(-129, 0, 0, 0, 0, 0);
+  sumSmallNumbers(0, 0, 0, 256, 0, 0);
+  sumSmallNumbers(0, 0, 0, -1, 0, 0);
+
+  sumSmallNumbers(0, 0x8000, 0, 0, 0, 0);
+  sumSmallNumbers(0, 0xFFFFFFFFFFFF7FFF, 0, 0, 0, 0);
+  sumSmallNumbers(0, 0, 0, 0, 0x10000, 0);
+  sumSmallNumbers(0, 0, 0, 0, -1, 0);
+
+  Expect.equals(0xFFFFFFFF80000000, sumSmallNumbers(0, 0, 0x80000000, 0, 0, 0));
+  Expect.equals(
+      0x000000007FFFFFFF, sumSmallNumbers(0, 0, 0xFFFFFFFF7FFFFFFF, 0, 0, 0));
+  Expect.equals(0, sumSmallNumbers(0, 0, 0, 0, 0, 0x100000000));
+  Expect.equals(0xFFFFFFFF, sumSmallNumbers(0, 0, 0, 0, 0, -1));
+}
+
+typedef NativeDoubleUnaryOp = ffi.Double Function(ffi.Double);
+typedef DoubleUnaryOp = double Function(double);
+
+void testNativeFunctionDoubles() {
+  DoubleUnaryOp times1_337Double = ffiTestFunctions
+      .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+  Expect.approxEquals(2.0 * 1.337, times1_337Double(2.0));
+}
+
+typedef NativeFloatUnaryOp = ffi.Float Function(ffi.Float);
+
+void testNativeFunctionFloats() {
+  DoubleUnaryOp times1_337Float = ffiTestFunctions
+      .lookupFunction<NativeFloatUnaryOp, DoubleUnaryOp>("Times1_337Float");
+  Expect.approxEquals(1337.0, times1_337Float(1000.0));
+}
+
+typedef NativeOctenaryOp = ffi.IntPtr Function(
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr,
+    ffi.IntPtr);
+typedef OctenaryOp = int Function(
+    int, int, int, int, int, int, int, int, int, int);
+
+void testNativeFunctionManyArguments1() {
+  OctenaryOp sumManyInts = ffiTestFunctions
+      .lookupFunction<NativeOctenaryOp, OctenaryOp>("SumManyInts");
+  Expect.equals(55, sumManyInts(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
+}
+
+typedef NativeDoubleOctenaryOp = ffi.Double Function(
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double,
+    ffi.Double);
+typedef DoubleOctenaryOp = double Function(double, double, double, double,
+    double, double, double, double, double, double);
+
+void testNativeFunctionManyArguments2() {
+  DoubleOctenaryOp sumManyDoubles =
+      ffiTestFunctions.lookupFunction<NativeDoubleOctenaryOp, DoubleOctenaryOp>(
+          "SumManyDoubles");
+  Expect.approxEquals(
+      55.0, sumManyDoubles(1.0, 2.0, 3.0, 4.0, 5.0, 6.0, 7.0, 8.0, 9.0, 10.0));
+}
+
+typedef NativeVigesimalOp = ffi.Double Function(
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double,
+    ffi.IntPtr,
+    ffi.Float,
+    ffi.IntPtr,
+    ffi.Double);
+typedef VigesimalOp = double Function(
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double,
+    int,
+    double);
+
+void testNativeFunctionManyArguments3() {
+  VigesimalOp sumManyNumbers = ffiTestFunctions
+      .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+  Expect.approxEquals(
+      210.0,
+      sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0, 11, 12.0, 13,
+          14.0, 15, 16.0, 17, 18.0, 19, 20.0));
+}
+
+typedef Int64PointerUnOp = ffi.Pointer<ffi.Int64> Function(
+    ffi.Pointer<ffi.Int64>);
+
+void testNativeFunctionPointer() {
+  Int64PointerUnOp assign1337Index1 = ffiTestFunctions
+      .lookupFunction<Int64PointerUnOp, Int64PointerUnOp>("Assign1337Index1");
+  ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
+  p2.store(42);
+  p2.elementAt(1).store(1000);
+  ffi.Pointer<ffi.Int64> result = assign1337Index1(p2);
+  Expect.equals(1337, result.load<int>());
+  Expect.equals(1337, p2.elementAt(1).load<int>());
+  Expect.equals(p2.elementAt(1).address, result.address);
+  p2.free();
+}
+
+void testNullInt() {
+  BinaryOp sumPlus42 =
+      ffiTestFunctions.lookupFunction<NativeBinaryOp, BinaryOp>("SumPlus42");
+
+  Expect.throws(() => sumPlus42(43, null));
+}
+
+void testNullDouble() {
+  DoubleUnaryOp times1_337Double = ffiTestFunctions
+      .lookupFunction<NativeDoubleUnaryOp, DoubleUnaryOp>("Times1_337Double");
+  Expect.throws(() => times1_337Double(null));
+}
+
+void testNullManyArgs() {
+  VigesimalOp sumManyNumbers = ffiTestFunctions
+      .lookupFunction<NativeVigesimalOp, VigesimalOp>("SumManyNumbers");
+  Expect.throws(() => sumManyNumbers(1, 2.0, 3, 4.0, 5, 6.0, 7, 8.0, 9, 10.0,
+      11, 12.0, 13, 14.0, 15, 16.0, 17, 18.0, null, 20.0));
+}
+
+void testNullPointers() {
+  Int64PointerUnOp nullableInt64ElemAt1 =
+      ffiTestFunctions.lookupFunction<Int64PointerUnOp, Int64PointerUnOp>(
+          "NullableInt64ElemAt1");
+
+  ffi.Pointer<ffi.Int64> result = nullableInt64ElemAt1(null);
+  Expect.isNull(result);
+
+  ffi.Pointer<ffi.Int64> p2 = ffi.allocate(count: 2);
+  result = nullableInt64ElemAt1(p2);
+  Expect.isNotNull(result);
+  p2.free();
+}
+
+typedef NativeFloatPointerToBool = ffi.Uint8 Function(ffi.Pointer<ffi.Float>);
+typedef FloatPointerToBool = int Function(ffi.Pointer<ffi.Float>);
+
+void testFloatRounding() {
+  FloatPointerToBool isRoughly1337 = ffiTestFunctions.lookupFunction<
+      NativeFloatPointerToBool, FloatPointerToBool>("IsRoughly1337");
+
+  ffi.Pointer<ffi.Float> p2 = ffi.allocate();
+  p2.store(1337.0);
+
+  int result = isRoughly1337(p2);
+  Expect.equals(1, result);
+
+  p2.free();
+}
diff --git a/tests/standalone_2/ffi/static_checks_test.dart b/tests/standalone_2/ffi/static_checks_test.dart
new file mode 100644
index 0000000..422fc6f
--- /dev/null
+++ b/tests/standalone_2/ffi/static_checks_test.dart
@@ -0,0 +1,365 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi extra checks
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+void main() {
+  testGetGeneric();
+  testGetGeneric2();
+  testGetVoid();
+  testGetNativeFunction();
+  testGetNativeType();
+  testGetTypeMismatch();
+  testSetGeneric();
+  testSetGeneric2();
+  testSetVoid();
+  testSetNativeFunction();
+  testSetNativeType();
+  testSetTypeMismatch();
+  testAsFunctionGeneric();
+  testAsFunctionGeneric2();
+  testAsFunctionWrongNativeFunctionSignature();
+  testAsFunctionTypeMismatch();
+  testFromFunctionGeneric();
+  testFromFunctionGeneric2();
+  testFromFunctionWrongNativeFunctionSignature();
+  testFromFunctionTypeMismatch();
+  testFromFunctionClosure();
+  testFromFunctionTearOff();
+  testLookupFunctionGeneric();
+  testLookupFunctionGeneric2();
+  testLookupFunctionWrongNativeFunctionSignature();
+  testLookupFunctionTypeMismatch();
+  testNativeFunctionSignatureInvalidReturn();
+  testNativeFunctionSignatureInvalidParam();
+  testNativeFunctionSignatureInvalidOptionalNamed();
+  testNativeFunctionSignatureInvalidOptionalPositional();
+}
+
+typedef Int8UnOp = ffi.Int8 Function(ffi.Int8);
+typedef IntUnOp = int Function(int);
+
+void testGetGeneric() {
+  int generic(ffi.Pointer p) {
+    int result;
+    result = p.load<int>(); //# 20: compile-time error
+    return result;
+  }
+
+  ffi.Pointer<ffi.Int8> p = ffi.allocate();
+  p.store(123);
+  ffi.Pointer loseType = p;
+  generic(loseType);
+  p.free();
+}
+
+void testGetGeneric2() {
+  T generic<T extends Object>() {
+    ffi.Pointer<ffi.Int8> p = ffi.allocate();
+    p.store(123);
+    T result;
+    result = p.load<T>(); //# 21: compile-time error
+    p.free();
+    return result;
+  }
+
+  generic<int>();
+}
+
+void testGetVoid() {
+  ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
+  ffi.Pointer<ffi.Void> p2 = p1.cast();
+
+  p2.load<int>(); //# 22: compile-time error
+
+  p1.free();
+}
+
+void testGetNativeFunction() {
+  ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.fromAddress(1337);
+  IntUnOp f = p.load(); //# 23: compile-time error
+}
+
+void testGetNativeType() {
+  // Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
+}
+
+void testGetTypeMismatch() {
+  ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
+  ffi.Pointer<ffi.Int16> typedNull = null;
+  p.store(typedNull);
+
+  // this fails to compile due to type mismatch
+  ffi.Pointer<ffi.Int8> p2 = p.load(); //# 25: compile-time error
+
+  p.free();
+}
+
+void testSetGeneric() {
+  void generic(ffi.Pointer p) {
+    p.store(123); //# 26: compile-time error
+  }
+
+  ffi.Pointer<ffi.Int8> p = ffi.allocate();
+  p.store(123);
+  ffi.Pointer loseType = p;
+  generic(loseType);
+  p.free();
+}
+
+void testSetGeneric2() {
+  void generic<T extends Object>(T arg) {
+    ffi.Pointer<ffi.Int8> p = ffi.allocate();
+    p.store(arg); //# 27: compile-time error
+    p.free();
+  }
+
+  generic<int>(123);
+}
+
+void testSetVoid() {
+  ffi.Pointer<ffi.IntPtr> p1 = ffi.allocate();
+  ffi.Pointer<ffi.Void> p2 = p1.cast();
+
+  p2.store(1234); //# 28: compile-time error
+
+  p1.free();
+}
+
+void testSetNativeFunction() {
+  ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.fromAddress(1337);
+  IntUnOp f = (a) => a + 1;
+  p.store(f); //# 29: compile-time error
+}
+
+void testSetNativeType() {
+  // Is it possible to obtain a ffi.Pointer<ffi.NativeType> at all?
+}
+
+void testSetTypeMismatch() {
+  // the pointer to pointer types must match up
+  ffi.Pointer<ffi.Int8> pHelper = ffi.allocate();
+  pHelper.store(123);
+
+  ffi.Pointer<ffi.Pointer<ffi.Int16>> p = ffi.allocate();
+
+  // this fails to compile due to type mismatch
+  p.store(pHelper); //# 40: compile-time error
+
+  pHelper.free();
+  p.free();
+}
+
+void testAsFunctionGeneric() {
+  T generic<T extends Function>() {
+    ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.fromAddress(1337);
+    Function f;
+    f = p.asFunction<T>(); //# 11: compile-time error
+    return f;
+  }
+
+  generic<IntUnOp>();
+}
+
+void testAsFunctionGeneric2() {
+  generic(ffi.Pointer<ffi.NativeFunction> p) {
+    Function f;
+    f = p.asFunction<IntUnOp>(); //# 12: compile-time error
+    return f;
+  }
+
+  ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.fromAddress(1337);
+  generic(p);
+}
+
+void testAsFunctionWrongNativeFunctionSignature() {
+  ffi.Pointer<ffi.NativeFunction<IntUnOp>> p;
+  Function f = p.asFunction<IntUnOp>(); //# 13: compile-time error
+}
+
+typedef IntBinOp = int Function(int, int);
+
+void testAsFunctionTypeMismatch() {
+  ffi.Pointer<ffi.NativeFunction<Int8UnOp>> p = ffi.fromAddress(1337);
+  IntBinOp f = p.asFunction(); //# 14: compile-time error
+}
+
+typedef NativeDoubleUnOp = ffi.Double Function(ffi.Double);
+typedef DoubleUnOp = double Function(double);
+
+double myTimesThree(double d) => d * 3;
+
+int myTimesFour(int i) => i * 4;
+
+void testFromFunctionGeneric() {
+  ffi.Pointer<ffi.NativeFunction> generic<T extends Function>(T f) {
+    ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> result;
+    result = ffi.fromFunction(f); //# 70: compile-time error
+    return result;
+  }
+
+  generic(myTimesThree);
+}
+
+void testFromFunctionGeneric2() {
+  ffi.Pointer<ffi.NativeFunction<T>> generic<T extends Function>() {
+    ffi.Pointer<ffi.NativeFunction<T>> result;
+    result = ffi.fromFunction(myTimesThree); //# 71: compile-time error
+    return result;
+  }
+
+  generic<NativeDoubleUnOp>();
+}
+
+void testFromFunctionWrongNativeFunctionSignature() {
+  ffi.fromFunction<IntUnOp>(myTimesFour); //# 72: compile-time error
+}
+
+void testFromFunctionTypeMismatch() {
+  ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
+  p = ffi.fromFunction(myTimesFour); //# 73: compile-time error
+}
+
+void testFromFunctionClosure() {
+  DoubleUnOp someClosure = (double z) => z / 27.0;
+  ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
+  p = ffi.fromFunction(someClosure); //# 74: compile-time error
+}
+
+class X {
+  double tearoff(double d) => d / 27.0;
+}
+
+DoubleUnOp fld = null;
+
+void testFromFunctionTearOff() {
+  fld = X().tearoff;
+  ffi.Pointer<ffi.NativeFunction<NativeDoubleUnOp>> p;
+  p = ffi.fromFunction(fld); //# 75: compile-time error
+}
+
+void testLookupFunctionGeneric() {
+  Function generic<T extends Function>() {
+    ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+    Function result;
+    result = l.lookupFunction<T, DoubleUnOp>("cos"); //# 15: compile-time error
+    return result;
+  }
+
+  generic<NativeDoubleUnOp>();
+}
+
+void testLookupFunctionGeneric2() {
+  Function generic<T extends Function>() {
+    ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+    Function result;
+    result = //# 16: compile-time error
+        l.lookupFunction<NativeDoubleUnOp, T>("cos"); //# 16: compile-time error
+    return result;
+  }
+
+  generic<DoubleUnOp>();
+}
+
+void testLookupFunctionWrongNativeFunctionSignature() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  l.lookupFunction<IntUnOp, IntUnOp>("cos"); //# 17: compile-time error
+}
+
+void testLookupFunctionTypeMismatch() {
+  ffi.DynamicLibrary l = ffi.DynamicLibrary.open("ffi_test_dynamic_library");
+  l.lookupFunction<NativeDoubleUnOp, IntUnOp>("cos"); //# 18: compile-time error
+}
+
+// TODO(dacoharkes): make the next 4 test compile errors
+typedef Invalid1 = int Function(ffi.Int8);
+typedef Invalid2 = ffi.Int8 Function(int);
+typedef Invalid3 = ffi.Int8 Function({ffi.Int8 named});
+typedef Invalid4 = ffi.Int8 Function([ffi.Int8 positional]);
+
+void testNativeFunctionSignatureInvalidReturn() {
+  // ffi.Pointer<ffi.NativeFunction<Invalid1>> p = ffi.fromAddress(999);
+}
+
+void testNativeFunctionSignatureInvalidParam() {
+  // ffi.Pointer<ffi.NativeFunction<Invalid2>> p = ffi.fromAddress(999);
+}
+
+void testNativeFunctionSignatureInvalidOptionalNamed() {
+  // ffi.Pointer<ffi.NativeFunction<Invalid3>> p = ffi.fromAddress(999);
+}
+
+void testNativeFunctionSignatureInvalidOptionalPositional() {
+  // ffi.Pointer<ffi.NativeFunction<Invalid4>> p = ffi.fromAddress(999);
+}
+
+// error on missing field annotation
+@ffi.struct
+class TestStruct extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  double x;
+
+  double y; //# 50: compile-time error
+}
+
+// error on missing struct annotation
+class TestStruct2 extends ffi.Pointer<ffi.Void> {
+  @ffi.Double() //# 51: compile-time error
+  double x; //# 51: compile-time error
+}
+
+// error on missing annotation on subtype
+@ffi.struct
+class TestStruct3 extends TestStruct {
+  double z; //# 52: compile-time error
+}
+
+// error on double annotation
+@ffi.struct
+class TestStruct4 extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  @ffi.Double() //# 53: compile-time error
+  double z;
+}
+
+// error on annotation not matching up
+@ffi.struct
+class TestStruct5 extends ffi.Pointer<ffi.Void> {
+  @ffi.Int64() //# 54: compile-time error
+  double z; //# 54: compile-time error
+}
+
+// error on annotation not matching up
+@ffi.struct
+class TestStruct6 extends ffi.Pointer<ffi.Void> {
+  @ffi.Void() //# 55: compile-time error
+  double z; //# 55: compile-time error
+}
+
+// error on annotation not matching up
+@ffi.struct
+class TestStruct7 extends ffi.Pointer<ffi.Void> {
+  @ffi.NativeType() //# 56: compile-time error
+  double z; //# 56: compile-time error
+}
+
+// error on field initializer on field
+@ffi.struct
+class TestStruct8 extends ffi.Pointer<ffi.Void> {
+  @ffi.Double() //# 57: compile-time error
+  double z = 10.0; //# 57: compile-time error
+}
+
+// error on field initializer in constructor
+@ffi.struct
+class TestStruct9 extends ffi.Pointer<ffi.Void> {
+  @ffi.Double()
+  double z;
+
+  TestStruct9() : z = 0.0 {} //# 58: compile-time error
+}
diff --git a/tests/standalone_2/ffi/structs_test.dart b/tests/standalone_2/ffi/structs_test.dart
new file mode 100644
index 0000000..cbb2eab
--- /dev/null
+++ b/tests/standalone_2/ffi/structs_test.dart
@@ -0,0 +1,136 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi struct pointers.
+
+library FfiTest;
+
+import 'dart:ffi' as ffi;
+
+import "package:expect/expect.dart";
+
+import 'coordinate_bare.dart' as bare;
+import 'coordinate_manual.dart' as manual;
+import 'coordinate.dart';
+
+void main() {
+  testStructAllocate();
+  testStructFromAddress();
+  testStructWithNulls();
+  testBareStruct();
+  testManualStruct();
+  testTypeTest();
+}
+
+/// allocates each coordinate separately in c memory
+void testStructAllocate() {
+  Coordinate c1 = Coordinate(10.0, 10.0, null);
+  Coordinate c2 = Coordinate(20.0, 20.0, c1);
+  Coordinate c3 = Coordinate(30.0, 30.0, c2);
+  c1.next = c3;
+
+  Coordinate currentCoordinate = c1;
+  Expect.equals(10.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(30.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(20.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(10.0, currentCoordinate.x);
+
+  c1.free();
+  c2.free();
+  c3.free();
+}
+
+/// allocates coordinates consecutively in c memory
+void testStructFromAddress() {
+  Coordinate c1 = Coordinate.allocate(count: 3);
+  Coordinate c2 = c1.elementAt(1);
+  Coordinate c3 = c1.elementAt(2);
+  c1.x = 10.0;
+  c1.y = 10.0;
+  c1.next = c3;
+  c2.x = 20.0;
+  c2.y = 20.0;
+  c2.next = c1;
+  c3.x = 30.0;
+  c3.y = 30.0;
+  c3.next = c2;
+
+  Coordinate currentCoordinate = c1;
+  Expect.equals(10.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(30.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(20.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(10.0, currentCoordinate.x);
+
+  c1.free();
+}
+
+void testStructWithNulls() {
+  Coordinate coordinate = Coordinate(10.0, 10.0, null);
+  Expect.isNull(coordinate.next);
+  coordinate.next = coordinate;
+  Expect.isNotNull(coordinate.next);
+  coordinate.next = null;
+  Expect.isNull(coordinate.next);
+  coordinate.free();
+}
+
+void testBareStruct() {
+  int structSize = ffi.sizeOf<ffi.Double>() * 2 + ffi.sizeOf<ffi.IntPtr>();
+  bare.Coordinate c1 = ffi.allocate<ffi.Uint8>(count: structSize * 3).cast();
+  bare.Coordinate c2 = c1.offsetBy(structSize).cast();
+  bare.Coordinate c3 = c1.offsetBy(structSize * 2).cast();
+  c1.x = 10.0;
+  c1.y = 10.0;
+  c1.next = c3;
+  c2.x = 20.0;
+  c2.y = 20.0;
+  c2.next = c1;
+  c3.x = 30.0;
+  c3.y = 30.0;
+  c3.next = c2;
+
+  bare.Coordinate currentCoordinate = c1;
+  Expect.equals(10.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(30.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(20.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(10.0, currentCoordinate.x);
+
+  c1.free();
+}
+
+void testManualStruct() {
+  manual.Coordinate c1 = manual.Coordinate(10.0, 10.0, null);
+  manual.Coordinate c2 = manual.Coordinate(20.0, 20.0, c1);
+  manual.Coordinate c3 = manual.Coordinate(30.0, 30.0, c2);
+  c1.next = c3;
+
+  manual.Coordinate currentCoordinate = c1;
+  Expect.equals(10.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(30.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(20.0, currentCoordinate.x);
+  currentCoordinate = currentCoordinate.next;
+  Expect.equals(10.0, currentCoordinate.x);
+
+  c1.free();
+  c2.free();
+  c3.free();
+}
+
+void testTypeTest() {
+  Coordinate c = Coordinate(10, 10, null);
+  Expect.isTrue(c is ffi.Pointer);
+  Expect.isTrue(c is ffi.Pointer<ffi.Void>);
+  c.free();
+}
diff --git a/tests/standalone_2/ffi/subtype_test.dart b/tests/standalone_2/ffi/subtype_test.dart
new file mode 100644
index 0000000..fd04b50
--- /dev/null
+++ b/tests/standalone_2/ffi/subtype_test.dart
@@ -0,0 +1,19 @@
+// Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+// for details. All rights reserved. Use of this source code is governed by a
+// BSD-style license that can be found in the LICENSE file.
+//
+// Dart test program for testing dart:ffi Pointer subtypes.
+
+library FfiTest;
+
+import "package:expect/expect.dart";
+
+import 'cstring.dart';
+
+void main() {
+  CString cs = CString.toUtf8("hello world!");
+
+  Expect.equals("hello world!", cs.fromUtf8());
+
+  cs.free();
+}
diff --git a/tests/standalone_2/ffi/very_large_struct.dart b/tests/standalone_2/ffi/very_large_struct.dart
new file mode 100644
index 0000000..283cb57
--- /dev/null
+++ b/tests/standalone_2/ffi/very_large_struct.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.
+
+library FfiTestCoordinateBare;
+
+import 'dart:ffi' as ffi;
+
+/// Large sample struct for dart:ffi library.
+@ffi.struct
+class VeryLargeStruct extends ffi.Pointer<ffi.Void> {
+  @ffi.Int8()
+  int a;
+
+  @ffi.Int16()
+  int b;
+
+  @ffi.Int32()
+  int c;
+
+  @ffi.Int64()
+  int d;
+
+  @ffi.Uint8()
+  int e;
+
+  @ffi.Uint16()
+  int f;
+
+  @ffi.Uint32()
+  int g;
+
+  @ffi.Uint64()
+  int h;
+
+  @ffi.IntPtr()
+  int i;
+
+  @ffi.Float()
+  double j;
+
+  @ffi.Double()
+  double k;
+
+  @ffi.Pointer()
+  VeryLargeStruct parent;
+
+  @ffi.IntPtr()
+  int numChidlren;
+
+  @ffi.Pointer()
+  VeryLargeStruct children;
+
+  @ffi.Int8()
+  int smallLastField;
+
+  // generated by @ffi.struct annotation
+  external static int sizeOf();
+
+  VeryLargeStruct offsetBy(int offsetInBytes) =>
+      super.offsetBy(offsetInBytes).cast();
+
+  VeryLargeStruct elementAt(int index) => offsetBy(sizeOf() * index);
+
+  static VeryLargeStruct allocate({int count: 1}) =>
+      ffi.allocate<ffi.Uint8>(count: count * sizeOf()).cast();
+}
diff --git a/tests/standalone_2/standalone_2_kernel.status b/tests/standalone_2/standalone_2_kernel.status
index 6cd14cb..7b2cfd6 100644
--- a/tests/standalone_2/standalone_2_kernel.status
+++ b/tests/standalone_2/standalone_2_kernel.status
@@ -34,6 +34,10 @@
 io/web_socket_protocol_processor_test: CompileTimeError
 io/zlib_test: RuntimeError
 
+[ $compiler == dartkb ]
+io/platform_resolved_executable_test/03: RuntimeError
+io/platform_resolved_executable_test/04: RuntimeError
+
 [ $compiler == dartkp ]
 io/test_runner_test: SkipByDesign # Is not relevant for AOT.
 
@@ -151,8 +155,6 @@
 
 [ $runtime == vm && $strong && ($compiler == dartk || $compiler == dartkb) ]
 io/http_client_request_test: Pass, Timeout
-io/platform_resolved_executable_test/03: Pass, RuntimeError
-io/platform_resolved_executable_test/04: Pass, RuntimeError
 io/secure_builtin_roots_test: Pass, Timeout
 io/socket_finalizer_test: Pass, Timeout
 no_support_debugger_test: Skip # kernel-service snapshot not compatible with flag disabled
diff --git a/tests/standalone_2/standalone_2_vm.status b/tests/standalone_2/standalone_2_vm.status
index 1880efc..c59b66f 100644
--- a/tests/standalone_2/standalone_2_vm.status
+++ b/tests/standalone_2/standalone_2_vm.status
@@ -6,6 +6,9 @@
 link_natives_lazily_test: SkipByDesign # Not supported.
 no_allow_absolute_addresses_test: SkipByDesign # Not supported.
 
+[ $builder_tag == asan ]
+ffi/data_not_asan_test: Skip # this test tries to allocate too much memory on purpose
+
 [ $compiler == app_jit ]
 full_coverage_test: Skip # Platform.executable
 io/code_collection_test: Skip # Platform.executable
@@ -22,7 +25,18 @@
 io/test_runner_test: RuntimeError # Issue 33168
 regress_26031_test: Skip # Platform.resolvedExecutable
 
+[ $compiler == app_jitk ]
+ffi/dynamic_library_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_callbacks_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_structs_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+ffi/function_test: Skip # https://github.com/dart-lang/sdk/issues/35934
+
+[ $runtime == dart_precompiled ]
+ffi: RuntimeError # https://github.com/dart-lang/sdk/issues/35765
+ffi/static_checks_test: Skip # https://github.com/dart-lang/sdk/issues/35765
+
 [ $runtime == vm ]
+ffi/enable_ffi_test: Fail # test designed to fail: --enable-ffi=false with import dart:ffi
 io/test_runner_test: Skip # Spawns a process which runs in Dart2 mode.
 
 [ $system == android ]
@@ -67,18 +81,21 @@
 [ $arch == arm && $mode == release && $runtime == dart_precompiled && $system == android ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 28426
 
-[ $arch == ia32 && $builder_tag == asan && $mode == release && $runtime == vm && $system == linux ]
-io/socket_close_test: Pass, Timeout # Issue 28502: timeout.
-
 [ $arch == simdbc64 && $mode == debug && $checked ]
 io/web_socket_test: Pass, RuntimeError # Issue 26814.
 
 [ $arch == x64 && $compiler == dartkb && $runtime == vm && $system == linux ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
+[ $arch == x64 && $mode == debug && $system == linux && $hot_reload ]
+ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35933
+
 [ $compiler != dart2analyzer && $system == windows ]
 io/platform_resolved_executable_test/06: RuntimeError # Issue 23641
 
+[ $compiler == dartkb && $mode == debug ]
+ffi/subtype_test: Skip # https://github.com/dart-lang/sdk/issues/35935
+
 [ $mode == release && $runtime == vm && $system == linux && ($arch == simdbc64 || $arch == x64) ]
 io/http_bind_test: Pass, Timeout # Issue 35192
 
@@ -88,11 +105,13 @@
 
 [ $mode == release && $runtime == vm && $system == windows ]
 io/http_server_close_response_after_error_test: Pass, Timeout # Issue 28370: timeout.
-io/regress_7191_test: Pass, Timeout # Issue 28374: timeout.
 
 [ $runtime == dart_precompiled && $system == linux && ($arch == simarm || $arch == simarm64 || $arch == x64) ]
 io/stdout_stderr_non_blocking_test: Pass, Timeout # Issue 35192
 
+[ $runtime != dart_precompiled && $runtime != vm ]
+ffi: SkipByDesign # ffi is only supported on vm
+
 [ $runtime == vm && !$checked && !$strong ]
 io/file_constructor_test: RuntimeError
 
@@ -115,3 +134,6 @@
 full_coverage_test: Skip # TODO(vegorov) SIMDBC interpreter doesn't support coverage yet.
 link_natives_lazily_test: SkipByDesign # SIMDBC interpreter doesn't support lazy linking of natives.
 no_lazy_dispatchers_test: SkipByDesign # SIMDBC interpreter doesn't support --no_lazy_dispatchers
+
+[ $arch != x64 || $system != linux && $system != macos ]
+ffi: Skip # ffi not yet supported on other systems than linux/macos 64
diff --git a/tools/3xhead_flutter_hooks.sh b/tools/3xhead_flutter_hooks.sh
index a075705..cb4219a 100755
--- a/tools/3xhead_flutter_hooks.sh
+++ b/tools/3xhead_flutter_hooks.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #
 # Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
@@ -12,11 +12,14 @@
 # (run inside the root of a flutter engine checkout)
 
 set -e
-if [ ! -e src/third_party/dart ]; then
-  echo "$0: error: "\
-       "This script must be run from the root of a flutter engine checkout" >&2
-  exit 1
-fi
+
+DIR=$(dirname -- "$(which -- "$0")")
+. $DIR/patches/utils.sh
+
+ensure_in_checkout_root
+
+# Apply patches to the Flutter Framework if needed.
+src/third_party/dart/tools/patches/flutter-flutter/apply.sh
 
 # Apply patches to the Flutter Engine if needed.
 src/third_party/dart/tools/patches/flutter-engine/apply.sh
diff --git a/tools/VERSION b/tools/VERSION
index e753a82..42623de1 100644
--- a/tools/VERSION
+++ b/tools/VERSION
@@ -25,7 +25,7 @@
 #
 CHANNEL dev
 MAJOR 2
-MINOR 1
-PATCH 2
-PRERELEASE 0
+MINOR 2
+PATCH 0
+PRERELEASE 2
 PRERELEASE_PATCH 0
diff --git a/tools/bots/flutter/analyze_flutter.sh b/tools/bots/flutter/analyze_flutter.sh
index 0685c0e..de71818 100755
--- a/tools/bots/flutter/analyze_flutter.sh
+++ b/tools/bots/flutter/analyze_flutter.sh
@@ -7,7 +7,7 @@
 set -e
 
 checkout=$(pwd)
-dart=$checkout/tools/sdks/dart-sdk/bin/dart
+dart=$checkout/out/ReleaseX64/dart-sdk/bin/dart
 sdk=$checkout/out/ReleaseX64/dart-sdk
 tmpdir=$(mktemp -d)
 cleanup() {
@@ -30,4 +30,4 @@
 
 bin/flutter update-packages
 
-$dart dev/bots/analyze.dart --dart-sdk $sdk
+$dart --enable-asserts dev/bots/analyze.dart --dart-sdk $sdk
diff --git a/tools/bots/test_matrix.json b/tools/bots/test_matrix.json
index 174149e..863c5af 100644
--- a/tools/bots/test_matrix.json
+++ b/tools/bots/test_matrix.json
@@ -17,6 +17,7 @@
       ".packages",
       "out/ReleaseIA32/dart-sdk/",
       "out/ReleaseX64/dart-sdk/",
+      "out/ReleaseX64/gen/utils/dartdevc/",
       "pkg/",
       "runtime/tests/",
       "samples-dev/",
@@ -41,9 +42,11 @@
       "third_party/observatory_pub_packages/packages/web_components/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
+      "third_party/requirejs/",
       "tools/",
       "xcodebuild/ReleaseIA32/dart-sdk/",
-      "xcodebuild/ReleaseX64/dart-sdk/"
+      "xcodebuild/ReleaseX64/dart-sdk/",
+      "xcodebuild/ReleaseX64/gen/utils/dartdevc/"
     ],
     "dart2js_hostasserts": [
       ".packages",
@@ -76,6 +79,7 @@
       "third_party/d8/",
       "third_party/pkg/",
       "third_party/pkg_tested/",
+      "third_party/requirejs/",
       "tools/",
       "xcodebuild/ReleaseIA32/dart",
       "xcodebuild/ReleaseIA32/dart2js_platform.dill",
@@ -764,6 +768,24 @@
           "arguments": ["dart2js_bot", "dartdevc_test"]
         },
         {
+          "name": "ddc co19_2 tests",
+          "arguments": [
+            "-ndartdevc-checked-${system}-release-chrome",
+            "co19_2"
+          ],
+          "shards": 6,
+          "fileset": "dart2js"
+        },
+        {
+          "name": "ddk co19_2 tests",
+          "arguments": [
+            "-ndartdevk-checked-${system}-release-chrome",
+            "co19_2"
+          ],
+          "shards": 6,
+          "fileset": "dart2js"
+        },
+        {
           "name": "ddc tests",
           "arguments": [
             "-ndartdevc-checked-${system}-release-chrome",
@@ -1266,10 +1288,9 @@
         "analyzer-linux-release",
         "analyzer-mac-release",
         "analyzer-win-release",
-        "analyzer-linux-release-analyzer",
-        "analyzer-linux-release-analyzer-new",
-        "analyzer-mac-release-analyzer",
-        "analyzer-win-release-analyzer"
+        "analyzer-linux-release-analyzer-stable",
+        "analyzer-mac-release-analyzer-stable",
+        "analyzer-win-release-analyzer-stable"
       ],
       "meta": {
         "description": "This configuration is used by the analyzer builders."
@@ -1336,7 +1357,7 @@
     {
       "builders": [
         "analyzer-analysis-server-linux",
-        "analyzer-analysis-server-linux-analyzer"
+        "analyzer-analysis-server-linux-analyzer-stable"
       ],
       "meta": {
         "description": "Analyze analyzer related packages."
@@ -1609,7 +1630,7 @@
     {
       "builders": [
         "flutter-analyze",
-        "flutter-analyze-analyzer"
+        "flutter-analyze-analyzer-stable"
       ],
       "meta": {
         "description": "This configuration is used for analyzing flutter."
diff --git a/tools/patches/flutter-engine/apply.sh b/tools/patches/flutter-engine/apply.sh
index b449af1..d1105a5 100755
--- a/tools/patches/flutter-engine/apply.sh
+++ b/tools/patches/flutter-engine/apply.sh
@@ -19,13 +19,13 @@
 # (run inside the root of a flutter engine checkout)
 
 set -e
-if [ ! -e src/third_party/dart ]; then
-  echo "$0: error: "\
-       "This script must be run from the root of a flutter engine checkout" >&2
-  exit 1
-fi
-pinned_dart_sdk=$(grep -E "'dart_revision':.*" src/flutter/DEPS |
-                  sed -E "s/.*'([^']*)',/\1/")
+
+DIR=$(dirname -- "$(which -- "$0")")
+. $DIR/../utils.sh
+
+ensure_in_checkout_root
+
+pinned_dart_sdk=$(get_pinned_dart_version)
 need_runhooks=false
 patch=src/third_party/dart/tools/patches/flutter-engine/${pinned_dart_sdk}.flutter.patch
 if [ -e "$patch" ]; then
diff --git a/tools/patches/flutter-engine/create.sh b/tools/patches/flutter-engine/create.sh
index d9bc6fd..15dad92 100755
--- a/tools/patches/flutter-engine/create.sh
+++ b/tools/patches/flutter-engine/create.sh
@@ -1,4 +1,4 @@
-#!/bin/sh
+#!/usr/bin/env bash
 #
 # Copyright (c) 2018, the Dart project authors.  Please see the AUTHORS file
 # for details. All rights reserved. Use of this source code is governed by a
@@ -15,13 +15,13 @@
 # (run inside the root of a flutter engine checkout)
 
 set -e
-if [ ! -e src/third_party/dart ]; then
-  echo "$0: error: "\
-       "This script must be run from the root of a flutter engine checkout" >&2
-  exit 1
-fi
-pinned_dart_sdk=$(grep -E "'dart_revision':.*" src/flutter/DEPS |
-                  sed -E "s/.*'([^']*)',/\1/")
+
+DIR=$(dirname -- "$(which -- "$0")")
+. $DIR/../utils.sh
+
+ensure_in_checkout_root
+
+pinned_dart_sdk=$(get_pinned_dart_version)
 patch=src/third_party/dart/tools/patches/flutter-engine/$pinned_dart_sdk.patch
 rm -f src/third_party/dart/tools/patches/flutter-engine/*.patch
 (cd src/flutter && git diff) > $patch
diff --git a/tools/patches/flutter-engine/ecd7a88606a4bf896316f56f1b0db6f5469c2623.patch b/tools/patches/flutter-engine/ecd7a88606a4bf896316f56f1b0db6f5469c2623.patch
new file mode 100644
index 0000000..60a8135
--- /dev/null
+++ b/tools/patches/flutter-engine/ecd7a88606a4bf896316f56f1b0db6f5469c2623.patch
@@ -0,0 +1,37 @@
+diff --git a/lib/snapshot/libraries.json b/lib/snapshot/libraries.json
+index a59ae6c66..99ef4cd77 100644
+--- a/lib/snapshot/libraries.json
++++ b/lib/snapshot/libraries.json
+@@ -57,6 +57,14 @@
+         ],
+         "uri": "../../../third_party/dart/sdk/lib/collection/collection.dart"
+       },
++      "ffi": {
++        "patches": [
++          "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart",
++          "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart",
++          "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++        ],
++        "uri": "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
++      },
+       "typed_data": {
+         "patches": "../../../third_party/dart/runtime/lib/typed_data_patch.dart",
+         "uri": "../../../third_party/dart/sdk/lib/typed_data/typed_data.dart"
+diff --git a/lib/snapshot/libraries.yaml b/lib/snapshot/libraries.yaml
+index 26c327705..c4244eaff 100644
+--- a/lib/snapshot/libraries.yaml
++++ b/lib/snapshot/libraries.yaml
+@@ -84,6 +84,13 @@ flutter:
+         - "../../../third_party/dart/runtime/lib/profiler.dart"
+         - "../../../third_party/dart/runtime/lib/timeline.dart"
+ 
++    ffi:
++      uri: "../../../third_party/dart/sdk/lib/ffi/ffi.dart"
++      patches:
++        - "../../../third_party/dart/runtime/lib/ffi_dynamic_library_patch.dart"
++        - "../../../third_party/dart/runtime/lib/ffi_native_type_patch.dart"
++        - "../../../third_party/dart/runtime/lib/ffi_patch.dart"
++
+     _http:
+       uri: "../../../third_party/dart/sdk/lib/_http/http.dart"
+ 
diff --git a/tools/patches/flutter-engine/fdfe40ea95d4e91dc9fc0d6e0a1f5215ab7c4b40.flutter.patch b/tools/patches/flutter-engine/fdfe40ea95d4e91dc9fc0d6e0a1f5215ab7c4b40.flutter.patch
new file mode 100644
index 0000000..e0d443e
--- /dev/null
+++ b/tools/patches/flutter-engine/fdfe40ea95d4e91dc9fc0d6e0a1f5215ab7c4b40.flutter.patch
@@ -0,0 +1,12 @@
+diff --git a/analysis_options.yaml b/analysis_options.yaml
+index 0f3f70d3c..97e5a6453 100644
+--- a/analysis_options.yaml
++++ b/analysis_options.yaml
+@@ -120,7 +120,6 @@ linter:
+     # - parameter_assignments # we do this commonly
+     - prefer_adjacent_string_concatenation
+     - prefer_asserts_in_initializer_lists
+-    - prefer_collection_literals
+     - prefer_conditional_assignment
+     - prefer_const_constructors
+     - prefer_const_constructors_in_immutables
diff --git a/tools/patches/flutter-flutter/15f2b92cce916982b7dd8ce658bbf2a465c06ba4.patch b/tools/patches/flutter-flutter/15f2b92cce916982b7dd8ce658bbf2a465c06ba4.patch
new file mode 100644
index 0000000..00aee00
--- /dev/null
+++ b/tools/patches/flutter-flutter/15f2b92cce916982b7dd8ce658bbf2a465c06ba4.patch
@@ -0,0 +1,59 @@
+diff --git a/packages/flutter/lib/src/painting/text_style.dart b/packages/flutter/lib/src/painting/text_style.dart
+index 821cb475b..c85da65b7 100644
+--- a/packages/flutter/lib/src/painting/text_style.dart
++++ b/packages/flutter/lib/src/painting/text_style.dart
+@@ -822,7 +822,7 @@ class TextStyle extends Diagnosticable {
+       fontStyle: fontStyle,
+       fontFamily: fontFamily,
+       fontSize: (fontSize ?? _defaultFontSize) * textScaleFactor,
+-      lineHeight: height,
++      height: height,
+       maxLines: maxLines,
+       ellipsis: ellipsis,
+       locale: locale,
+diff --git a/packages/flutter/lib/src/rendering/error.dart b/packages/flutter/lib/src/rendering/error.dart
+index 03ab64749..a8552b37b 100644
+--- a/packages/flutter/lib/src/rendering/error.dart
++++ b/packages/flutter/lib/src/rendering/error.dart
+@@ -95,7 +95,7 @@ class RenderErrorBox extends RenderBox {
+ 
+   /// The paragraph style to use when painting [RenderErrorBox] objects.
+   static ui.ParagraphStyle paragraphStyle = ui.ParagraphStyle(
+-    lineHeight: 1.0,
++    height: 1.0,
+   );
+ 
+   @override
+diff --git a/packages/flutter/test/painting/text_style_test.dart b/packages/flutter/test/painting/text_style_test.dart
+index 4d65194e9..f26570aec 100644
+--- a/packages/flutter/test/painting/text_style_test.dart
++++ b/packages/flutter/test/painting/text_style_test.dart
+@@ -169,22 +169,22 @@ void main() {
+     expect(ts2.toString(), 'TextStyle(color: Color(0xff00ff00), decoration: unspecified, decorationColor: unspecified, decorationStyle: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, textBaseline: unspecified, fontFamily: unspecified, fontFamilyFallback: unspecified, fontSize: 10.0, letterSpacing: unspecified, wordSpacing: unspecified, height: 100.0x, locale: unspecified, background: unspecified, foreground: unspecified, shadows: unspecified)');
+ 
+     final ui.ParagraphStyle ps2 = s2.getParagraphStyle(textAlign: TextAlign.center);
+-    expect(ps2, equals(ui.ParagraphStyle(textAlign: TextAlign.center, fontWeight: FontWeight.w800, fontSize: 10.0, lineHeight: 100.0)));
+-    expect(ps2.toString(), 'ParagraphStyle(textAlign: TextAlign.center, textDirection: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 10.0, lineHeight: 100.0x, ellipsis: unspecified, locale: unspecified)');
++    expect(ps2, equals(ui.ParagraphStyle(textAlign: TextAlign.center, fontWeight: FontWeight.w800, fontSize: 10.0, height: 100.0)));
++    expect(ps2.toString(), 'ParagraphStyle(textAlign: TextAlign.center, textDirection: unspecified, fontWeight: FontWeight.w800, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 10.0, height: 100.0x, ellipsis: unspecified, locale: unspecified)');
+     final ui.ParagraphStyle ps5 = s5.getParagraphStyle();
+-    expect(ps5, equals(ui.ParagraphStyle(fontWeight: FontWeight.w700, fontSize: 12.0, lineHeight: 123.0)));
+-    expect(ps5.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 12.0, lineHeight: 123.0x, ellipsis: unspecified, locale: unspecified)');
++    expect(ps5, equals(ui.ParagraphStyle(fontWeight: FontWeight.w700, fontSize: 12.0, height: 123.0)));
++    expect(ps5.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: unspecified, fontWeight: FontWeight.w700, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 12.0, height: 123.0x, ellipsis: unspecified, locale: unspecified)');
+   });
+ 
+ 
+   test('TextStyle with text direction', () {
+     final ui.ParagraphStyle ps6 = const TextStyle().getParagraphStyle(textDirection: TextDirection.ltr);
+     expect(ps6, equals(ui.ParagraphStyle(textDirection: TextDirection.ltr, fontSize: 14.0)));
+-    expect(ps6.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.ltr, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, lineHeight: unspecified, ellipsis: unspecified, locale: unspecified)');
++    expect(ps6.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.ltr, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, height: unspecified, ellipsis: unspecified, locale: unspecified)');
+ 
+     final ui.ParagraphStyle ps7 = const TextStyle().getParagraphStyle(textDirection: TextDirection.rtl);
+     expect(ps7, equals(ui.ParagraphStyle(textDirection: TextDirection.rtl, fontSize: 14.0)));
+-    expect(ps7.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.rtl, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, lineHeight: unspecified, ellipsis: unspecified, locale: unspecified)');
++    expect(ps7.toString(), 'ParagraphStyle(textAlign: unspecified, textDirection: TextDirection.rtl, fontWeight: unspecified, fontStyle: unspecified, maxLines: unspecified, fontFamily: unspecified, fontSize: 14.0, height: unspecified, ellipsis: unspecified, locale: unspecified)');
+   });
+ 
+   test('TextStyle using package font', () {
diff --git a/tools/patches/flutter-flutter/3c118b6c3b42c89f4ef18fce4b27e328f2fd754d.patch b/tools/patches/flutter-flutter/3c118b6c3b42c89f4ef18fce4b27e328f2fd754d.patch
new file mode 100644
index 0000000..acde0c1
--- /dev/null
+++ b/tools/patches/flutter-flutter/3c118b6c3b42c89f4ef18fce4b27e328f2fd754d.patch
@@ -0,0 +1,446 @@
+diff --git a/packages/flutter/test/widgets/text_golden_test.dart b/packages/flutter/test/widgets/text_golden_test.dart
+index 4adb60968..fe08d98e4 100644
+--- a/packages/flutter/test/widgets/text_golden_test.dart
++++ b/packages/flutter/test/widgets/text_golden_test.dart
+@@ -1,440 +1 @@
+-// Copyright 2018 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.
+-
+-import 'dart:io' show Platform;
+-
+-import 'package:flutter_test/flutter_test.dart';
+-import 'package:flutter/material.dart';
+-import 'package:flutter/widgets.dart';
+-
+-void main() {
+-  testWidgets('Centered text', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello',
+-              textDirection: TextDirection.ltr,
+-              textAlign: TextAlign.center,
+-              style: TextStyle(color: Color(0xffff0000)),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Centered.png'),
+-    );
+-
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello world how are you today',
+-              textDirection: TextDirection.ltr,
+-              textAlign: TextAlign.center,
+-              style: TextStyle(color: Color(0xffff0000)),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Centered.wrap.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-
+-  testWidgets('Text Foreground', (WidgetTester tester) async {
+-    const Color black = Color(0xFF000000);
+-    const Color red = Color(0xFFFF0000);
+-    const Color blue = Color(0xFF0000FF);
+-    final Shader linearGradient = const LinearGradient(
+-      colors: <Color>[red, blue],
+-    ).createShader(Rect.fromLTWH(0.0, 0.0, 50.0, 20.0));
+-
+-    await tester.pumpWidget(
+-      Align(
+-        alignment: Alignment.topLeft,
+-        child: RepaintBoundary(
+-          child: Text('Hello',
+-            textDirection: TextDirection.ltr,
+-            style: TextStyle(
+-              foreground: Paint()
+-                ..color = black
+-                ..shader = linearGradient
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(RepaintBoundary),
+-      matchesGoldenFile('text_golden.Foreground.gradient.png'),
+-    );
+-
+-    await tester.pumpWidget(
+-      Align(
+-        alignment: Alignment.topLeft,
+-        child: RepaintBoundary(
+-          child: Text('Hello',
+-            textDirection: TextDirection.ltr,
+-            style: TextStyle(
+-              foreground: Paint()
+-                ..color = black
+-                ..style = PaintingStyle.stroke
+-                ..strokeWidth = 2.0
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(RepaintBoundary),
+-      matchesGoldenFile('text_golden.Foreground.stroke.png'),
+-    );
+-
+-    await tester.pumpWidget(
+-      Align(
+-        alignment: Alignment.topLeft,
+-        child: RepaintBoundary(
+-          child: Text('Hello',
+-            textDirection: TextDirection.ltr,
+-            style: TextStyle(
+-              foreground: Paint()
+-                ..color = black
+-                ..style = PaintingStyle.stroke
+-                ..strokeWidth = 2.0
+-                ..shader = linearGradient
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(RepaintBoundary),
+-      matchesGoldenFile('text_golden.Foreground.stroke_and_gradient.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  // TODO(garyq): This test requires an update when the background
+-  // drawing from the beginning of the line bug is fixed. The current
+-  // tested version is not completely correct.
+-  testWidgets('Text Background', (WidgetTester tester) async {
+-    const Color red = Colors.red;
+-    const Color blue = Colors.blue;
+-    const Color translucentGreen = Color(0x5000F000);
+-    const Color translucentDarkRed = Color(0x500F0000);
+-    await tester.pumpWidget(
+-      Align(
+-        alignment: Alignment.topLeft,
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Colors.green,
+-            ),
+-            child: RichText(
+-              textDirection: TextDirection.ltr,
+-              text: TextSpan(
+-                text: 'text1 ',
+-                style: TextStyle(
+-                  color: translucentGreen,
+-                  background: Paint()
+-                    ..color = red.withOpacity(0.5)
+-                ),
+-                children: <TextSpan>[
+-                  TextSpan(
+-                    text: 'text2',
+-                    style: TextStyle(
+-                      color: translucentDarkRed,
+-                      background: Paint()
+-                        ..color = blue.withOpacity(0.5)
+-                    )
+-                  ),
+-                ],
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-
+-    await expectLater(
+-      find.byType(RepaintBoundary),
+-      matchesGoldenFile('text_golden.Background.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Text Fade', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-        MaterialApp(
+-          home: Scaffold(
+-            backgroundColor: Colors.transparent,
+-            body: RepaintBoundary(
+-              child: Center(
+-                child: Container(
+-                  width: 200.0,
+-                  height: 200.0,
+-                  color: Colors.green,
+-                  child: Center(
+-                    child: Container(
+-                      width: 100.0,
+-                      color: Colors.blue,
+-                      child: const Text(
+-                        'Pp PPp PPPp PPPPp PPPPpp PPPPppp PPPPppppp ',
+-                        style: TextStyle(color: Colors.black),
+-                        maxLines: 3,
+-                        overflow: TextOverflow.fade,
+-                      ),
+-                    ),
+-                  ),
+-                ),
+-              ),
+-            ),
+-          )
+-        )
+-    );
+-
+-    await expectLater(
+-      find.byType(RepaintBoundary).first,
+-      matchesGoldenFile('text_golden.Fade.1.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Default Strut text', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello\nLine 2\nLine 3',
+-              textDirection: TextDirection.ltr,
+-              style: TextStyle(),
+-              strutStyle: StrutStyle(),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.StrutDefault.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Strut text 1', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello\nLine2\nLine3',
+-              textDirection: TextDirection.ltr,
+-              style: TextStyle(),
+-              strutStyle: StrutStyle(
+-                height: 1.5,
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Strut.1.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Strut text 2', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello\nLine 2\nLine 3',
+-              textDirection: TextDirection.ltr,
+-              style: TextStyle(),
+-              strutStyle: StrutStyle(
+-                height: 1.5,
+-                fontSize: 14,
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Strut.2.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Strut text rich', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 150.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text.rich(
+-              TextSpan(
+-                text: 'Hello\n',
+-                style: TextStyle(
+-                  color: Colors.red,
+-                  fontSize: 30
+-                ),
+-                children: <TextSpan>[
+-                  TextSpan(
+-                    text: 'Second line!\n',
+-                    style: TextStyle(
+-                      fontSize: 5,
+-                      color: Colors.blue,
+-                    ),
+-                  ),
+-                  TextSpan(
+-                    text: 'Third line!\n',
+-                    style: TextStyle(
+-                      fontSize: 25,
+-                      color: Colors.white,
+-                    ),
+-                  ),
+-                ],
+-              ),
+-              textDirection: TextDirection.ltr,
+-              strutStyle: StrutStyle(
+-                fontSize: 14,
+-                height: 1.1,
+-                leading: 0.1,
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Strut.3.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Strut text font fallback', (WidgetTester tester) async {
+-    // Font Fallback
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text('Hello\nLine 2\nLine 3',
+-              textDirection: TextDirection.ltr,
+-              style: TextStyle(),
+-              strutStyle: StrutStyle(
+-                fontFamily: 'FakeFont 1',
+-                fontFamilyFallback: <String>[
+-                  'FakeFont 2',
+-                  'EvilFont 3',
+-                  'Nice Font 4',
+-                  'ahem'
+-                ],
+-                fontSize: 14,
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.Strut.4.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-
+-  testWidgets('Strut text rich forceStrutHeight', (WidgetTester tester) async {
+-    await tester.pumpWidget(
+-      Center(
+-        child: RepaintBoundary(
+-          child: Container(
+-            width: 200.0,
+-            height: 100.0,
+-            decoration: const BoxDecoration(
+-              color: Color(0xff00ff00),
+-            ),
+-            child: const Text.rich(
+-              TextSpan(
+-                text: 'Hello\n',
+-                style: TextStyle(
+-                  color: Colors.red,
+-                  fontSize: 30
+-                ),
+-                children: <TextSpan>[
+-                  TextSpan(
+-                    text: 'Second line!\n',
+-                    style: TextStyle(
+-                      fontSize: 9,
+-                      color: Colors.blue,
+-                    ),
+-                  ),
+-                  TextSpan(
+-                    text: 'Third line!\n',
+-                    style: TextStyle(
+-                      fontSize: 27,
+-                      color: Colors.white,
+-                    ),
+-                  ),
+-                ],
+-              ),
+-              textDirection: TextDirection.ltr,
+-              strutStyle: StrutStyle(
+-                fontSize: 14,
+-                height: 1.1,
+-                forceStrutHeight: true,
+-              ),
+-            ),
+-          ),
+-        ),
+-      ),
+-    );
+-    await expectLater(
+-      find.byType(Container),
+-      matchesGoldenFile('text_golden.StrutForce.1.png'),
+-    );
+-  }, skip: !Platform.isLinux);
+-}
++void main() { }
diff --git a/tools/patches/flutter-flutter/apply.sh b/tools/patches/flutter-flutter/apply.sh
new file mode 100755
index 0000000..47043f0
--- /dev/null
+++ b/tools/patches/flutter-flutter/apply.sh
@@ -0,0 +1,25 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# This script applies a patch, if available, to the Flutter Framework. Only a
+# patch is applied for the particular engine.version the flutter framework is
+# using.
+#
+# Usage: src/third_party/dart/tools/patches/flutter-flutter/apply.sh
+# (run inside the root of a flutter checkout)
+
+set -e
+
+DIR=$(dirname -- "$(which -- "$0")")
+. $DIR/../utils.sh
+
+ensure_in_checkout_root
+
+pinned_engine_version=$(get_pinned_flutter_engine_version)
+patch=src/third_party/dart/tools/patches/flutter-flutter/${pinned_engine_version}.patch
+if [ -e "$patch" ]; then
+  (cd flutter && git apply ../$patch)
+fi
diff --git a/tools/patches/flutter-flutter/create.sh b/tools/patches/flutter-flutter/create.sh
new file mode 100755
index 0000000..f0f8511
--- /dev/null
+++ b/tools/patches/flutter-flutter/create.sh
@@ -0,0 +1,26 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+#
+# This script produces a patch to the Flutter Framework from the local
+# uncommitted changes in the current engine checkout.
+#
+# Usage: src/third_party/dart/tools/patches/flutter-flutter/create.sh
+# (run inside the root of a flutter engine checkout)
+
+set -e
+
+DIR=$(dirname -- "$(which -- "$0")")
+. $DIR/../utils.sh
+
+ensure_in_checkout_root
+
+pinned_engine_version=$(get_pinned_flutter_engine_version)
+patch=src/third_party/dart/tools/patches/flutter-flutter/$pinned_engine_version.patch
+rm -f src/third_party/dart/tools/patches/flutter-flutter/*.patch
+(cd flutter && git diff) > $patch
+if [ ! -s $patch ]; then
+  rm $patch
+fi
diff --git a/tools/patches/utils.sh b/tools/patches/utils.sh
new file mode 100644
index 0000000..681c707
--- /dev/null
+++ b/tools/patches/utils.sh
@@ -0,0 +1,34 @@
+#!/usr/bin/env bash
+#
+# Copyright (c) 2019, the Dart project authors.  Please see the AUTHORS file
+# for details. All rights reserved. Use of this source code is governed by a
+# BSD-style license that can be found in the LICENSE file.
+
+die() {
+  echo "$0: error: "\
+       "This script must be run from the root of a flutter engine checkout "\
+       "(containing src/flutter/ and flutter/)" >&2
+  exit 1
+}
+
+ensure_in_checkout_root() {
+  set -e
+  if [ ! -e src/third_party/dart ]; then
+    die
+  fi
+
+  if [ ! -e flutter ]; then
+    die
+  fi
+}
+
+get_pinned_dart_version() {
+  pinned_dart_sdk=$(grep -E "'dart_revision':.*" src/flutter/DEPS |
+                    sed -E "s/.*'([^']*)',/\1/")
+  echo -n $pinned_dart_sdk
+}
+
+get_pinned_flutter_engine_version() {
+  pinned_engine_version=$(cat flutter/bin/internal/engine.version | sed 's/[[:space:]]//')
+  echo -n $pinned_engine_version
+}
diff --git a/tools/testing/dart/browser_test.dart b/tools/testing/dart/browser_test.dart
index b4518af..1faea9e 100644
--- a/tools/testing/dart/browser_test.dart
+++ b/tools/testing/dart/browser_test.dart
@@ -198,6 +198,28 @@
     // lines too.
     return lines.join("\\n");
   };
+
+  let pendingCallbacks = 0;
+  let waitForDone = false;
+
+  sdk.dart.addAsyncCallback = function() {
+    pendingCallbacks++;
+    if (!waitForDone) {
+      // When the first callback is added, signal that test_controller.js
+      // should wait until done.
+      waitForDone = true;
+      dartPrint('unittest-suite-wait-for-done');
+    }
+  };
+
+  sdk.dart.removeAsyncCallback = function() {
+    if (--pendingCallbacks <= 0) {
+      // We might be done with async callbacks. Schedule a microtask to check.
+      Promise.resolve().then(function() {
+        if (pendingCallbacks <= 0) dartPrint('unittest-suite-done');
+      });
+    }
+  };
   
   dartMainRunner($testId.$testId.main);
 });
diff --git a/tools/testing/dart/options.dart b/tools/testing/dart/options.dart
index e611925..8593b59 100644
--- a/tools/testing/dart/options.dart
+++ b/tools/testing/dart/options.dart
@@ -3,6 +3,7 @@
 // BSD-style license that can be found in the LICENSE file.
 
 import 'dart:io';
+import 'dart:convert';
 
 import 'package:smith/smith.dart';
 
@@ -146,8 +147,7 @@
     new _Option(
         'named_configuration',
         '''The named test configuration that supplies the values for all
-test options, specifying how tests should be run. Unimplemented
-currently.''',
+test options, specifying how tests should be run.''',
         abbr: 'n',
         hide: true),
     new _Option.bool('checked', 'Run tests in checked mode.'),
@@ -290,7 +290,9 @@
     new _Option.int(
         'test_driver_error_port', 'Port for http test driver server errors.',
         defaultsTo: 0, hide: true),
-    new _Option('test_list', 'File containing a list of tests to be executed'),
+    new _Option('test_list', 'File containing a list of tests to be executed',
+        hide: true),
+    new _Option('tests', 'A newline separated list of tests to be executed'),
     new _Option(
         'builder_tag',
         '''Machine specific options that is not captured by the regular test
@@ -501,9 +503,17 @@
     }
 
     // Fetch list of tests to run, if option is present.
-    if (configuration['test_list'] is String) {
-      configuration['test_list_contents'] =
-          File(configuration['test_list'] as String).readAsLinesSync();
+    var testList = configuration['test_list'];
+    if (testList is String) {
+      configuration['test_list_contents'] = File(testList).readAsLinesSync();
+    }
+
+    var tests = configuration['tests'];
+    if (tests is String) {
+      if (configuration.containsKey('test_list_contents')) {
+        _fail('--tests and --test-list cannot be used together');
+      }
+      configuration['test_list_contents'] = LineSplitter.split(tests).toList();
     }
 
     return _createConfigurations(configuration);
diff --git a/tools/testing/dart/test_controller.js b/tools/testing/dart/test_controller.js
index 9335407..8a82fce 100644
--- a/tools/testing/dart/test_controller.js
+++ b/tools/testing/dart/test_controller.js
@@ -72,13 +72,6 @@
   }
 }
 
-function printToDOM(message) {
-  var pre = document.createElement('pre');
-  pre.appendChild(document.createTextNode(String(message)));
-  document.body.appendChild(pre);
-  document.body.appendChild(document.createTextNode('\n'));
-}
-
 function printToConsole(message) {
   var consoleAvailable = typeof console === 'object';
 
@@ -110,11 +103,6 @@
   notifyDone('FAIL');
 };
 
-// testRunner is provided by content shell.
-// It is not available in browser tests.
-var testRunner = window.testRunner || window.layoutTestController;
-var isContentShell = testRunner;
-
 var waitForDone = false;
 
 var driverWindowCached = false;
@@ -173,13 +161,7 @@
   // If we are not using the browser controller (e.g. in the none-drt
   // configuration), we need to print 'testOutcome' as it is.
   if (isDone && !usingBrowserController()) {
-    if (isContentShell) {
-      // We need this, since test.dart is looking for 'FAIL\n', 'PASS\n' in the
-      // DOM output of content shell.
-      printToDOM(testOutcome);
-    } else {
-      printToConsole('Test outcome: ' + testOutcome);
-    }
+    printToConsole('Test outcome: ' + testOutcome);
   } else if (usingBrowserController()) {
     // To support in browser launching of tests we post back start and result
     // messages to the window.opener.
@@ -201,9 +183,6 @@
           is_done: isDone
         }), '*');
   }
-  if (isDone) {
-    if (testRunner) testRunner.notifyDone();
-  }
 }
 
 function notifyDone(testOutcome) {
@@ -228,13 +207,6 @@
   if (typeof msg != 'string') return;
   if (msg == 'unittest-suite-wait-for-done') {
     waitForDone = true;
-    if (testRunner) {
-      testRunner.startedDartTest = true;
-    }
-  } else if (msg == 'dart-calling-main') {
-    if (testRunner) {
-      testRunner.startedDartTest = true;
-    }
   } else if (msg == 'dart-main-done') {
     if (!waitForDone) {
       notifyDone('PASS');
@@ -251,10 +223,6 @@
   processMessage(e.data);
 }
 
-if (testRunner) {
-  testRunner.dumpAsText();
-  testRunner.waitUntilDone();
-}
 window.addEventListener('message', onReceive, false);
 
 function onLoad(e) {
diff --git a/tools/write_dartdoc_options_file.py b/tools/write_dartdoc_options_file.py
new file mode 100755
index 0000000..44f0278
--- /dev/null
+++ b/tools/write_dartdoc_options_file.py
@@ -0,0 +1,40 @@
+#!/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.
+
+import argparse
+import sys
+import utils
+
+def ParseArgs(args):
+  args = args[1:]
+  parser = argparse.ArgumentParser(
+      description='A script to write a custom dartdoc_options.yaml to a file')
+
+  parser.add_argument('--output', '-o',
+      type=str,
+      required=True,
+      help='File to write')
+
+  return parser.parse_args(args)
+
+
+def Main(argv):
+  args = ParseArgs(argv)
+  # TODO(jcollins-g): switch to version numbers when github has its tags synced
+  revision = utils.GetGitRevision()
+  if revision is None:
+    revision = 'master'
+  output = '''dartdoc:
+  categoryOrder: ["Core", "VM", "Web"]
+  linkToSource:
+    root: '.'
+    uriTemplate: 'https://github.com/dart-lang/sdk/blob/%s/sdk/%%f%%#L%%l%%'
+''' % revision
+  with open(args.output, 'w') as f:
+    f.write(output)
+  return 0
+
+if __name__ == '__main__':
+  sys.exit(Main(sys.argv))